From 11807d5951f62cf4c7c3b51e5c872d46ac534223 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Wed, 14 Oct 2015 09:46:42 -0700 Subject: [PATCH] Linux: Fix focus/activation handling and keyboard input (issue #1679). --- patch/patch.cfg | 6 ++ patch/patches/x11_desktop_handler_focus.patch | 82 +++++++++++++++++++ tests/cefclient/browser/root_window_gtk.cc | 26 +++++- 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 patch/patches/x11_desktop_handler_focus.patch diff --git a/patch/patch.cfg b/patch/patch.cfg index 87890a8e0..c4270d531 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -54,6 +54,12 @@ patches = [ 'name': 'views_widget_180_1677', 'path': '../ui/views/widget/', }, + { + # Fix focus/activation handling and keyboard input on Linux. + # https://bitbucket.org/chromiumembedded/cef/issues/1679 + 'name': 'x11_desktop_handler_focus', + 'path': '../', + }, { # Allow continued use of ContentRendererClient::HandleNavigation. # https://code.google.com/p/chromiumembedded/issues/detail?id=1129 diff --git a/patch/patches/x11_desktop_handler_focus.patch b/patch/patches/x11_desktop_handler_focus.patch new file mode 100644 index 000000000..b97c81d06 --- /dev/null +++ b/patch/patches/x11_desktop_handler_focus.patch @@ -0,0 +1,82 @@ +diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc +index 9fcd8c3..cbf865d 100644 +--- content/browser/renderer_host/render_widget_host_view_aura.cc ++++ content/browser/renderer_host/render_widget_host_view_aura.cc +@@ -746,6 +746,13 @@ void RenderWidgetHostViewAura::SetKeyboardFocus() { + ::SetFocus(host->GetAcceleratedWidget()); + } + #endif ++#if defined(OS_LINUX) ++ if (CanFocus()) { ++ aura::WindowTreeHost* host = window_->GetHost(); ++ if (host) ++ host->Show(); ++ } ++#endif + if (host_ && set_focus_on_mouse_down_) { + set_focus_on_mouse_down_ = false; + host_->Focus(); +diff --git ui/views/widget/desktop_aura/x11_desktop_handler.cc ui/views/widget/desktop_aura/x11_desktop_handler.cc +index 5ab84f9..1052e2c 100644 +--- ui/views/widget/desktop_aura/x11_desktop_handler.cc ++++ ui/views/widget/desktop_aura/x11_desktop_handler.cc +@@ -31,6 +31,30 @@ views::X11DesktopHandler* g_handler = NULL; + + namespace views { + ++namespace { ++ ++bool IsParentOfWindow(XDisplay* xdisplay, ++ ::Window potential_parent, ++ ::Window window) { ++ ::Window parent_win, root_win; ++ Window* child_windows; ++ unsigned int num_child_windows; ++ while (window) { ++ if (!XQueryTree(xdisplay, window, &root_win, &parent_win, ++ &child_windows, &num_child_windows)) { ++ break; ++ } ++ if(child_windows) ++ XFree(child_windows); ++ if (parent_win == potential_parent) ++ return true; ++ window = parent_win; ++ } ++ return false; ++} ++ ++} // namespace ++ + // static + X11DesktopHandler* X11DesktopHandler::get() { + if (!g_handler) +@@ -58,14 +82,7 @@ X11DesktopHandler::X11DesktopHandler() + attr.your_event_mask | PropertyChangeMask | + StructureNotifyMask | SubstructureNotifyMask); + +- if (ui::GuessWindowManager() == ui::WM_WMII) { +- // wmii says that it supports _NET_ACTIVE_WINDOW but does not. +- // https://code.google.com/p/wmii/issues/detail?id=266 +- wm_supports_active_window_ = false; +- } else { +- wm_supports_active_window_ = +- ui::WmSupportsHint(atom_cache_.GetAtom("_NET_ACTIVE_WINDOW")); +- } ++ wm_supports_active_window_ = false; + } + + X11DesktopHandler::~X11DesktopHandler() { +@@ -175,8 +192,10 @@ uint32_t X11DesktopHandler::DispatchEvent(const ui::PlatformEvent& event) { + ::Window window; + if (ui::GetXIDProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) && + window) { +- x_active_window_ = window; +- OnActiveWindowChanged(window, ACTIVE); ++ if (!IsParentOfWindow(xdisplay_, window, current_window_)) { ++ x_active_window_ = window; ++ OnActiveWindowChanged(window, ACTIVE); ++ } + } else { + x_active_window_ = None; + } diff --git a/tests/cefclient/browser/root_window_gtk.cc b/tests/cefclient/browser/root_window_gtk.cc index ee85f9d35..93bb65c22 100644 --- a/tests/cefclient/browser/root_window_gtk.cc +++ b/tests/cefclient/browser/root_window_gtk.cc @@ -603,7 +603,31 @@ gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget, GdkWindow* gdk_window = gtk_widget_get_window(window); ::Display* xdisplay = GDK_WINDOW_XDISPLAY(gdk_window); ::Window xwindow = GDK_WINDOW_XID(gdk_window); - XSetInputFocus(xdisplay, xwindow, RevertToParent, CurrentTime); + + // Retrieve the atoms required by the below XSendEvent call. + const char* kAtoms[] = { + "WM_PROTOCOLS", + "WM_TAKE_FOCUS" + }; + Atom atoms[2]; + int result = XInternAtoms(xdisplay, const_cast(kAtoms), 2, false, + atoms); + if (!result) + NOTREACHED(); + + XEvent e; + e.type = ClientMessage; + e.xany.display = xdisplay; + e.xany.window = xwindow; + e.xclient.format = 32; + e.xclient.message_type = atoms[0]; + e.xclient.data.l[0] = atoms[1]; + e.xclient.data.l[1] = CurrentTime; + e.xclient.data.l[2] = 0; + e.xclient.data.l[3] = 0; + e.xclient.data.l[4] = 0; + + XSendEvent(xdisplay, xwindow, false, 0, &e); return FALSE; }