From 61ffc55ec3927c2543d431819dc92a9e6dbaef03 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 11 Sep 2014 18:23:10 +0000 Subject: [PATCH] Linux: Reduce resource usage when the window is minimized (issue #1369). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1832 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- libcef/browser/window_x11.cc | 39 ++++++++++++++++++- tests/cefclient/cefclient_gtk.cpp | 65 +++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 2 deletions(-) diff --git a/libcef/browser/window_x11.cc b/libcef/browser/window_x11.cc index ef62f7878..13fd01444 100644 --- a/libcef/browser/window_x11.cc +++ b/libcef/browser/window_x11.cc @@ -17,17 +17,21 @@ namespace { +const char kAtom[] = "ATOM"; const char kWMDeleteWindow[] = "WM_DELETE_WINDOW"; const char kWMProtocols[] = "WM_PROTOCOLS"; -const char kNetWMPing[] = "_NET_WM_PING"; const char kNetWMPid[] = "_NET_WM_PID"; +const char kNetWMPing[] = "_NET_WM_PING"; +const char kNetWMState[] = "_NET_WM_STATE"; const char kXdndProxy[] = "XdndProxy"; const char* kAtomsToCache[] = { + kAtom, kWMDeleteWindow, kWMProtocols, - kNetWMPing, kNetWMPid, + kNetWMPing, + kNetWMState, kXdndProxy, NULL }; @@ -360,6 +364,37 @@ uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) { if (focus_pending_) focus_pending_ = false; break; + case PropertyNotify: { + ::Atom changed_atom = xev->xproperty.atom; + if (changed_atom == atom_cache_.GetAtom(kNetWMState)) { + // State change event like minimize/maximize. + if (browser_) { + ::Window child = FindChild(xdisplay_, xwindow_); + if (child) { + // Forward the state change to the child DesktopWindowTreeHostX11 + // window so that resource usage will be reduced while the window is + // minimized. + std::vector< ::Atom> atom_list; + if (ui::GetAtomArrayProperty(xwindow_, kNetWMState, &atom_list) && + !atom_list.empty()) { + ui::SetAtomArrayProperty(child, kNetWMState, "ATOM", atom_list); + } else { + // Set an empty list of property values to pass the check in + // DesktopWindowTreeHostX11::OnWMStateUpdated(). + XChangeProperty(xdisplay_, + child, + atom_cache_.GetAtom(kNetWMState), // name + atom_cache_.GetAtom(kAtom), // type + 32, // size in bits of items in 'value' + PropModeReplace, + NULL, + 0); // num items + } + } + } + } + break; + } } return ui::POST_DISPATCH_STOP_PROPAGATION; diff --git a/tests/cefclient/cefclient_gtk.cpp b/tests/cefclient/cefclient_gtk.cpp index 8aef60129..1b4bf347f 100644 --- a/tests/cefclient/cefclient_gtk.cpp +++ b/tests/cefclient/cefclient_gtk.cpp @@ -16,6 +16,7 @@ #include #include "cefclient/cefclient.h" +#include "include/base/cef_scoped_ptr.h" #include "include/cef_app.h" #include "include/cef_browser.h" #include "include/cef_frame.h" @@ -115,6 +116,68 @@ gboolean WindowFocusIn(GtkWidget* widget, return FALSE; } +gboolean WindowState(GtkWidget* widget, + GdkEventWindowState* event, + gpointer user_data) { + if (!(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED)) + return TRUE; + + if (!g_handler) + return TRUE; + CefRefPtr browser = g_handler->GetBrowser(); + if (!browser) + return TRUE; + + const bool iconified = (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED); + if (browser->GetHost()->IsWindowRenderingDisabled()) { + // Notify the off-screen browser that it was shown or hidden. + browser->GetHost()->WasHidden(iconified); + } else { + // Forward the state change event to the browser window. + ::Display* xdisplay = cef_get_xdisplay(); + ::Window xwindow = browser->GetHost()->GetWindowHandle(); + + // Retrieve the atoms required by the below XChangeProperty call. + const char* kAtoms[] = { + "_NET_WM_STATE", + "ATOM", + "_NET_WM_STATE_HIDDEN" + }; + Atom atoms[3]; + int result = XInternAtoms(xdisplay, const_cast(kAtoms), 3, false, + atoms); + if (!result) + NOTREACHED(); + + if (iconified) { + // Set the hidden property state value. + scoped_ptr data(new Atom[1]); + data[0] = atoms[2]; + + XChangeProperty(xdisplay, + xwindow, + atoms[0], // name + atoms[1], // type + 32, // size in bits of items in 'value' + PropModeReplace, + reinterpret_cast(data.get()), + 1); // num items + } else { + // Set an empty array of property state values. + XChangeProperty(xdisplay, + xwindow, + atoms[0], // name + atoms[1], // type + 32, // size in bits of items in 'value' + PropModeReplace, + NULL, + 0); // num items + } + } + + return TRUE; +} + // Callback for Tests > Get Source... menu item. gboolean GetSourceActivated(GtkWidget* widget) { if (g_handler.get() && g_handler->GetBrowserId()) @@ -357,6 +420,8 @@ int main(int argc, char* argv[]) { gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); g_signal_connect(window, "focus-in-event", G_CALLBACK(WindowFocusIn), NULL); + g_signal_connect(window, "window-state-event", + G_CALLBACK(WindowState), NULL); GtkWidget* vbox = gtk_vbox_new(FALSE, 0); g_signal_connect(vbox, "size-allocate",