Skip to content

Commit 3e07952

Browse files
author
徐扬斌
committed
GTK: Final fix wxGUIEventLoop::DoYieldFor compatibility when using with CEF
We'll now do Yield differently based on whether we're linking to CEF. When not using CEF, we maintain the original Yield logic. When using CEF, we do not replace the global GDK event handler, we only handle GDK events, and we also do not use gtk_main_iteration() to handle non GDK events, because it will trapped us in and endless message loop, Pending() will always be true.
1 parent 2f191ef commit 3e07952

File tree

1 file changed

+52
-8
lines changed

1 file changed

+52
-8
lines changed

src/gtk/evtloop.cpp

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333

3434
#include "wx/gtk/private/wrapgtk.h"
3535

36+
#include <dlfcn.h>
37+
#include <link.h>
38+
3639
GdkWindow* wxGetTopLevelGDK();
3740

3841
// ============================================================================
@@ -364,9 +367,31 @@ static void wxgtk_main_do_event(GdkEvent* event, void* data)
364367
}
365368
}
366369

370+
bool isUsingCef(){
371+
static bool is_using_cef = false;
372+
static bool known_already = false;
373+
if (known_already)
374+
return is_using_cef;
375+
// Use dl_iterate_phdr to iterate over the program headers of the current process
376+
dl_iterate_phdr([](struct dl_phdr_info *info, size_t WXUNUSED(size), void *WXUNUSED(data)) {
377+
auto so_name = std::string{info->dlpi_name};
378+
auto pos = so_name.find_last_of('/');
379+
if (pos == std::string::npos)
380+
return 0;
381+
so_name = so_name.substr(pos + 1);
382+
if (so_name.compare(0, 9, "libcef.so") == 0){
383+
is_using_cef = true;
384+
return 1;
385+
}
386+
return 0;
387+
}, nullptr);
388+
known_already = true;
389+
return is_using_cef;
390+
}
391+
367392
void wxGUIEventLoop::DoYieldFor(long eventsToProcess)
368393
{
369-
// DO NOT replace the global GDK event handler with our 'wxgtk_main_do_event'.
394+
// DO NOT replace the global GDK event handler with our 'wxgtk_main_do_event' WHEN-USING-CEF.
370395
// Because this trick rely on one uncertain assumption:
371396
// No one besides us, had done gdk_event_handler_set() already.
372397
// In most case, this might be true.
@@ -379,15 +404,34 @@ void wxGUIEventLoop::DoYieldFor(long eventsToProcess)
379404
// If there're GdkEvents, we handle them via 'wxgtk_main_do_event',
380405
// all other events should be handle by one gtk_main_iteration().
381406
// 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_);
407+
if (isUsingCef()){
408+
while(Pending()){
409+
auto gdk_event_ = gdk_event_get();
410+
if (gdk_event_ != nullptr){
411+
wxgtk_main_do_event(gdk_event_, this);
412+
gdk_event_free(gdk_event_);
413+
}
414+
else
415+
break;
387416
}
388-
else
417+
}
418+
else {
419+
// temporarily replace the global GDK event handler with our function, which
420+
// categorizes the events and using m_eventsToProcessInsideYield decides
421+
// if an event should be processed immediately or not
422+
// NOTE: this approach is better than using gdk_display_get_event() because
423+
// gtk_main_iteration() does more than just calling gdk_display_get_event()
424+
// and then call gtk_main_do_event()!
425+
// In particular in this way we also process input from sources like
426+
// GIOChannels (this is needed for e.g. wxGUIAppTraits::WaitForChild).
427+
gdk_event_handler_set(wxgtk_main_do_event, this, NULL);
428+
while (Pending()) // avoid false positives from our idle source
389429
gtk_main_iteration();
390-
}
430+
431+
wxGCC_WARNING_SUPPRESS_CAST_FUNCTION_TYPE()
432+
gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
433+
wxGCC_WARNING_RESTORE_CAST_FUNCTION_TYPE()
434+
}
391435

392436
wxEventLoopBase::DoYieldFor(eventsToProcess);
393437

0 commit comments

Comments
 (0)