| Index: chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc
|
| diff --git a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc
|
| index e96e322bcb66b627003f07e7302ff2aa96be3260..41548348631785edfc6cae66b59ef5669edf26ad 100644
|
| --- a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc
|
| +++ b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc
|
| @@ -4,6 +4,10 @@
|
|
|
| #include "chrome/browser/ui/gtk/extensions/native_app_window_gtk.h"
|
|
|
| +#include <gdk/gdkx.h>
|
| +#include <vector>
|
| +
|
| +#include "base/message_loop/message_pump_gtk.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
|
| @@ -28,6 +32,12 @@ namespace {
|
| // gtk_window_get_position() after the last GTK configure-event signal.
|
| const int kDebounceTimeoutMilliseconds = 100;
|
|
|
| +const char* kAtomsToCache[] = {
|
| + "_NET_WM_STATE",
|
| + "_NET_WM_STATE_HIDDEN",
|
| + NULL
|
| +};
|
| +
|
| } // namespace
|
|
|
| NativeAppWindowGtk::NativeAppWindowGtk(ShellWindow* shell_window,
|
| @@ -38,7 +48,9 @@ NativeAppWindowGtk::NativeAppWindowGtk(ShellWindow* shell_window,
|
| is_active_(false),
|
| content_thinks_its_fullscreen_(false),
|
| frameless_(params.frame == ShellWindow::FRAME_NONE),
|
| - frame_cursor_(NULL) {
|
| + frame_cursor_(NULL),
|
| + atom_cache_(base::MessagePumpGtk::GetDefaultXDisplay(), kAtomsToCache),
|
| + is_x_event_listened_(false) {
|
| window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
|
|
|
| gfx::NativeView native_view =
|
| @@ -128,6 +140,25 @@ NativeAppWindowGtk::NativeAppWindowGtk(ShellWindow* shell_window,
|
| G_CALLBACK(OnMouseMoveEventThunk), this);
|
| }
|
|
|
| + // If _NET_WM_STATE_HIDDEN is in _NET_SUPPORTED, listen for XEvent to work
|
| + // around GTK+ not reporting minimization state changes. See comment in the
|
| + // |OnXEvent|.
|
| + std::vector< ::Atom> supported_atoms;
|
| + if (ui::GetAtomArrayProperty(ui::GetX11RootWindow(),
|
| + "_NET_SUPPORTED",
|
| + &supported_atoms)) {
|
| + if (std::find(supported_atoms.begin(),
|
| + supported_atoms.end(),
|
| + atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN")) !=
|
| + supported_atoms.end()) {
|
| + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(window_));
|
| + gdk_window_add_filter(window,
|
| + &NativeAppWindowGtk::OnXEventThunk,
|
| + this);
|
| + is_x_event_listened_ = true;
|
| + }
|
| + }
|
| +
|
| // Add the keybinding registry.
|
| extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
|
| shell_window_->profile(),
|
| @@ -140,6 +171,11 @@ NativeAppWindowGtk::NativeAppWindowGtk(ShellWindow* shell_window,
|
|
|
| NativeAppWindowGtk::~NativeAppWindowGtk() {
|
| ui::ActiveWindowWatcherX::RemoveObserver(this);
|
| + if (is_x_event_listened_) {
|
| + gdk_window_remove_filter(NULL,
|
| + &NativeAppWindowGtk::OnXEventThunk,
|
| + this);
|
| + }
|
| }
|
|
|
| bool NativeAppWindowGtk::IsActive() const {
|
| @@ -224,6 +260,10 @@ void NativeAppWindowGtk::Deactivate() {
|
| }
|
|
|
| void NativeAppWindowGtk::Maximize() {
|
| + // Represent the window first in order to keep the maximization behavior
|
| + // consistency with Windows platform. Otherwise the window will be hidden if
|
| + // it has been minimized.
|
| + gtk_window_present(window_);
|
| gtk_window_maximize(window_);
|
| }
|
|
|
| @@ -236,6 +276,12 @@ void NativeAppWindowGtk::Restore() {
|
| gtk_window_unmaximize(window_);
|
| else if (IsMinimized())
|
| gtk_window_deiconify(window_);
|
| +
|
| + // Represent the window to keep restoration behavior consistency with Windows
|
| + // platform.
|
| + // TODO(zhchbin): verify whether we need this until http://crbug.com/261013 is
|
| + // fixed.
|
| + gtk_window_present(window_);
|
| }
|
|
|
| void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
|
| @@ -257,6 +303,33 @@ void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
|
| }
|
| }
|
|
|
| +GdkFilterReturn NativeAppWindowGtk::OnXEvent(GdkXEvent* gdk_x_event,
|
| + GdkEvent* gdk_event) {
|
| + // Work around GTK+ not reporting minimization state changes. Listen
|
| + // for _NET_WM_STATE property changes and use _NET_WM_STATE_HIDDEN's
|
| + // presence to set or clear the iconified bit if _NET_WM_STATE_HIDDEN
|
| + // is supported. http://crbug.com/162794.
|
| + XEvent* x_event = static_cast<XEvent*>(gdk_x_event);
|
| + std::vector< ::Atom> atom_list;
|
| +
|
| + if (x_event->type == PropertyNotify &&
|
| + x_event->xproperty.atom == atom_cache_.GetAtom("_NET_WM_STATE") &&
|
| + ui::GetAtomArrayProperty(GDK_WINDOW_XWINDOW(GTK_WIDGET(window_)->window),
|
| + "_NET_WM_STATE",
|
| + &atom_list)) {
|
| + std::vector< ::Atom>::iterator it =
|
| + std::find(atom_list.begin(),
|
| + atom_list.end(),
|
| + atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN"));
|
| + state_ = (it != atom_list.end()) ? GDK_WINDOW_STATE_ICONIFIED :
|
| + static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);
|
| +
|
| + shell_window_->OnNativeWindowChanged();
|
| + }
|
| +
|
| + return GDK_FILTER_CONTINUE;
|
| +}
|
| +
|
| void NativeAppWindowGtk::FlashFrame(bool flash) {
|
| gtk_window_set_urgency_hint(window_, flash);
|
| }
|
|
|