Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc

Issue 18741006: [GTK] Report isMinimized and correctly restore app windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add a bool member for safer remove filter. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/gtk/extensions/native_app_window_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/gtk/extensions/native_app_window_gtk.h" 5 #include "chrome/browser/ui/gtk/extensions/native_app_window_gtk.h"
6 6
7 #include <gdk/gdkx.h>
8 #include <vector>
9
10 #include "base/message_loop/message_pump_gtk.h"
7 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h" 13 #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
10 #include "chrome/browser/ui/gtk/gtk_util.h" 14 #include "chrome/browser/ui/gtk/gtk_util.h"
11 #include "chrome/browser/ui/gtk/gtk_window_util.h" 15 #include "chrome/browser/ui/gtk/gtk_window_util.h"
12 #include "chrome/browser/web_applications/web_app.h" 16 #include "chrome/browser/web_applications/web_app.h"
13 #include "chrome/common/extensions/extension.h" 17 #include "chrome/common/extensions/extension.h"
14 #include "content/public/browser/render_view_host.h" 18 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/render_widget_host_view.h" 19 #include "content/public/browser/render_widget_host_view.h"
16 #include "content/public/browser/web_contents.h" 20 #include "content/public/browser/web_contents.h"
17 #include "content/public/browser/web_contents_view.h" 21 #include "content/public/browser/web_contents_view.h"
18 #include "ui/base/x/active_window_watcher_x.h" 22 #include "ui/base/x/active_window_watcher_x.h"
19 #include "ui/gfx/gtk_util.h" 23 #include "ui/gfx/gtk_util.h"
20 #include "ui/gfx/image/image.h" 24 #include "ui/gfx/image/image.h"
21 #include "ui/gfx/rect.h" 25 #include "ui/gfx/rect.h"
22 26
23 using apps::ShellWindow; 27 using apps::ShellWindow;
24 28
25 namespace { 29 namespace {
26 30
27 // The timeout in milliseconds before we'll get the true window position with 31 // The timeout in milliseconds before we'll get the true window position with
28 // gtk_window_get_position() after the last GTK configure-event signal. 32 // gtk_window_get_position() after the last GTK configure-event signal.
29 const int kDebounceTimeoutMilliseconds = 100; 33 const int kDebounceTimeoutMilliseconds = 100;
30 34
35 const char* kAtomsToCache[] = {
36 "_NET_WM_STATE",
37 "_NET_WM_STATE_HIDDEN",
38 NULL
39 };
40
31 } // namespace 41 } // namespace
32 42
33 NativeAppWindowGtk::NativeAppWindowGtk(ShellWindow* shell_window, 43 NativeAppWindowGtk::NativeAppWindowGtk(ShellWindow* shell_window,
34 const ShellWindow::CreateParams& params) 44 const ShellWindow::CreateParams& params)
35 : shell_window_(shell_window), 45 : shell_window_(shell_window),
36 window_(NULL), 46 window_(NULL),
37 state_(GDK_WINDOW_STATE_WITHDRAWN), 47 state_(GDK_WINDOW_STATE_WITHDRAWN),
38 is_active_(false), 48 is_active_(false),
39 content_thinks_its_fullscreen_(false), 49 content_thinks_its_fullscreen_(false),
40 frameless_(params.frame == ShellWindow::FRAME_NONE), 50 frameless_(params.frame == ShellWindow::FRAME_NONE),
41 frame_cursor_(NULL) { 51 frame_cursor_(NULL),
52 atom_cache_(base::MessagePumpGtk::GetDefaultXDisplay(), kAtomsToCache),
53 is_x_event_listened_(false) {
42 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); 54 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
43 55
44 gfx::NativeView native_view = 56 gfx::NativeView native_view =
45 web_contents()->GetView()->GetNativeView(); 57 web_contents()->GetView()->GetNativeView();
46 gtk_container_add(GTK_CONTAINER(window_), native_view); 58 gtk_container_add(GTK_CONTAINER(window_), native_view);
47 59
48 if (params.bounds.x() != INT_MIN && params.bounds.y() != INT_MIN) 60 if (params.bounds.x() != INT_MIN && params.bounds.y() != INT_MIN)
49 gtk_window_move(window_, params.bounds.x(), params.bounds.y()); 61 gtk_window_move(window_, params.bounds.x(), params.bounds.y());
50 62
51 // This is done to avoid a WM "feature" where setting the window size to 63 // This is done to avoid a WM "feature" where setting the window size to
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 G_CALLBACK(OnConfigureThunk), this); 133 G_CALLBACK(OnConfigureThunk), this);
122 g_signal_connect(window_, "window-state-event", 134 g_signal_connect(window_, "window-state-event",
123 G_CALLBACK(OnWindowStateThunk), this); 135 G_CALLBACK(OnWindowStateThunk), this);
124 if (frameless_) { 136 if (frameless_) {
125 g_signal_connect(window_, "button-press-event", 137 g_signal_connect(window_, "button-press-event",
126 G_CALLBACK(OnButtonPressThunk), this); 138 G_CALLBACK(OnButtonPressThunk), this);
127 g_signal_connect(window_, "motion-notify-event", 139 g_signal_connect(window_, "motion-notify-event",
128 G_CALLBACK(OnMouseMoveEventThunk), this); 140 G_CALLBACK(OnMouseMoveEventThunk), this);
129 } 141 }
130 142
143 // If _NET_WM_STATE_HIDDEN is in _NET_SUPPORTED, listen for XEvent to work
144 // around GTK+ not reporting minimization state changes. See comment in the
145 // |OnXEvent|.
146 std::vector< ::Atom> supported_atoms;
147 if (ui::GetAtomArrayProperty(ui::GetX11RootWindow(),
148 "_NET_SUPPORTED",
149 &supported_atoms)) {
150 if (std::find(supported_atoms.begin(),
151 supported_atoms.end(),
152 atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN")) !=
153 supported_atoms.end()) {
154 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(window_));
155 gdk_window_add_filter(window,
156 &NativeAppWindowGtk::OnXEventThunk,
157 this);
158 is_x_event_listened_ = true;
159 }
160 }
161
131 // Add the keybinding registry. 162 // Add the keybinding registry.
132 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk( 163 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
133 shell_window_->profile(), 164 shell_window_->profile(),
134 window_, 165 window_,
135 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, 166 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
136 shell_window_)); 167 shell_window_));
137 168
138 ui::ActiveWindowWatcherX::AddObserver(this); 169 ui::ActiveWindowWatcherX::AddObserver(this);
139 } 170 }
140 171
141 NativeAppWindowGtk::~NativeAppWindowGtk() { 172 NativeAppWindowGtk::~NativeAppWindowGtk() {
142 ui::ActiveWindowWatcherX::RemoveObserver(this); 173 ui::ActiveWindowWatcherX::RemoveObserver(this);
174 if (is_x_event_listened_) {
175 gdk_window_remove_filter(NULL,
176 &NativeAppWindowGtk::OnXEventThunk,
177 this);
178 }
143 } 179 }
144 180
145 bool NativeAppWindowGtk::IsActive() const { 181 bool NativeAppWindowGtk::IsActive() const {
146 if (ui::ActiveWindowWatcherX::WMSupportsActivation()) 182 if (ui::ActiveWindowWatcherX::WMSupportsActivation())
147 return is_active_; 183 return is_active_;
148 184
149 // This still works even though we don't get the activation notification. 185 // This still works even though we don't get the activation notification.
150 return gtk_window_is_active(window_); 186 return gtk_window_is_active(window_);
151 } 187 }
152 188
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 253
218 void NativeAppWindowGtk::Activate() { 254 void NativeAppWindowGtk::Activate() {
219 gtk_window_present(window_); 255 gtk_window_present(window_);
220 } 256 }
221 257
222 void NativeAppWindowGtk::Deactivate() { 258 void NativeAppWindowGtk::Deactivate() {
223 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_))); 259 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
224 } 260 }
225 261
226 void NativeAppWindowGtk::Maximize() { 262 void NativeAppWindowGtk::Maximize() {
263 // Represent the window first in order to keep the maximization behavior
264 // consistency with Windows platform. Otherwise the window will be hidden if
265 // it has been minimized.
266 gtk_window_present(window_);
227 gtk_window_maximize(window_); 267 gtk_window_maximize(window_);
228 } 268 }
229 269
230 void NativeAppWindowGtk::Minimize() { 270 void NativeAppWindowGtk::Minimize() {
231 gtk_window_iconify(window_); 271 gtk_window_iconify(window_);
232 } 272 }
233 273
234 void NativeAppWindowGtk::Restore() { 274 void NativeAppWindowGtk::Restore() {
235 if (IsMaximized()) 275 if (IsMaximized())
236 gtk_window_unmaximize(window_); 276 gtk_window_unmaximize(window_);
237 else if (IsMinimized()) 277 else if (IsMinimized())
238 gtk_window_deiconify(window_); 278 gtk_window_deiconify(window_);
279
280 // Represent the window to keep restoration behavior consistency with Windows
281 // platform.
282 // TODO(zhchbin): verify whether we need this until http://crbug.com/261013 is
283 // fixed.
284 gtk_window_present(window_);
239 } 285 }
240 286
241 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) { 287 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
242 gfx::Rect content_bounds = bounds; 288 gfx::Rect content_bounds = bounds;
243 content_bounds.Inset(GetFrameInsets()); 289 content_bounds.Inset(GetFrameInsets());
244 gtk_window_move(window_, content_bounds.x(), content_bounds.y()); 290 gtk_window_move(window_, content_bounds.x(), content_bounds.y());
245 if (!resizable_) { 291 if (!resizable_) {
246 if (frameless_ && 292 if (frameless_ &&
247 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) { 293 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) {
248 content_bounds.set_height(content_bounds.height() - 1); 294 content_bounds.set_height(content_bounds.height() - 1);
249 } 295 }
250 // TODO(jeremya): set_size_request doesn't honor min/max size, so the 296 // TODO(jeremya): set_size_request doesn't honor min/max size, so the
251 // bounds should be constrained manually. 297 // bounds should be constrained manually.
252 gtk_widget_set_size_request(GTK_WIDGET(window_), 298 gtk_widget_set_size_request(GTK_WIDGET(window_),
253 content_bounds.width(), content_bounds.height()); 299 content_bounds.width(), content_bounds.height());
254 } else { 300 } else {
255 gtk_window_util::SetWindowSize(window_, 301 gtk_window_util::SetWindowSize(window_,
256 gfx::Size(bounds.width(), bounds.height())); 302 gfx::Size(bounds.width(), bounds.height()));
257 } 303 }
258 } 304 }
259 305
306 GdkFilterReturn NativeAppWindowGtk::OnXEvent(GdkXEvent* gdk_x_event,
307 GdkEvent* gdk_event) {
308 // Work around GTK+ not reporting minimization state changes. Listen
309 // for _NET_WM_STATE property changes and use _NET_WM_STATE_HIDDEN's
310 // presence to set or clear the iconified bit if _NET_WM_STATE_HIDDEN
311 // is supported. http://crbug.com/162794.
312 XEvent* x_event = static_cast<XEvent*>(gdk_x_event);
313 std::vector< ::Atom> atom_list;
314
315 if (x_event->type == PropertyNotify &&
316 x_event->xproperty.atom == atom_cache_.GetAtom("_NET_WM_STATE") &&
317 ui::GetAtomArrayProperty(GDK_WINDOW_XWINDOW(GTK_WIDGET(window_)->window),
318 "_NET_WM_STATE",
319 &atom_list)) {
320 std::vector< ::Atom>::iterator it =
321 std::find(atom_list.begin(),
322 atom_list.end(),
323 atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN"));
324 state_ = (it != atom_list.end()) ? GDK_WINDOW_STATE_ICONIFIED :
325 static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);
326
327 shell_window_->OnNativeWindowChanged();
328 }
329
330 return GDK_FILTER_CONTINUE;
331 }
332
260 void NativeAppWindowGtk::FlashFrame(bool flash) { 333 void NativeAppWindowGtk::FlashFrame(bool flash) {
261 gtk_window_set_urgency_hint(window_, flash); 334 gtk_window_set_urgency_hint(window_, flash);
262 } 335 }
263 336
264 bool NativeAppWindowGtk::IsAlwaysOnTop() const { 337 bool NativeAppWindowGtk::IsAlwaysOnTop() const {
265 return false; 338 return false;
266 } 339 }
267 340
268 void NativeAppWindowGtk::RenderViewHostChanged() { 341 void NativeAppWindowGtk::RenderViewHostChanged() {
269 web_contents()->GetView()->Focus(); 342 web_contents()->GetView()->Focus();
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 620
548 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions)); 621 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
549 } 622 }
550 623
551 // static 624 // static
552 NativeAppWindow* NativeAppWindow::Create( 625 NativeAppWindow* NativeAppWindow::Create(
553 ShellWindow* shell_window, 626 ShellWindow* shell_window,
554 const ShellWindow::CreateParams& params) { 627 const ShellWindow::CreateParams& params) {
555 return new NativeAppWindowGtk(shell_window, params); 628 return new NativeAppWindowGtk(shell_window, params);
556 } 629 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/extensions/native_app_window_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698