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

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: Update comment. 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 }
130 141
142 // If _NET_WM_STATE_HIDDEN is in _NET_SUPPORTED, listen for XEvent to work
143 // around GTK+ not reporting minimization state changes. See comment in the
144 // |OnXEvent|.
145 std::vector< ::Atom> supported_atoms;
146 if (ui::GetAtomArrayProperty(ui::GetX11RootWindow(),
147 "_NET_SUPPORTED",
148 &supported_atoms)) {
149 if (std::find(supported_atoms.begin(),
150 supported_atoms.end(),
151 atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN")) !=
152 supported_atoms.end()) {
153 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(window_));
154 gdk_window_add_filter(window,
155 &NativeAppWindowGtk::OnXEventThunk,
156 this);
157 }
158 }
159
131 // Add the keybinding registry. 160 // Add the keybinding registry.
132 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk( 161 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
133 shell_window_->profile(), 162 shell_window_->profile(),
134 window_, 163 window_,
135 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, 164 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
136 shell_window_)); 165 shell_window_));
137 166
138 ui::ActiveWindowWatcherX::AddObserver(this); 167 ui::ActiveWindowWatcherX::AddObserver(this);
139 } 168 }
140 169
141 NativeAppWindowGtk::~NativeAppWindowGtk() { 170 NativeAppWindowGtk::~NativeAppWindowGtk() {
142 ui::ActiveWindowWatcherX::RemoveObserver(this); 171 ui::ActiveWindowWatcherX::RemoveObserver(this);
172 gdk_window_remove_filter(NULL,
Daniel Erat 2013/07/20 01:29:30 is this safe to call when the filter wasn't added?
zhchbin 2013/07/20 02:14:31 Done.
173 &NativeAppWindowGtk::OnXEventThunk,
174 this);
143 } 175 }
144 176
145 bool NativeAppWindowGtk::IsActive() const { 177 bool NativeAppWindowGtk::IsActive() const {
146 if (ui::ActiveWindowWatcherX::WMSupportsActivation()) 178 if (ui::ActiveWindowWatcherX::WMSupportsActivation())
147 return is_active_; 179 return is_active_;
148 180
149 // This still works even though we don't get the activation notification. 181 // This still works even though we don't get the activation notification.
150 return gtk_window_is_active(window_); 182 return gtk_window_is_active(window_);
151 } 183 }
152 184
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 249
218 void NativeAppWindowGtk::Activate() { 250 void NativeAppWindowGtk::Activate() {
219 gtk_window_present(window_); 251 gtk_window_present(window_);
220 } 252 }
221 253
222 void NativeAppWindowGtk::Deactivate() { 254 void NativeAppWindowGtk::Deactivate() {
223 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_))); 255 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
224 } 256 }
225 257
226 void NativeAppWindowGtk::Maximize() { 258 void NativeAppWindowGtk::Maximize() {
259 // Represent the window first in order to keep the maximization behavior
260 // consistency with Windows platform. Otherwise the window will be hidden if
261 // it has been minimized.
262 gtk_window_present(window_);
227 gtk_window_maximize(window_); 263 gtk_window_maximize(window_);
228 } 264 }
229 265
230 void NativeAppWindowGtk::Minimize() { 266 void NativeAppWindowGtk::Minimize() {
231 gtk_window_iconify(window_); 267 gtk_window_iconify(window_);
232 } 268 }
233 269
234 void NativeAppWindowGtk::Restore() { 270 void NativeAppWindowGtk::Restore() {
235 if (IsMaximized()) 271 if (IsMaximized())
236 gtk_window_unmaximize(window_); 272 gtk_window_unmaximize(window_);
237 else if (IsMinimized()) 273 else if (IsMinimized())
238 gtk_window_deiconify(window_); 274 gtk_window_deiconify(window_);
275
276 // Represent the window to keep restoration behavior consistency with Windows
277 // platform.
278 // TODO(zhchbin): verify whether we need this until http://crbug.com/261013 is
279 // fixed.
280 gtk_window_present(window_);
239 } 281 }
240 282
241 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) { 283 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
242 gfx::Rect content_bounds = bounds; 284 gfx::Rect content_bounds = bounds;
243 content_bounds.Inset(GetFrameInsets()); 285 content_bounds.Inset(GetFrameInsets());
244 gtk_window_move(window_, content_bounds.x(), content_bounds.y()); 286 gtk_window_move(window_, content_bounds.x(), content_bounds.y());
245 if (!resizable_) { 287 if (!resizable_) {
246 if (frameless_ && 288 if (frameless_ &&
247 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) { 289 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) {
248 content_bounds.set_height(content_bounds.height() - 1); 290 content_bounds.set_height(content_bounds.height() - 1);
249 } 291 }
250 // TODO(jeremya): set_size_request doesn't honor min/max size, so the 292 // TODO(jeremya): set_size_request doesn't honor min/max size, so the
251 // bounds should be constrained manually. 293 // bounds should be constrained manually.
252 gtk_widget_set_size_request(GTK_WIDGET(window_), 294 gtk_widget_set_size_request(GTK_WIDGET(window_),
253 content_bounds.width(), content_bounds.height()); 295 content_bounds.width(), content_bounds.height());
254 } else { 296 } else {
255 gtk_window_util::SetWindowSize(window_, 297 gtk_window_util::SetWindowSize(window_,
256 gfx::Size(bounds.width(), bounds.height())); 298 gfx::Size(bounds.width(), bounds.height()));
257 } 299 }
258 } 300 }
259 301
302 GdkFilterReturn NativeAppWindowGtk::OnXEvent(GdkXEvent* gdk_x_event,
303 GdkEvent* gdk_event) {
304 // Work around GTK+ not reporting minimization state changes. Listen
305 // for _NET_WM_STATE property changes and use _NET_WM_STATE_HIDDEN's
306 // presence to set or clear the iconified bit if _NET_WM_STATE_HIDDEN
307 // is supported. http://crbug.com/162794.
308 XEvent* x_event = static_cast<XEvent*>(gdk_x_event);
309 std::vector< ::Atom> atom_list;
310
311 if (x_event->type == PropertyNotify &&
312 x_event->xproperty.atom == atom_cache_.GetAtom("_NET_WM_STATE") &&
313 ui::GetAtomArrayProperty(GDK_WINDOW_XWINDOW(GTK_WIDGET(window_)->window),
314 "_NET_WM_STATE",
315 &atom_list)) {
316 std::vector< ::Atom>::iterator it =
317 std::find(atom_list.begin(),
318 atom_list.end(),
319 atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN"));
320 state_ = (it != atom_list.end()) ? GDK_WINDOW_STATE_ICONIFIED :
321 static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);
322
323 shell_window_->OnNativeWindowChanged();
324 }
325
326 return GDK_FILTER_CONTINUE;
327 }
328
260 void NativeAppWindowGtk::FlashFrame(bool flash) { 329 void NativeAppWindowGtk::FlashFrame(bool flash) {
261 gtk_window_set_urgency_hint(window_, flash); 330 gtk_window_set_urgency_hint(window_, flash);
262 } 331 }
263 332
264 bool NativeAppWindowGtk::IsAlwaysOnTop() const { 333 bool NativeAppWindowGtk::IsAlwaysOnTop() const {
265 return false; 334 return false;
266 } 335 }
267 336
268 void NativeAppWindowGtk::RenderViewHostChanged() { 337 void NativeAppWindowGtk::RenderViewHostChanged() {
269 web_contents()->GetView()->Focus(); 338 web_contents()->GetView()->Focus();
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 616
548 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions)); 617 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
549 } 618 }
550 619
551 // static 620 // static
552 NativeAppWindow* NativeAppWindow::Create( 621 NativeAppWindow* NativeAppWindow::Create(
553 ShellWindow* shell_window, 622 ShellWindow* shell_window,
554 const ShellWindow::CreateParams& params) { 623 const ShellWindow::CreateParams& params) {
555 return new NativeAppWindowGtk(shell_window, params); 624 return new NativeAppWindowGtk(shell_window, params);
556 } 625 }
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