Discussion:
[zathura] Making page refreshes less prone to breaking
Abdó Roig-Maranges
2013-10-22 16:15:04 UTC
Permalink
Hi,

Tinkering with zathura I've been annoyed several times by the fragility of the
page updates. They are prone to race conditions, due to the asynchronous nature
of GTK. For instance, since the last GTK3 update zathura does not always refresh
the page correctly when coming out of index mode.

I think the problem is that right now zathura's mechanism for keeping track of
the current page and position relies on GTK stuff (the adjustments) for storing
the position parameters, and uses them on page jumps, etc.

I think we should keep data, including details on its presentation like the
current page and position, separate from the GTK stuff. Then talk to gtk through
signals, and let it be as asynchronous as he wants. We shouldn't rely on gtk
adjustments as data containers.

I have some partially working code in that direction, which goes roughly as
follows:

1. Store data related to the document display, like positions, pages-per-row,
etc. into the document struct, so the document can compute whatever he needs
regarding the page layout by itself, without using GTK.

2. make the adjustment_value_changed callbacks update the data in the document
object from the GTK adjustments, to keep them in sync when the adjustment is
changed by the user.

3. Make the functions page_set and position_set compute and save the new
position into the document struct. Then trigger a custom signal
'refresh-view'.

4. Add a callback to 'refresh-view' that updates the GTK adjustments from the
position in the document struct. This makes all position_set calls delayed,
avoiding annoying races, for instance when coming out of index mode.

5. Of course, every time zathura needs a position, should get it from the
document struct, and never from GTK.

What we gain with this, is that all page or position changes are made
asynchronous (i.e. go through a signal) yet the new position is immediately
available to zathura through data in the document struct. In particular we would
no longer need to keep both, position_set and position_set_delayed, as one
version would fullfil both needs.

On the other hand, this proposed change relies on a predictable page positioning
algorithm, so we can compute it without GTK. Currently this is easy: a grid of
equal sized cells.

Ok, as this is a rather big change, I thought it would be a good idea to ask for
feedback at this point...

Abd?.
Abdó Roig-Maranges
2013-10-26 16:45:21 UTC
Permalink
Hi,

I got this in a stable state. I tried to attach the patches on a previous mail,
but it was too big and got held up for moderation. So I've uploaded it on
github.

https://github.com/aroig/zathura

What I have done is mainly restructure the code to cleanly separate document
data from GTK stuff.

It may seem like a lot of work for almost nothing, but I believe it is worth it
in terms of making the code more structured (so easier to hack), and more
robust.

There is one remaining issue, I've not been able to fix, which also happens with
current develop branch under GTK3. I'll report that in the bug tracker.

Abd?.
Post by Abdó Roig-Maranges
Hi,
Tinkering with zathura I've been annoyed several times by the fragility of the
page updates. They are prone to race conditions, due to the asynchronous nature
of GTK. For instance, since the last GTK3 update zathura does not always refresh
the page correctly when coming out of index mode.
I think the problem is that right now zathura's mechanism for keeping track of
the current page and position relies on GTK stuff (the adjustments) for storing
the position parameters, and uses them on page jumps, etc.
I think we should keep data, including details on its presentation like the
current page and position, separate from the GTK stuff. Then talk to gtk through
signals, and let it be as asynchronous as he wants. We shouldn't rely on gtk
adjustments as data containers.
I have some partially working code in that direction, which goes roughly as
1. Store data related to the document display, like positions, pages-per-row,
etc. into the document struct, so the document can compute whatever he needs
regarding the page layout by itself, without using GTK.
2. make the adjustment_value_changed callbacks update the data in the document
object from the GTK adjustments, to keep them in sync when the adjustment is
changed by the user.
3. Make the functions page_set and position_set compute and save the new
position into the document struct. Then trigger a custom signal
'refresh-view'.
4. Add a callback to 'refresh-view' that updates the GTK adjustments from the
position in the document struct. This makes all position_set calls delayed,
avoiding annoying races, for instance when coming out of index mode.
5. Of course, every time zathura needs a position, should get it from the
document struct, and never from GTK.
What we gain with this, is that all page or position changes are made
asynchronous (i.e. go through a signal) yet the new position is immediately
available to zathura through data in the document struct. In particular we would
no longer need to keep both, position_set and position_set_delayed, as one
version would fullfil both needs.
On the other hand, this proposed change relies on a predictable page positioning
algorithm, so we can compute it without GTK. Currently this is easy: a grid of
equal sized cells.
Ok, as this is a rather big change, I thought it would be a good idea to ask for
feedback at this point...
Abd?.
Sebastian Ramacher
2013-10-26 17:11:42 UTC
Permalink
Hi,

sorry that I haven't yet found the time to reply to your mail.
Post by Abdó Roig-Maranges
I got this in a stable state. I tried to attach the patches on a previous mail,
but it was too big and got held up for moderation. So I've uploaded it on
github.
https://github.com/aroig/zathura
Thank you, I'll check it out.

Regards
--
Sebastian Ramacher
Sebastian Ramacher
2013-10-27 00:48:26 UTC
Permalink
Post by Abdó Roig-Maranges
https://github.com/aroig/zathura
I've played a bit with the new code and enjoy it so far. I'll push it as
feature/redo-page-refresh to the git repository at pwmt.org until I've
had more time to look at the code in more detail.

Cheers
--
Sebastian Ramacher
Sebastian Ramacher
2013-10-30 02:40:49 UTC
Permalink
Post by Sebastian Ramacher
Post by Abdó Roig-Maranges
https://github.com/aroig/zathura
I've played a bit with the new code and enjoy it so far. I'll push it as
feature/redo-page-refresh to the git repository at pwmt.org until I've
had more time to look at the code in more detail.
Maybe that's a bug that I haven't noticed so far or is introduced by
these changes: using the index to jump to some page, I always see the
first page. Moving around a little bit or zooming in/out displays the
correct page again.

Regards
--
Sebastian Ramacher
Abdó Roig-Maranges
2013-10-30 07:39:59 UTC
Permalink
Hi,
Post by Sebastian Ramacher
Maybe that's a bug that I haven't noticed so far or is introduced by
these changes: using the index to jump to some page, I always see the
first page. Moving around a little bit or zooming in/out displays the
correct page again.
hmm... I can't reproduce this on the redo-page-refresh branch, neither on GTK2
nor GTK3.

It did happen with current develop quite a lot. I think it started happening
after the upgrade to GTK 3.10, but I wouldn't bet on it.

The problem there was that when setting the vertical position coming out of the
index mode, the adjustment still was thinking it was "adjusting the index", it
had the wrong bounds. In fact, this is one of the racy things that made me
finish these patches! If I missed something, I'd like very much to fix it!

I'm using the redo-page-refresh branch for my work related pdf reading, so it is
having some testing. So far I didn't find any issues, except for the one I
reported on the bug tracker regarding scale on the first page for a new document
on gtk3.

Abd?.
Sebastian Ramacher
2013-10-30 17:54:54 UTC
Permalink
Post by Abdó Roig-Maranges
Hi,
Post by Sebastian Ramacher
Maybe that's a bug that I haven't noticed so far or is introduced by
these changes: using the index to jump to some page, I always see the
first page. Moving around a little bit or zooming in/out displays the
correct page again.
hmm... I can't reproduce this on the redo-page-refresh branch, neither on GTK2
nor GTK3.
It did happen with current develop quite a lot. I think it started happening
after the upgrade to GTK 3.10, but I wouldn't bet on it.
The problem there was that when setting the vertical position coming out of the
index mode, the adjustment still was thinking it was "adjusting the index", it
had the wrong bounds. In fact, this is one of the racy things that made me
finish these patches! If I missed something, I'd like very much to fix it!
I'm using the redo-page-refresh branch for my work related pdf reading, so it is
having some testing. So far I didn't find any issues, except for the one I
reported on the bug tracker regarding scale on the first page for a new document
on gtk3.
Maybe I was on the wrong branch. I can't reproduce it at the moment.
I'll let you know if it happens again.

Regards
--
Sebastian Ramacher
Abdó Roig-Maranges
2013-10-30 21:13:19 UTC
Permalink
Hi,
So far I didn't find any issues, except for the one I reported on the bug
tracker regarding scale on the first page for a new document on gtk3.
And right after that I found a little problem with link evaluation for some
pdf's (the ones without page coordinates for the target). I attach a patch for
the redo-page-refresh branch.

I think this is not related to what you reported, though.

Abd?.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: fix-links.patch
Type: text/x-diff
Size: 849 bytes
Desc: fix links
URL: <http://lists.pwmt.org/archive/zathura/attachments/20131030/a897d2ef/attachment.patch>
Sebastian Ramacher
2013-10-31 03:37:32 UTC
Permalink
Applied this one and I've also gone ahead and merge the branch back into
develop.

Regards
--
Sebastian Ramacher
Abdó Roig-Maranges
2013-10-26 16:25:45 UTC
Permalink
Hi,

I got this in a stable state, so I attach the patches.

What I have done is mainly restructure the code to cleanly separate document
data from GTK stuff.

It may seem like a lot of work for almost nothing, but I believe it is worth it
in terms of making the code more structured (so easier to hack), and more
robust.

There is one remaining issue, I've not been able to fix, which also happens with
current develop branch under GTK3. I'll report that in the bug tracker.

I have split the long chain of commits into several patches with a common
theme. Here is a short description of the patches, in the order they should be
applied.

* layout.patch:
Make the document object aware of page layout data, like
pages-per-row, etc. And use it to simplify some existing functions.

* position.patch:
Make the document object know about document position and viewport size. Then
change the mechanism zathura updates page positions.

- page_set and position_set only change data in the document object and
trigger a refresh-view signal

- the adjustment callbacks do not change position, only copy data from the
document object to the GtkAdjustment back and forth.

* use-position.patch:
Make use of the new position change mechanism to get rid of explicit calls to
GTK code in various places. Whenever zathura wants a new page or position, it
should do it through page_set or position_set, and query the document object
for data. Never use GTK directly.

* cleanup.patch:
Remove things rendered obsolete by the above chain of commits.

Abd?.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: layout.patch
Type: text/x-diff
Size: 32389 bytes
Desc: layout
URL: <http://lists.pwmt.org/archive/zathura/attachments/20131026/d7e5e7de/attachment-0004.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: position.patch
Type: text/x-diff
Size: 50754 bytes
Desc: position
URL: <http://lists.pwmt.org/archive/zathura/attachments/20131026/d7e5e7de/attachment-0005.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: use-position.patch
Type: text/x-diff
Size: 29550 bytes
Desc: use position
URL: <http://lists.pwmt.org/archive/zathura/attachments/20131026/d7e5e7de/attachment-0006.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cleanup.patch
Type: text/x-diff
Size: 17062 bytes
Desc: cleanup
URL: <http://lists.pwmt.org/archive/zathura/attachments/20131026/d7e5e7de/attachment-0007.patch>
-------------- next part --------------
Post by Abdó Roig-Maranges
Hi,
Tinkering with zathura I've been annoyed several times by the fragility of the
page updates. They are prone to race conditions, due to the asynchronous nature
of GTK. For instance, since the last GTK3 update zathura does not always refresh
the page correctly when coming out of index mode.
I think the problem is that right now zathura's mechanism for keeping track of
the current page and position relies on GTK stuff (the adjustments) for storing
the position parameters, and uses them on page jumps, etc.
I think we should keep data, including details on its presentation like the
current page and position, separate from the GTK stuff. Then talk to gtk through
signals, and let it be as asynchronous as he wants. We shouldn't rely on gtk
adjustments as data containers.
I have some partially working code in that direction, which goes roughly as
1. Store data related to the document display, like positions, pages-per-row,
etc. into the document struct, so the document can compute whatever he needs
regarding the page layout by itself, without using GTK.
2. make the adjustment_value_changed callbacks update the data in the document
object from the GTK adjustments, to keep them in sync when the adjustment is
changed by the user.
3. Make the functions page_set and position_set compute and save the new
position into the document struct. Then trigger a custom signal
'refresh-view'.
4. Add a callback to 'refresh-view' that updates the GTK adjustments from the
position in the document struct. This makes all position_set calls delayed,
avoiding annoying races, for instance when coming out of index mode.
5. Of course, every time zathura needs a position, should get it from the
document struct, and never from GTK.
What we gain with this, is that all page or position changes are made
asynchronous (i.e. go through a signal) yet the new position is immediately
available to zathura through data in the document struct. In particular we would
no longer need to keep both, position_set and position_set_delayed, as one
version would fullfil both needs.
On the other hand, this proposed change relies on a predictable page positioning
algorithm, so we can compute it without GTK. Currently this is easy: a grid of
equal sized cells.
Ok, as this is a rather big change, I thought it would be a good idea to ask for
feedback at this point...
Abd?.
Loading...