Discussion:
wxEVT_SIZE handler called multiple times per resize?
Paarvai Naai
2008-12-05 19:18:01 UTC
Permalink
Hi,

I noticed something very strange with when hooking the wxEVT_SIZE
event in one of my custom controls. Specifically, for every discrete
window resize, I find that the wxEVT_SIZE seems to be issued 4(!)
times, thereby calling my event handler 4 times. This seems very
inefficient. In an effort to simplify things, I decided to test the
wxEVT_SIZE event on a simple wxApp.

I created a wxApp that instantiates a wxFrame which in turn creates a
wxPanel. The wxEVT_SIZE event is hooked as follows:

panel->Connect(ID_PANEL, wxEVT_SIZE,
wxSizeEventHandler(SizeTestFrame::OnSize), NULL, this);

The OnSize function is written as:

void SizeTestFrame::OnSize( wxSizeEvent& event )
{
static int count = 0;
printf("OnSize: %p %d\n", event.GetEventObject(), count++);
//event.Skip();
}

Now when I launch the app, I get 3 OnSize calls upon the initial
showing of the main frame. All show the same value from
event.GetEventObject() (presumably the panel's pointer). I am using
wxGTK 2.8.9. To resize the window, I right click on the titlebar and
select the resize option. This way I can use discrete events on my
keyboard to resize the window. Each resize results in 3 more calls to
OnSize.

Is this is a known issue? Is there some way I can squelch these extra
wxEVT_SIZE events?

Thanks,
Paarvai
Vadim Zeitlin
2008-12-05 19:48:07 UTC
Permalink
On Fri, 5 Dec 2008 11:18:01 -0800 Paarvai Naai <***@gmail.com> wrote:

PN> Is this is a known issue? Is there some way I can squelch these extra
PN> wxEVT_SIZE events?

I don't have time to test this right now myself unfortunately but it would
help to see from where each of these events is generated (i.e. the stack
trace from gdb when it stops on the breakpoint at your size event handler).
This would allow to see if it's GTK+ or wxGTK which generates duplicated
events.

Also, are they really exactly the same? I.e. do they all carry the same
size?

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Paarvai Naai
2008-12-05 21:28:35 UTC
Permalink
Hi Vadim,
Post by Vadim Zeitlin
I don't have time to test this right now myself unfortunately but it would
help to see from where each of these events is generated (i.e. the stack
trace from gdb when it stops on the breakpoint at your size event handler).
This would allow to see if it's GTK+ or wxGTK which generates duplicated
events.
I used a breakpoint to trap the handler when I resize the window
manually after creation. The stack traces look slightly different for
each of the 3 times my handler is called. Here are snippets of the
stack traces:

Call #1
#11 0x00d20666 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#12 0x00752545 in wxFrame::GtkOnSize () from /usr/lib/libwx_gtk2u_core-2.8.so.0
#13 0x006ed7ab in wxTopLevelWindowGTK::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#14 0x007bff4d in wxFrameBase::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#15 0x00751b9e in wxFrame::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#16 0x00786635 in wxAppBase::SendIdleEvents ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#17 0x0078699b in wxAppBase::ProcessIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#18 0x006c7886 in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0

Call #2:
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f41ab in wxWindow::GTKProcessEvent ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x006f80bf in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0
#7 0x00a21a79 in g_cclosure_marshal_VOID__BOXED ()
from /lib/libgobject-2.0.so.0

Call #3:
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f7ad7 in wxWindow::DoSetSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x0081508c in wxTopLevelWindowBase::DoLayout ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#7 0x00815c4d in wxTopLevelWindowBase::OnSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#8 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#9 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#10 0x00d204fd in wxEventHashTable::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#11 0x00d20666 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#12 0x006f41ab in wxWindow::GTKProcessEvent ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#13 0x006f80bf in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0


Where Call #3 looks like it is occurring because the top level frame
is resized which then causes it to call Layout on its child frame (the
panel). Regardless, this is non-intuitive. Not sure how to explain
the redundancy of Call #1 and Call #2 since I am not intimately
familiar with the GTK idle loop and GTK event triggering.
Post by Vadim Zeitlin
Also, are they really exactly the same? I.e. do they all carry the same
size?
Yes, they all carry the same size. This is what triggered my
suspicion at the very outset.

Thanks,
Paarvai
Paarvai Naai
2008-12-05 21:57:01 UTC
Permalink
Looking into this a little more, I realized I didn't paste enough of
the calls to be as useful. Here are each of the calls again, along
with some theories on what is happening.

Call #1:
#0 SizeTestFrame::OnSize (this=0x8d748c8, event=@0xbf87a590)
at sizetestframe.cpp:168
#1 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#2 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#3 0x00d20584 in wxEvtHandler::SearchDynamicEventTable ()
from /usr/lib/libwx_baseu-2.8.so.0
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f7ad7 in wxWindow::DoSetSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x0081508c in wxTopLevelWindowBase::DoLayout ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#7 0x00815c4d in wxTopLevelWindowBase::OnSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#8 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#9 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#10 0x00d204fd in wxEventHashTable::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#11 0x00d20666 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#12 0x00752545 in wxFrame::GtkOnSize () from /usr/lib/libwx_gtk2u_core-2.8.so.0
#13 0x006ed7ab in wxTopLevelWindowGTK::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#14 0x007bff4d in wxFrameBase::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#15 0x00751b9e in wxFrame::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#16 0x00786635 in wxAppBase::SendIdleEvents ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#17 0x0078699b in wxAppBase::ProcessIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#18 0x006c7886 in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0

It appears that the app is resized and the frame gets notification
through the idle loop. Then the frame resizes its child panel since
the panel is the only child and the frame wants to fill its entire
client region with the panel. The call to DoSetSize on the panel
generates a wxEVT_SIZE event.

Next, Call #2 happens:
#0 SizeTestFrame::OnSize (this=0x8d748c8, event=@0xbf878670)
at sizetestframe.cpp:168
#1 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#2 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#3 0x00d20584 in wxEvtHandler::SearchDynamicEventTable ()
from /usr/lib/libwx_baseu-2.8.so.0
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f41ab in wxWindow::GTKProcessEvent ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x006f80bf in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0

This call seems to be generated by GTK for the panel itself because
the panel's size was changed due to Call #1.

Finally, we have Call #3:
#0 SizeTestFrame::OnSize (this=0x8d748c8, event=@0xbf879080)
at sizetestframe.cpp:168
#1 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#2 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#3 0x00d20584 in wxEvtHandler::SearchDynamicEventTable ()
from /usr/lib/libwx_baseu-2.8.so.0
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f7ad7 in wxWindow::DoSetSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x0081508c in wxTopLevelWindowBase::DoLayout ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#7 0x00815c4d in wxTopLevelWindowBase::OnSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#8 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#9 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#10 0x00d204fd in wxEventHashTable::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#11 0x00d20666 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#12 0x006f41ab in wxWindow::GTKProcessEvent ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#13 0x006f80bf in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0

I'm not entirely sure, but it seems that this call is generated by GTK
because the frame has changed size (during the course of Call #1).
This again causes the DoSetSize to be called on the panel via
DoLayout. The DoSetSize then causes another wxEVT_SIZE to be emitted.
My guess is that the only thing that saves us from going into an
infinite loop is that the DoSetSize on the panel during Call #3 does
not generate a subsequent internal event by GTK for the panel since
the panel's size is simply set to the same size as was set in Call #1.

Please confirm my logic above. On face, it seems that there is a
problem here and it should somehow be fixed.

Thanks,
Paarvai
Paarvai Naai
2008-12-09 00:15:56 UTC
Permalink
Hi,

Was the information I provided below useful? I'd like to do as much a
I can to assist in figuring out why OnSize is called so many times
with wxGTK. Please let me know if there is any more information I can
quickly collect that might be useful.

Thanks again,
Paarvai
Post by Paarvai Naai
Looking into this a little more, I realized I didn't paste enough of
the calls to be as useful. Here are each of the calls again, along
with some theories on what is happening.
at sizetestframe.cpp:168
#1 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#2 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#3 0x00d20584 in wxEvtHandler::SearchDynamicEventTable ()
from /usr/lib/libwx_baseu-2.8.so.0
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f7ad7 in wxWindow::DoSetSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x0081508c in wxTopLevelWindowBase::DoLayout ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#7 0x00815c4d in wxTopLevelWindowBase::OnSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#8 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#9 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#10 0x00d204fd in wxEventHashTable::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#11 0x00d20666 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#12 0x00752545 in wxFrame::GtkOnSize () from /usr/lib/libwx_gtk2u_core-2.8.so.0
#13 0x006ed7ab in wxTopLevelWindowGTK::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#14 0x007bff4d in wxFrameBase::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#15 0x00751b9e in wxFrame::OnInternalIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#16 0x00786635 in wxAppBase::SendIdleEvents ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#17 0x0078699b in wxAppBase::ProcessIdle ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#18 0x006c7886 in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0
It appears that the app is resized and the frame gets notification
through the idle loop. Then the frame resizes its child panel since
the panel is the only child and the frame wants to fill its entire
client region with the panel. The call to DoSetSize on the panel
generates a wxEVT_SIZE event.
at sizetestframe.cpp:168
#1 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#2 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#3 0x00d20584 in wxEvtHandler::SearchDynamicEventTable ()
from /usr/lib/libwx_baseu-2.8.so.0
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f41ab in wxWindow::GTKProcessEvent ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x006f80bf in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0
This call seems to be generated by GTK for the panel itself because
the panel's size was changed due to Call #1.
at sizetestframe.cpp:168
#1 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#2 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#3 0x00d20584 in wxEvtHandler::SearchDynamicEventTable ()
from /usr/lib/libwx_baseu-2.8.so.0
#4 0x00d20643 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#5 0x006f7ad7 in wxWindow::DoSetSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#6 0x0081508c in wxTopLevelWindowBase::DoLayout ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#7 0x00815c4d in wxTopLevelWindowBase::OnSize ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#8 0x00c73765 in wxAppConsole::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#9 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
from /usr/lib/libwx_baseu-2.8.so.0
#10 0x00d204fd in wxEventHashTable::HandleEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#11 0x00d20666 in wxEvtHandler::ProcessEvent ()
from /usr/lib/libwx_baseu-2.8.so.0
#12 0x006f41ab in wxWindow::GTKProcessEvent ()
from /usr/lib/libwx_gtk2u_core-2.8.so.0
#13 0x006f80bf in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0
I'm not entirely sure, but it seems that this call is generated by GTK
because the frame has changed size (during the course of Call #1).
This again causes the DoSetSize to be called on the panel via
DoLayout. The DoSetSize then causes another wxEVT_SIZE to be emitted.
My guess is that the only thing that saves us from going into an
infinite loop is that the DoSetSize on the panel during Call #3 does
not generate a subsequent internal event by GTK for the panel since
the panel's size is simply set to the same size as was set in Call #1.
Please confirm my logic above. On face, it seems that there is a
problem here and it should somehow be fixed.
Thanks,
Paarvai
Vadim Zeitlin
2008-12-09 00:18:13 UTC
Permalink
On Mon, 8 Dec 2008 16:15:56 -0800 Paarvai Naai <***@gmail.com> wrote:

PN> Was the information I provided below useful?

Yes, it was, but unfortunately I simply didn't have time to look at it in
details, sorry. I keep this in my "TODO" folder but I don't know when will
I be able to look at it. Maybe it would be better if you created a report
on the Trac and attach all this information to it, at least it won't get
lost like this.

Thanks,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Vadim Zeitlin
2009-01-17 12:30:42 UTC
Permalink
On Fri, 5 Dec 2008 13:57:01 -0800 Paarvai Naai <***@gmail.com> wrote:

[sorry for the delay with reply, I hoped to find time to debug this myself
but as I still didn't I wanted to at least follow up here]

PN> Looking into this a little more, I realized I didn't paste enough of
PN> the calls to be as useful. Here are each of the calls again, along
PN> with some theories on what is happening.
PN>
PN> Call #1:
PN> #0 SizeTestFrame::OnSize (this=0x8d748c8, event=@0xbf87a590)
PN> at sizetestframe.cpp:168

Just as a note to whoever reads this thread later (including myself):
SizeTestFrame actually is a child window and not a wxFrame, right?

PN> It appears that the app is resized and the frame gets notification
PN> through the idle loop. Then the frame resizes its child panel since
PN> the panel is the only child and the frame wants to fill its entire
PN> client region with the panel. The call to DoSetSize on the panel
PN> generates a wxEVT_SIZE event.
PN>
PN> Next, Call #2 happens:
PN> #0 SizeTestFrame::OnSize (this=0x8d748c8, event=@0xbf878670)
PN> at sizetestframe.cpp:168
PN> #1 0x00c73765 in wxAppConsole::HandleEvent ()
PN> from /usr/lib/libwx_baseu-2.8.so.0
PN> #2 0x00d203af in wxEvtHandler::ProcessEventIfMatches ()
PN> from /usr/lib/libwx_baseu-2.8.so.0
PN> #3 0x00d20584 in wxEvtHandler::SearchDynamicEventTable ()
PN> from /usr/lib/libwx_baseu-2.8.so.0
PN> #4 0x00d20643 in wxEvtHandler::ProcessEvent ()
PN> from /usr/lib/libwx_baseu-2.8.so.0
PN> #5 0x006f41ab in wxWindow::GTKProcessEvent ()
PN> from /usr/lib/libwx_gtk2u_core-2.8.so.0
PN> #6 0x006f80bf in ?? () from /usr/lib/libwx_gtk2u_core-2.8.so.0
PN>
PN> This call seems to be generated by GTK for the panel itself because
PN> the panel's size was changed due to Call #1.

So we seem to have a problem here already, i.e. we generate the size event
ourselves and also get one from GTK+. Unfortunately I don't know what would
the consequences of not doing either would be -- nor which one should be
dropped.

PN> Finally, we have Call #3:
[called from wxTLW::OnSize again]

PN> I'm not entirely sure, but it seems that this call is generated by GTK
PN> because the frame has changed size (during the course of Call #1).
PN> This again causes the DoSetSize to be called on the panel via
PN> DoLayout. The DoSetSize then causes another wxEVT_SIZE to be emitted.
PN> My guess is that the only thing that saves us from going into an
PN> infinite loop is that the DoSetSize on the panel during Call #3 does
PN> not generate a subsequent internal event by GTK for the panel since
PN> the panel's size is simply set to the same size as was set in Call #1.
PN>
PN> Please confirm my logic above. On face, it seems that there is a
PN> problem here and it should somehow be fixed.

Yes, it definitely looks so and I see nothing wrong with your logic.
Unfortunately I don't know enough to be sure what is the best way to fix
this. I'd like to ask you to open a wxGTK bug report on Trac about it with
a patch to the minimal sample simply adding a EVT_SIZE handler calling
wxLogDebug() with the new size so that the problem would be easy to
reproduce for whoever looks into it. But I just don't have enough time to
fix it myself at the moment so I can only hope that Robert or Paul can look
at this.

Thanks,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Loading...