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

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: Ignore PlatformAppBrowserTest.WindowsApiProperties. It can pass in local. 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) {
42 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); 53 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
43 54
44 gfx::NativeView native_view = 55 gfx::NativeView native_view =
45 web_contents()->GetView()->GetNativeView(); 56 web_contents()->GetView()->GetNativeView();
46 gtk_container_add(GTK_CONTAINER(window_), native_view); 57 gtk_container_add(GTK_CONTAINER(window_), native_view);
47 58
48 if (params.bounds.x() != INT_MIN && params.bounds.y() != INT_MIN) 59 if (params.bounds.x() != INT_MIN && params.bounds.y() != INT_MIN)
49 gtk_window_move(window_, params.bounds.x(), params.bounds.y()); 60 gtk_window_move(window_, params.bounds.x(), params.bounds.y());
50 61
51 // This is done to avoid a WM "feature" where setting the window size to 62 // This is done to avoid a WM "feature" where setting the window size to
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 g_signal_connect(window_, "configure-event", 131 g_signal_connect(window_, "configure-event",
121 G_CALLBACK(OnConfigureThunk), this); 132 G_CALLBACK(OnConfigureThunk), this);
122 g_signal_connect(window_, "window-state-event", 133 g_signal_connect(window_, "window-state-event",
123 G_CALLBACK(OnWindowStateThunk), this); 134 G_CALLBACK(OnWindowStateThunk), this);
124 if (frameless_) { 135 if (frameless_) {
125 g_signal_connect(window_, "button-press-event", 136 g_signal_connect(window_, "button-press-event",
126 G_CALLBACK(OnButtonPressThunk), this); 137 G_CALLBACK(OnButtonPressThunk), this);
127 g_signal_connect(window_, "motion-notify-event", 138 g_signal_connect(window_, "motion-notify-event",
128 G_CALLBACK(OnMouseMoveEventThunk), this); 139 G_CALLBACK(OnMouseMoveEventThunk), this);
129 } 140 }
141 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(window_));
142 gdk_window_add_filter(window,
143 &NativeAppWindowGtk::OnXEventThunk,
144 this);
130 145
131 // Add the keybinding registry. 146 // Add the keybinding registry.
132 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk( 147 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
133 shell_window_->profile(), 148 shell_window_->profile(),
134 window_, 149 window_,
135 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, 150 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
136 shell_window_)); 151 shell_window_));
137 152
138 ui::ActiveWindowWatcherX::AddObserver(this); 153 ui::ActiveWindowWatcherX::AddObserver(this);
139 } 154 }
140 155
141 NativeAppWindowGtk::~NativeAppWindowGtk() { 156 NativeAppWindowGtk::~NativeAppWindowGtk() {
142 ui::ActiveWindowWatcherX::RemoveObserver(this); 157 ui::ActiveWindowWatcherX::RemoveObserver(this);
158 gdk_window_remove_filter(NULL,
159 &NativeAppWindowGtk::OnXEventThunk,
160 this);
143 } 161 }
144 162
145 bool NativeAppWindowGtk::IsActive() const { 163 bool NativeAppWindowGtk::IsActive() const {
146 if (ui::ActiveWindowWatcherX::WMSupportsActivation()) 164 if (ui::ActiveWindowWatcherX::WMSupportsActivation())
147 return is_active_; 165 return is_active_;
148 166
149 // This still works even though we don't get the activation notification. 167 // This still works even though we don't get the activation notification.
150 return gtk_window_is_active(window_); 168 return gtk_window_is_active(window_);
151 } 169 }
152 170
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 235
218 void NativeAppWindowGtk::Activate() { 236 void NativeAppWindowGtk::Activate() {
219 gtk_window_present(window_); 237 gtk_window_present(window_);
220 } 238 }
221 239
222 void NativeAppWindowGtk::Deactivate() { 240 void NativeAppWindowGtk::Deactivate() {
223 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_))); 241 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
224 } 242 }
225 243
226 void NativeAppWindowGtk::Maximize() { 244 void NativeAppWindowGtk::Maximize() {
245 // Represent the window first in order to keep the maximization behavior
246 // consistency with Windows platform. Otherwise the window will be hidden if
247 // it has been minimized.
248 gtk_window_present(window_);
227 gtk_window_maximize(window_); 249 gtk_window_maximize(window_);
228 } 250 }
229 251
230 void NativeAppWindowGtk::Minimize() { 252 void NativeAppWindowGtk::Minimize() {
231 gtk_window_iconify(window_); 253 gtk_window_iconify(window_);
232 } 254 }
233 255
234 void NativeAppWindowGtk::Restore() { 256 void NativeAppWindowGtk::Restore() {
235 if (IsMaximized()) 257 if (IsMaximized())
236 gtk_window_unmaximize(window_); 258 gtk_window_unmaximize(window_);
237 else if (IsMinimized()) 259 else if (IsMinimized())
238 gtk_window_deiconify(window_); 260 gtk_window_deiconify(window_);
261
262 // Represent the window to keep restoration behavior consistency with Windows
263 // platform.
264 // TODO(zhchbin): verify whether we need this until http://crbug.com/261013 is
265 // fixed.
266 gtk_window_present(window_);
Daniel Erat 2013/07/18 20:18:39 i don't understand this call. http://crbug.com/261
zhchbin 2013/07/19 02:12:29 From our API docs, "Restore" means: "Restore the w
239 } 267 }
240 268
241 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) { 269 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
242 gfx::Rect content_bounds = bounds; 270 gfx::Rect content_bounds = bounds;
243 content_bounds.Inset(GetFrameInsets()); 271 content_bounds.Inset(GetFrameInsets());
244 gtk_window_move(window_, content_bounds.x(), content_bounds.y()); 272 gtk_window_move(window_, content_bounds.x(), content_bounds.y());
245 if (!resizable_) { 273 if (!resizable_) {
246 if (frameless_ && 274 if (frameless_ &&
247 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) { 275 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) {
248 content_bounds.set_height(content_bounds.height() - 1); 276 content_bounds.set_height(content_bounds.height() - 1);
249 } 277 }
250 // TODO(jeremya): set_size_request doesn't honor min/max size, so the 278 // TODO(jeremya): set_size_request doesn't honor min/max size, so the
251 // bounds should be constrained manually. 279 // bounds should be constrained manually.
252 gtk_widget_set_size_request(GTK_WIDGET(window_), 280 gtk_widget_set_size_request(GTK_WIDGET(window_),
253 content_bounds.width(), content_bounds.height()); 281 content_bounds.width(), content_bounds.height());
254 } else { 282 } else {
255 gtk_window_util::SetWindowSize(window_, 283 gtk_window_util::SetWindowSize(window_,
256 gfx::Size(bounds.width(), bounds.height())); 284 gfx::Size(bounds.width(), bounds.height()));
257 } 285 }
258 } 286 }
259 287
288 GdkFilterReturn NativeAppWindowGtk::OnXEvent(GdkXEvent* gdk_x_event,
289 GdkEvent* gdk_event) {
290 // Work around for gtk+ not reporting minimize state changes, by listening for
291 // property notify events for state and checking to see if the state includes
292 // hidden. Then from that setting or clearing the iconified bit.
Daniel Erat 2013/07/18 20:18:39 nit: reword this as: Work around GTK+ not repor
zhchbin 2013/07/19 02:12:29 Done.
293 // http://crbug.com/162794.
294 XEvent* x_event = static_cast<XEvent*>(gdk_x_event);
295 std::vector< ::Atom> atom_list;
296
297 if (x_event->type == PropertyNotify &&
298 x_event->xproperty.atom == atom_cache_.GetAtom("_NET_WM_STATE") &&
299 ui::GetAtomArrayProperty(GDK_WINDOW_XWINDOW(GTK_WIDGET(window_)->window),
300 "_NET_WM_STATE",
301 &atom_list)) {
302 std::vector< ::Atom>::iterator it =
303 std::find(atom_list.begin(),
304 atom_list.end(),
305 atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN"));
306 if (it != atom_list.end())
Evan Stade 2013/07/18 18:08:26 I prefer use of the ternary operator here. If no t
Daniel Erat 2013/07/18 20:18:39 agreed
zhchbin 2013/07/19 02:12:29 Done.
307 state_ = GDK_WINDOW_STATE_ICONIFIED;
308 else
309 state_ =
310 static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);
311
312 shell_window_->OnNativeWindowChanged();
313 }
314
315 return GDK_FILTER_CONTINUE;
316 }
317
260 void NativeAppWindowGtk::FlashFrame(bool flash) { 318 void NativeAppWindowGtk::FlashFrame(bool flash) {
261 gtk_window_set_urgency_hint(window_, flash); 319 gtk_window_set_urgency_hint(window_, flash);
262 } 320 }
263 321
264 bool NativeAppWindowGtk::IsAlwaysOnTop() const { 322 bool NativeAppWindowGtk::IsAlwaysOnTop() const {
265 return false; 323 return false;
266 } 324 }
267 325
268 void NativeAppWindowGtk::RenderViewHostChanged() { 326 void NativeAppWindowGtk::RenderViewHostChanged() {
269 web_contents()->GetView()->Focus(); 327 web_contents()->GetView()->Focus();
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 605
548 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions)); 606 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
549 } 607 }
550 608
551 // static 609 // static
552 NativeAppWindow* NativeAppWindow::Create( 610 NativeAppWindow* NativeAppWindow::Create(
553 ShellWindow* shell_window, 611 ShellWindow* shell_window,
554 const ShellWindow::CreateParams& params) { 612 const ShellWindow::CreateParams& params) {
555 return new NativeAppWindowGtk(shell_window, params); 613 return new NativeAppWindowGtk(shell_window, params);
556 } 614 }
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