Opened 15 years ago
Last modified 5 years ago
#5468 new bug
Draw() can overtake FrameResized()
Reported by: | bonefish | Owned by: | axeld |
---|---|---|---|
Priority: | normal | Milestone: | R1 |
Component: | Kits/Interface Kit | Version: | R1/Development |
Keywords: | Cc: | X512 | |
Blocked By: | Blocking: | ||
Platform: | All |
Description
After resizing a view Draw() can be invoked with the new view bounds in effect (and a respective update rect) before the view's FrameResized() has been called.
This led to #2851, which has been fixed in hrev35587 by no longer relying on FrameResized() to be called before Draw().
As a simple test case the Terminal can be used. Insert the following at the beginning of Draw():
{ int32 columns = (Bounds().IntegerWidth() + 1) / fFontWidth; int32 rows = (Bounds().IntegerHeight() + 1) / fFontHeight; if (columns != fColumns || rows != fRows) debugger("Draw(): view size changed without FrameResized()"); }
The debugger() call is triggered easily when resizing the Terminal window. Resizing in individual steps doesn't trigger it.
Attachments (1)
Change History (8)
comment:1 by , 8 years ago
comment:2 by , 6 years ago
Relevant commits list log: https://www.freelists.org/post/haiku-commits/haiku-hrev45852-in-src-appsdeskcalc-kitsshared,1
Test program is here: http://pastebin.com/hb3fne5V
The view starts off green. When you resize the view turns red. keep resizing and eventually it will turn blue, this means you've triggered the bug. more details below:
App server occasionally drops the Draw() call which causes the view to not be drawn correctly. Actually this happens on BeOS too but much more frequently on Haiku. I'm not sure if this is intentional or not and I'm not sure how to trigger the bug, it just seems to happen at random. It's not like if I resize the window quickly it happens more often, it just occasionally doesn't call Draw() and suddenly my red window turns blue.
comment:3 by , 6 years ago
After running the program linked in last comment on a more recent Haiku things have improved since 2013 (5 years ago today). Messages do not get dropped and we consistently call FrameResized() then Draw() however, the bug is still every bit as present and not even hard to trigger.
comment:4 by , 5 years ago
Cc: | added |
---|
Cc X512: Did your recent changes affect this, or is it still an issue?
comment:6 by , 5 years ago
by , 5 years ago
Attachment: | MinApp.cpp added |
---|
Program to reproduce. "Size don't match" in stdout indicate bug.
comment:7 by , 5 years ago
I'm afraid that this bug cannot be fixed without changing how messages work unfortunately. There's no way for us to guarantee that a Draw() call will happen after a FrameResized() call without implementing a transaction. Most of the time it works but without a guarantee that messages will arrive in a certain order there are race conditions that pop-up now and then. This is a design flaw and was as much a problem on BeOS as it is on Haiku fundamentally. I've also observed that sliders sometimes don't send the message (or the receiver never get it.) For example in Deskbar preferences when you click to change the slider value, occasionally the icons don't resize and we end up in an invalid state. This is not a fault of the Deskbar code but is a bug somewhere deeper in the messaging system. I'm not sure if that bug is related to this one or not.
The view bounds are updated synchronously, while
FrameResized()
(andDraw()
) are called asynchronously via messages. The app_server can issue a drawing update at any time, so the behavior is actually to be expected.Of course, it would be possible to change the implementation in a way that
FrameResized()
is always called beforeDraw()
. I'm just not sure if it's worth the hassle. Opinions welcome. In any case, if the current behavior is not changed, it should at least be documented.