Linux: cefclient: Fix GTK behavior with multi-threaded-message-loop (fixes issue #3087)

Switch to using g_main_context_default() in MainMessageLoopMultithreadedGtk. As of M86
(https://crrev.com/b960daf4e6) Chromium now creates its own context in MessagePumpGlib so
we can use the default context in cefclient. This is also more "correct" from a GTK usage
perspective. As part of this change all GTK dialogs and callbacks are now executed on the
main thread instead of the UI thread (note that these are the same thread when not using
multi-threaded-message-loop).
This commit is contained in:
Marshall Greenblatt 2021-02-12 11:46:38 -08:00
parent 7fe6a18f03
commit b3ad79e2c5
3 changed files with 23 additions and 33 deletions

View File

@ -143,10 +143,6 @@ GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
return nullptr; return nullptr;
} }
void RunCallback(base::Callback<void(GtkWindow*)> callback, GtkWindow* window) {
callback.Run(window);
}
} // namespace } // namespace
ClientDialogHandlerGtk::ClientDialogHandlerGtk() : gtk_dialog_(nullptr) {} ClientDialogHandlerGtk::ClientDialogHandlerGtk() : gtk_dialog_(nullptr) {}
@ -227,7 +223,7 @@ void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params, void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
GtkWindow* window) { GtkWindow* window) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
ScopedGdkThreadsEnter scoped_gdk_threads; ScopedGdkThreadsEnter scoped_gdk_threads;
@ -367,7 +363,7 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
void ClientDialogHandlerGtk::OnJSDialogContinue(OnJSDialogParams params, void ClientDialogHandlerGtk::OnJSDialogContinue(OnJSDialogParams params,
GtkWindow* window) { GtkWindow* window) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
ScopedGdkThreadsEnter scoped_gdk_threads; ScopedGdkThreadsEnter scoped_gdk_threads;
@ -443,7 +439,7 @@ void ClientDialogHandlerGtk::GetWindowAndContinue(
GtkWindow* window = GetWindow(browser); GtkWindow* window = GetWindow(browser);
if (window) { if (window) {
CefPostTask(TID_UI, base::Bind(RunCallback, callback, window)); callback.Run(window);
} }
} }
@ -451,7 +447,7 @@ void ClientDialogHandlerGtk::GetWindowAndContinue(
void ClientDialogHandlerGtk::OnDialogResponse(GtkDialog* dialog, void ClientDialogHandlerGtk::OnDialogResponse(GtkDialog* dialog,
gint response_id, gint response_id,
ClientDialogHandlerGtk* handler) { ClientDialogHandlerGtk* handler) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
DCHECK_EQ(dialog, GTK_DIALOG(handler->gtk_dialog_)); DCHECK_EQ(dialog, GTK_DIALOG(handler->gtk_dialog_));
switch (response_id) { switch (response_id) {
@ -466,7 +462,8 @@ void ClientDialogHandlerGtk::OnDialogResponse(GtkDialog* dialog,
NOTREACHED(); NOTREACHED();
} }
handler->OnResetDialogState(nullptr); CefPostTask(TID_UI, base::Bind(&ClientDialogHandlerGtk::OnResetDialogState,
handler, nullptr));
} }
} // namespace client } // namespace client

View File

@ -78,10 +78,9 @@ MainMessageLoopMultithreadedGtk::~MainMessageLoopMultithreadedGtk() {
int MainMessageLoopMultithreadedGtk::Run() { int MainMessageLoopMultithreadedGtk::Run() {
DCHECK(RunsTasksOnCurrentThread()); DCHECK(RunsTasksOnCurrentThread());
// Chromium uses the default GLib context so we create our own context and // We use the default Glib context and Chromium creates its own context in
// make it the default for this thread. // MessagePumpGlib (starting in M86).
main_context_ = g_main_context_new(); main_context_ = g_main_context_default();
g_main_context_push_thread_default(main_context_);
main_loop_ = g_main_loop_new(main_context_, TRUE); main_loop_ = g_main_loop_new(main_context_, TRUE);
@ -100,8 +99,6 @@ int MainMessageLoopMultithreadedGtk::Run() {
g_main_loop_unref(main_loop_); g_main_loop_unref(main_loop_);
main_loop_ = nullptr; main_loop_ = nullptr;
g_main_context_pop_thread_default(main_context_);
g_main_context_unref(main_context_);
main_context_ = nullptr; main_context_ = nullptr;
return 0; return 0;

View File

@ -94,13 +94,9 @@ void RootWindowGtk::Init(RootWindow::Delegate* delegate,
initialized_ = true; initialized_ = true;
// Create the native root window on the main thread. // Always post asynchronously to avoid reentrancy of the GDK lock.
if (CURRENTLY_ON_MAIN_THREAD()) { MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::CreateRootWindow, this, settings,
CreateRootWindow(settings, config.initially_hidden); config.initially_hidden));
} else {
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::CreateRootWindow, this,
settings, config.initially_hidden));
}
} }
void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate, void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
@ -682,7 +678,7 @@ void RootWindowGtk::NotifyDestroyedIfDone(bool window_destroyed,
gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget, gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
GdkEventFocus* event, GdkEventFocus* event,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
if (event->in) { if (event->in) {
self->NotifySetFocus(); self->NotifySetFocus();
@ -698,7 +694,7 @@ gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
gboolean RootWindowGtk::WindowState(GtkWidget* widget, gboolean RootWindowGtk::WindowState(GtkWidget* widget,
GdkEventWindowState* event, GdkEventWindowState* event,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
// Called when the root window is iconified or restored. Hide the browser // Called when the root window is iconified or restored. Hide the browser
// window when the root window is iconified to reduce resource usage. // window when the root window is iconified to reduce resource usage.
@ -714,7 +710,7 @@ gboolean RootWindowGtk::WindowState(GtkWidget* widget,
gboolean RootWindowGtk::WindowConfigure(GtkWindow* window, gboolean RootWindowGtk::WindowConfigure(GtkWindow* window,
GdkEvent* event, GdkEvent* event,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
self->NotifyMoveOrResizeStarted(); self->NotifyMoveOrResizeStarted();
return FALSE; // Don't stop this message. return FALSE; // Don't stop this message.
} }
@ -729,7 +725,7 @@ void RootWindowGtk::WindowDestroy(GtkWidget* widget, RootWindowGtk* self) {
gboolean RootWindowGtk::WindowDelete(GtkWidget* widget, gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
GdkEvent* event, GdkEvent* event,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
// Called to query whether the root window should be closed. // Called to query whether the root window should be closed.
if (self->force_close_) if (self->force_close_)
@ -769,7 +765,7 @@ void RootWindowGtk::MenubarSizeAllocated(GtkWidget* widget,
// static // static
gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget, gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
// Retrieve the menu ID set in AddMenuEntry. // Retrieve the menu ID set in AddMenuEntry.
int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey)); int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey));
@ -787,33 +783,33 @@ void RootWindowGtk::ToolbarSizeAllocated(GtkWidget* widget,
// static // static
void RootWindowGtk::BackButtonClicked(GtkButton* button, RootWindowGtk* self) { void RootWindowGtk::BackButtonClicked(GtkButton* button, RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
self->NotifyButtonClicked(IDC_NAV_BACK); self->NotifyButtonClicked(IDC_NAV_BACK);
} }
// static // static
void RootWindowGtk::ForwardButtonClicked(GtkButton* button, void RootWindowGtk::ForwardButtonClicked(GtkButton* button,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
self->NotifyButtonClicked(IDC_NAV_FORWARD); self->NotifyButtonClicked(IDC_NAV_FORWARD);
} }
// static // static
void RootWindowGtk::StopButtonClicked(GtkButton* button, RootWindowGtk* self) { void RootWindowGtk::StopButtonClicked(GtkButton* button, RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
self->NotifyButtonClicked(IDC_NAV_STOP); self->NotifyButtonClicked(IDC_NAV_STOP);
} }
// static // static
void RootWindowGtk::ReloadButtonClicked(GtkButton* button, void RootWindowGtk::ReloadButtonClicked(GtkButton* button,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
self->NotifyButtonClicked(IDC_NAV_RELOAD); self->NotifyButtonClicked(IDC_NAV_RELOAD);
} }
// static // static
void RootWindowGtk::URLEntryActivate(GtkEntry* entry, RootWindowGtk* self) { void RootWindowGtk::URLEntryActivate(GtkEntry* entry, RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
const gchar* url = gtk_entry_get_text(entry); const gchar* url = gtk_entry_get_text(entry);
self->NotifyLoadURL(std::string(url)); self->NotifyLoadURL(std::string(url));
} }
@ -822,7 +818,7 @@ void RootWindowGtk::URLEntryActivate(GtkEntry* entry, RootWindowGtk* self) {
gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget, gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget,
GdkEventButton* event, GdkEventButton* event,
RootWindowGtk* self) { RootWindowGtk* self) {
CEF_REQUIRE_UI_THREAD(); REQUIRE_MAIN_THREAD();
// Give focus to the GTK window. This is a work-around for bad focus-related // Give focus to the GTK window. This is a work-around for bad focus-related
// interaction between the root window managed by GTK and the browser managed // interaction between the root window managed by GTK and the browser managed