Skip to content

Commit 69dbef5

Browse files
author
徐扬斌
committed
GTK: Fix wxGUIEventLoop::DoYieldFor compatibility when using with CEF
DO NOT replace the global GDK event handler with our 'wxgtk_main_do_event'. Because this trick rely on one uncertain assumption: No one besides us, had done gdk_event_handler_set() already. In most case, this might be true. But a single exception can destroy this trick completely. For example, when we want to embed CEF, Chromium will use a custom gdk_event_handler too. This trick will render all CEF browser window/view no longer usable. GTK3 should be blamed for not offering any gdk_event_handler_get() or similar stuff for a safe trick here. In GTK4, there's a more sane way to get the job done. So let's do it in a more conservative way. If there're GdkEvents, we handle them via 'wxgtk_main_do_event', all other events should be handle by one gtk_main_iteration(). I'm not sure whether this is really okay, but it seems a nicer and less intrusive way to do things.
1 parent 6c13421 commit 69dbef5

File tree

1 file changed

+23
-16
lines changed

1 file changed

+23
-16
lines changed

src/gtk/evtloop.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -365,22 +365,29 @@ static void wxgtk_main_do_event(GdkEvent* event, void* data)
365365
}
366366

367367
void wxGUIEventLoop::DoYieldFor(long eventsToProcess)
368-
{
369-
// temporarily replace the global GDK event handler with our function, which
370-
// categorizes the events and using m_eventsToProcessInsideYield decides
371-
// if an event should be processed immediately or not
372-
// NOTE: this approach is better than using gdk_display_get_event() because
373-
// gtk_main_iteration() does more than just calling gdk_display_get_event()
374-
// and then call gtk_main_do_event()!
375-
// In particular in this way we also process input from sources like
376-
// GIOChannels (this is needed for e.g. wxGUIAppTraits::WaitForChild).
377-
gdk_event_handler_set(wxgtk_main_do_event, this, NULL);
378-
while (Pending()) // avoid false positives from our idle source
379-
gtk_main_iteration();
380-
381-
wxGCC_WARNING_SUPPRESS_CAST_FUNCTION_TYPE()
382-
gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
383-
wxGCC_WARNING_RESTORE_CAST_FUNCTION_TYPE()
368+
{
369+
// DO NOT replace the global GDK event handler with our 'wxgtk_main_do_event'.
370+
// Because this trick rely on one uncertain assumption:
371+
// No one besides us, had done gdk_event_handler_set() already.
372+
// In most case, this might be true.
373+
// But a single exception can destroy this trick completely.
374+
// For example, when we want to embed CEF, Chromium will use a custom gdk_event_handler too.
375+
// This trick will render all CEF browser window/view no longer usable.
376+
// GTK3 should be blamed for not offering any gdk_event_handler_get() or similar stuff for a safe trick here.
377+
// In GTK4, there's a more sane way to get the job done.
378+
// So let's do it in a more conservative way.
379+
// If there're GdkEvents, we handle them via 'wxgtk_main_do_event',
380+
// all other events should be handle by one gtk_main_iteration().
381+
// I'm not sure whether this is really okay, but it seems a nicer and less intrusive way to do things.
382+
while(Pending()){
383+
auto gdk_event_ = gdk_event_get();
384+
if (gdk_event_ != nullptr){
385+
wxgtk_main_do_event(gdk_event_, this);
386+
gdk_event_free(gdk_event_);
387+
}
388+
else
389+
gtk_main_iteration();
390+
}
384391

385392
wxEventLoopBase::DoYieldFor(eventsToProcess);
386393

0 commit comments

Comments
 (0)