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

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: Enable PlatformAppBrowserTest.WindowsApiProperties on GTK. 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
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 gtk_window_present(window_);
scheib 2013/07/16 22:11:21 I'm not sure why this is needed here?
zhchbin 2013/07/17 02:39:32 After minimize the app window, calling maximize sh
scheib 2013/07/17 04:47:39 Ah! I agree that we should move the different syst
zhchbin 2013/07/17 09:05:36 Done.
227 gtk_window_maximize(window_); 246 gtk_window_maximize(window_);
228 } 247 }
229 248
230 void NativeAppWindowGtk::Minimize() { 249 void NativeAppWindowGtk::Minimize() {
231 gtk_window_iconify(window_); 250 gtk_window_iconify(window_);
232 } 251 }
233 252
234 void NativeAppWindowGtk::Restore() { 253 void NativeAppWindowGtk::Restore() {
235 if (IsMaximized()) 254 if (IsMaximized())
236 gtk_window_unmaximize(window_); 255 gtk_window_unmaximize(window_);
237 else if (IsMinimized()) 256 else if (IsMinimized())
238 gtk_window_deiconify(window_); 257 gtk_window_deiconify(window_);
258
259 gtk_window_present(window_);
scheib 2013/07/16 22:11:21 We should only present if the window isn't hidden
zhchbin 2013/07/17 02:39:32 However, I find these behavior are different on th
scheib 2013/07/17 04:47:39 Hmm, on win7 with window state sample (from github
zhchbin 2013/07/17 09:05:36 Done.
239 } 260 }
240 261
241 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) { 262 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
242 gfx::Rect content_bounds = bounds; 263 gfx::Rect content_bounds = bounds;
243 content_bounds.Inset(GetFrameInsets()); 264 content_bounds.Inset(GetFrameInsets());
244 gtk_window_move(window_, content_bounds.x(), content_bounds.y()); 265 gtk_window_move(window_, content_bounds.x(), content_bounds.y());
245 if (!resizable_) { 266 if (!resizable_) {
246 if (frameless_ && 267 if (frameless_ &&
247 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) { 268 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) {
248 content_bounds.set_height(content_bounds.height() - 1); 269 content_bounds.set_height(content_bounds.height() - 1);
249 } 270 }
250 // TODO(jeremya): set_size_request doesn't honor min/max size, so the 271 // TODO(jeremya): set_size_request doesn't honor min/max size, so the
251 // bounds should be constrained manually. 272 // bounds should be constrained manually.
252 gtk_widget_set_size_request(GTK_WIDGET(window_), 273 gtk_widget_set_size_request(GTK_WIDGET(window_),
253 content_bounds.width(), content_bounds.height()); 274 content_bounds.width(), content_bounds.height());
254 } else { 275 } else {
255 gtk_window_util::SetWindowSize(window_, 276 gtk_window_util::SetWindowSize(window_,
256 gfx::Size(bounds.width(), bounds.height())); 277 gfx::Size(bounds.width(), bounds.height()));
257 } 278 }
258 } 279 }
259 280
281 GdkFilterReturn NativeAppWindowGtk::OnXEvent(GdkXEvent* xevent,
scheib 2013/07/16 22:11:21 Please add a comment explaining why this method is
zhchbin 2013/07/17 02:39:32 Done.
scheib 2013/07/17 04:47:39 Thank you, though the comment needs a bit more cle
zhchbin 2013/07/17 09:05:36 Done.
282 GdkEvent* event) {
283 XEvent* xev = static_cast<XEvent*>(xevent);
scheib 2013/07/16 22:11:21 name it xevent, and name the method parameter gdkx
zhchbin 2013/07/17 02:39:32 Done.
284 ::Atom state = atom_cache_.GetAtom("_NET_WM_STATE");
scheib 2013/07/16 22:11:21 variable only used once, right? Consider calling G
zhchbin 2013/07/17 02:39:32 Done.
285 std::vector< ::Atom> atom_list;
286
287 if (xev->type == PropertyNotify &&
288 xev->xproperty.atom == state &&
289 ui::GetAtomArrayProperty(GDK_WINDOW_XWINDOW(GTK_WIDGET(window_)->window),
290 "_NET_WM_STATE",
291 &atom_list)) {
292 ::Atom state_hidden = atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN");
293 std::vector< ::Atom>::iterator it = std::find(atom_list.begin(),
294 atom_list.end(),
295 state_hidden);
scheib 2013/07/16 22:11:21 One thing I don't understand is why the hidden ato
zhchbin 2013/07/17 02:39:32 Glance through the source code of "gtk_widget_hide
296 if (it != atom_list.end())
297 state_ = GDK_WINDOW_STATE_ICONIFIED;
298 else
299 state_ =
300 static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);
301
302 shell_window_->OnNativeWindowChanged();
303 }
304
305 return GDK_FILTER_CONTINUE;
306 }
307
260 void NativeAppWindowGtk::FlashFrame(bool flash) { 308 void NativeAppWindowGtk::FlashFrame(bool flash) {
261 gtk_window_set_urgency_hint(window_, flash); 309 gtk_window_set_urgency_hint(window_, flash);
262 } 310 }
263 311
264 bool NativeAppWindowGtk::IsAlwaysOnTop() const { 312 bool NativeAppWindowGtk::IsAlwaysOnTop() const {
265 return false; 313 return false;
266 } 314 }
267 315
268 void NativeAppWindowGtk::RenderViewHostChanged() { 316 void NativeAppWindowGtk::RenderViewHostChanged() {
269 web_contents()->GetView()->Focus(); 317 web_contents()->GetView()->Focus();
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 595
548 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions)); 596 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
549 } 597 }
550 598
551 // static 599 // static
552 NativeAppWindow* NativeAppWindow::Create( 600 NativeAppWindow* NativeAppWindow::Create(
553 ShellWindow* shell_window, 601 ShellWindow* shell_window,
554 const ShellWindow::CreateParams& params) { 602 const ShellWindow::CreateParams& params) {
555 return new NativeAppWindowGtk(shell_window, params); 603 return new NativeAppWindowGtk(shell_window, params);
556 } 604 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698