Closed
Bug 43305
Opened 25 years ago
Closed 25 years ago
scrolling code on linux paints twice in some circumstances and leaks elements into linked list
Categories
(Core :: XUL, defect, P3)
Tracking
()
RESOLVED
FIXED
People
(Reporter: blizzard, Assigned: blizzard)
Details
Attachments
(3 files)
34.34 KB,
patch
|
Details | Diff | Splinter Review | |
34.63 KB,
patch
|
Details | Diff | Splinter Review | |
35.17 KB,
patch
|
Details | Diff | Splinter Review |
Right now the scrolling code on linux paints twice when scrolling down in some
circumstances and further investigations reveals that it's leaking elements into
a linked list that's traversed on every scroll. This means that in addition to
double painting the longer you scroll the slower it gets. Bonus.
I've been working on this for the last couple of days. The pain in this bug
runs deep but I have four sheets of paper outlining a plan to fix it The Right
Way.
Assignee | ||
Comment 1•25 years ago
|
||
Comment 2•25 years ago
|
||
Great work, scrolling looks much faster now. But sometimes widgets
on page get position all wrong (bugzilla query page is good test for this).
I Think this is becouse of scroll optimisation:
if (ABS(dx) > width || ABS(dy) > height) {
gdk_superwin_expose_area(superwin, 0, 0, width, height);
return;
}
This doesn't move child windows at all, just repaints main window at right
place.
Here is hacked version that moves child windows too:
if (ABS(dx) > width || ABS(dy) > height) {
/* get list of widgets */
GList *iter, *childs = gdk_window_get_children(superwin->bin_window);
iter=childs;
while(iter)
{
gint x,y;
gdk_window_get_position(iter->data, &x, &y);
gdk_window_move(iter->data, x+dx, y+dy);
iter=iter->next;
}
g_list_free(childs);
gdk_superwin_expose_area(superwin, 0, 0, width, height);
return;
}
Assignee | ||
Comment 3•25 years ago
|
||
Yeah, that will break things now that you mention it. I'll have a look at this
when I get back into town. I don't like the idea of scrolling those widgets
around one at a time by hand. It will give an interesting visual effect on slow
machines.
Assignee | ||
Comment 4•25 years ago
|
||
Assignee | ||
Comment 5•25 years ago
|
||
Ok, the patch that I've uploaded doesn't have the shortcut but it does clip
paints to the width or height of the window. Should have the best of all worlds
here. Tax free child window movement and clipped painting.
Status: NEW → ASSIGNED
Assignee | ||
Comment 6•25 years ago
|
||
So, I'm pretty happy with this code. I'd like to get a review on it if anyone
is up to it.
Comment 7•25 years ago
|
||
When moving the widgets one-by-one the "visual effects" could be removed by
mapping an unpaintable window on top and unmapping it when done. Probably not
worth it?
What happens to this mechanism with large (>32kpx) pages? Widgets probably have
problems...
Assignee | ||
Comment 8•25 years ago
|
||
I imagine there are problems with > 32 bit scrolls. I'm not trying to solve
that here. That's another problem entirely.
Assignee | ||
Comment 9•25 years ago
|
||
bryner has reviewed this. I'm still looking for other people to review and test
it.
Comment 10•25 years ago
|
||
I tested it and seems to work fine (and indeed is faster).
Still looking at the code...
Assignee | ||
Comment 11•25 years ago
|
||
Let me know. Looking for multiple reviews on this.
Comment 12•25 years ago
|
||
Ok, run this with couple of printfs and paintflash on, found two
things:
1. linked list can grow quite large when scrolling just with up/down
arrows. This is becouse in every expose there is stuff in list and goto jumps
over list cleaning. This is easy to fix by moving label 'end:' just before
list cleaning block.
2. Other thing that i notised that when scrolling down more than one page,
antiexpose events doesnt match with expose. I didnt figure out why, i just
tryed other values and come to this:
/* if scrolling down ( dy < 0 ) moving window up so expose area at
the bottom of the window. Clip the exposed area to the height of
the window or the offset, whichever is smaller. */
if (dy < 0) {
- gdk_superwin_expose_area(superwin, 0, height - ABS(dy),
+ gdk_superwin_expose_area(superwin, 0, MAX(0, height - ABS(dy)),
width, MIN(height, ABS(dy)));
/* If we've exposed this area add an antiexpose for it. When the
window was moved up, the expose will be offset by ABS(dy). */
gdk_superwin_add_antiexpose(superwin, move_serial,
0,
- height, /* actually, height-ABS(dy)+ABS(dy). */
+ MAX(height, ABS(dy)),
width, MIN(height, ABS(dy)));
}
Assignee | ||
Comment 13•25 years ago
|
||
For 1, we can definitely move end end: label before the cleanup. I've added
that.
As for 2, good catch. The area we want to expose doesn't include any areas that
are outside of the visible window where dy is < 0:
MAX(0, height - ABS(dy))
otherwise the y for the start of the expose is < 0 and we paint a lot more than
what we want to.
The antiexpose that we want to generate will be offset by either the height, or
however much we are moving the window
MAX(height, ABS(dy))
since that's what the X expose event will look like.
I've added this for the x < 0 case, too. Thanks, again! I'll attach a new
patch here for testing.
Assignee | ||
Comment 14•25 years ago
|
||
Assignee | ||
Comment 15•25 years ago
|
||
So, how does everyone feel about this? I'd like to get this into the tree to
plug the leak. I don't know of any outstanding issues with the code.
Keywords: review
Assignee | ||
Comment 16•25 years ago
|
||
I have an r=imot on this.
Comment 17•25 years ago
|
||
r=pavlov
Assignee | ||
Updated•25 years ago
|
Assignee | ||
Comment 18•25 years ago
|
||
a=brendan on this
Comment 19•25 years ago
|
||
There might be small speedup by emptying mouse motion events from
x queue when scrolling. I tryed this and scrolling looks better,
with long tables scrolling it's not coming like half second behind
mouse.
I added this code to end of gdk_superwin_scroll:
XSync(GDK_DISPLAY(), FALSE);
while (XCheckTypedEvent(GDK_DISPLAY(), MotionNotify, &remove_event)
== TRUE);
(and added XEvent remove_event; at start)
Comment 20•25 years ago
|
||
You should use the last motion event, not the first one.
One thing that you should try: XSync only if there are two MotionNotify events
in the queue.
Assignee | ||
Comment 21•25 years ago
|
||
And only on the window in question. You don't want the potential to start
eating events for windows you don't own.
Also, I'm concerned about doing this from the scroll code and not doing anything
with them. There's a potential of lossage of information. We do compress
motion notify events somewhere else. You should look there for an example.
Comment 22•25 years ago
|
||
I agree, it's best to compress elsewhere. I misread the first comment.
At the very least, the last events needs to be put back in the queue.
Assignee | ||
Comment 23•25 years ago
|
||
To see how we do it elsewhere have a look at:
http://lxr.mozilla.org/seamonkey/ident?i=HandleGDKEvent
Assignee | ||
Comment 24•25 years ago
|
||
Checked in.
Status: ASSIGNED → RESOLVED
Closed: 25 years ago
Resolution: --- → FIXED
Comment 25•25 years ago
|
||
Sorry i missed that this compression is already in gdkhanleevent.
But it looks like its not compressing all events, somehow when scrolling hard
it doesnt get in there. But if you add that XSync(GDK_DISPLAY(), FALSE);
at end of gdk_superwin_scroll() it starts to work. This makes scrolling
even more better looking. You can see that more events is compressed by putting
printf at nsWindow::HandleGDKEvent:
while (XCheckWindowEvent(GDK_DISPLAY(),
GDK_WINDOW_XWINDOW(mSuperWin->bin_window),
ButtonMotionMask, &xevent)) {
synthEvent = PR_TRUE;
+ printf("take out one event\n");
}
Good testpage for this is some long slashdot article, like:
http://slashdot.org/article.pl?sid=00/07/05/167248&mode=thread&threshold=1
Without XSync, no eventcompressing is happening when scrolling page and it
scrolls slighly after mouse, with XSync some events are compressed and
scrolling looks faster.
Assignee | ||
Comment 26•25 years ago
|
||
It does look a bit better with that in there, yes. I'll check that in.
You need to log in
before you can comment on or make changes to this bug.
Description
•