| OLD | NEW |
| 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/shell_window_gtk.h" | 5 #include "chrome/browser/ui/gtk/extensions/shell_window_gtk.h" |
| 6 | 6 |
| 7 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
| 8 #include "chrome/browser/profiles/profile.h" | 8 #include "chrome/browser/profiles/profile.h" |
| 9 #include "chrome/browser/ui/gtk/gtk_window_util.h" | 9 #include "chrome/browser/ui/gtk/gtk_window_util.h" |
| 10 #include "chrome/browser/web_applications/web_app.h" | 10 #include "chrome/browser/web_applications/web_app.h" |
| 11 #include "chrome/common/extensions/draggable_region.h" | 11 #include "chrome/common/extensions/draggable_region.h" |
| 12 #include "chrome/common/extensions/extension.h" | 12 #include "chrome/common/extensions/extension.h" |
| 13 #include "content/public/browser/render_view_host.h" | 13 #include "content/public/browser/render_view_host.h" |
| 14 #include "content/public/browser/render_widget_host_view.h" | 14 #include "content/public/browser/render_widget_host_view.h" |
| 15 #include "content/public/browser/web_contents.h" | 15 #include "content/public/browser/web_contents.h" |
| 16 #include "content/public/browser/web_contents_view.h" | 16 #include "content/public/browser/web_contents_view.h" |
| 17 #include "ui/base/x/active_window_watcher_x.h" | 17 #include "ui/base/x/active_window_watcher_x.h" |
| 18 #include "ui/gfx/rect.h" | 18 #include "ui/gfx/rect.h" |
| 19 | 19 |
| 20 namespace { |
| 21 |
| 22 // The timeout in milliseconds before we'll get the true window position with |
| 23 // gtk_window_get_position() after the last GTK configure-event signal. |
| 24 const int kDebounceTimeoutMilliseconds = 100; |
| 25 |
| 26 } // namespace |
| 27 |
| 20 ShellWindowGtk::ShellWindowGtk(ShellWindow* shell_window, | 28 ShellWindowGtk::ShellWindowGtk(ShellWindow* shell_window, |
| 21 const ShellWindow::CreateParams& params) | 29 const ShellWindow::CreateParams& params) |
| 22 : shell_window_(shell_window), | 30 : shell_window_(shell_window), |
| 23 state_(GDK_WINDOW_STATE_WITHDRAWN), | 31 state_(GDK_WINDOW_STATE_WITHDRAWN), |
| 24 is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()), | 32 is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()), |
| 25 content_thinks_its_fullscreen_(false), | 33 content_thinks_its_fullscreen_(false), |
| 26 frameless_(params.frame == ShellWindow::CreateParams::FRAME_NONE) { | 34 frameless_(params.frame == ShellWindow::CreateParams::FRAME_NONE) { |
| 27 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); | 35 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); |
| 28 | 36 |
| 29 gfx::NativeView native_view = | 37 gfx::NativeView native_view = |
| 30 web_contents()->GetView()->GetNativeView(); | 38 web_contents()->GetView()->GetNativeView(); |
| 31 gtk_container_add(GTK_CONTAINER(window_), native_view); | 39 gtk_container_add(GTK_CONTAINER(window_), native_view); |
| 32 | 40 |
| 41 if (params.bounds.x() >= 0 && params.bounds.y() >= 0) |
| 42 gtk_window_move(window_, params.bounds.x(), params.bounds.y()); |
| 43 |
| 33 // This is done to avoid a WM "feature" where setting the window size to | 44 // This is done to avoid a WM "feature" where setting the window size to |
| 34 // the monitor size causes the WM to set the EWMH for full screen mode. | 45 // the monitor size causes the WM to set the EWMH for full screen mode. |
| 35 if (frameless_ && | 46 if (frameless_ && |
| 36 gtk_window_util::BoundsMatchMonitorSize(window_, params.bounds)) { | 47 gtk_window_util::BoundsMatchMonitorSize(window_, params.bounds)) { |
| 37 gtk_window_set_default_size( | 48 gtk_window_set_default_size( |
| 38 window_, params.bounds.width(), params.bounds.height() - 1); | 49 window_, params.bounds.width(), params.bounds.height() - 1); |
| 39 } else { | 50 } else { |
| 40 gtk_window_set_default_size( | 51 gtk_window_set_default_size( |
| 41 window_, params.bounds.width(), params.bounds.height()); | 52 window_, params.bounds.width(), params.bounds.height()); |
| 42 } | 53 } |
| 43 | 54 |
| 55 // make sure bounds_ and restored_bounds_ have correct values until we |
| 56 // get our first configure-event |
| 57 bounds_ = restored_bounds_ = params.bounds; |
| 58 gint x, y; |
| 59 gtk_window_get_position(window_, &x, &y); |
| 60 bounds_.set_origin(gfx::Point(x, y)); |
| 61 |
| 44 // Hide titlebar when {frame: 'none'} specified on ShellWindow. | 62 // Hide titlebar when {frame: 'none'} specified on ShellWindow. |
| 45 if (frameless_) | 63 if (frameless_) |
| 46 gtk_window_set_decorated(window_, false); | 64 gtk_window_set_decorated(window_, false); |
| 47 | 65 |
| 48 int min_width = params.minimum_size.width(); | 66 int min_width = params.minimum_size.width(); |
| 49 int min_height = params.minimum_size.height(); | 67 int min_height = params.minimum_size.height(); |
| 50 int max_width = params.maximum_size.width(); | 68 int max_width = params.maximum_size.width(); |
| 51 int max_height = params.maximum_size.height(); | 69 int max_height = params.maximum_size.height(); |
| 52 GdkGeometry hints; | 70 GdkGeometry hints; |
| 53 int hints_mask = 0; | 71 int hints_mask = 0; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 void ShellWindowGtk::Show() { | 148 void ShellWindowGtk::Show() { |
| 131 gtk_window_present(window_); | 149 gtk_window_present(window_); |
| 132 } | 150 } |
| 133 | 151 |
| 134 void ShellWindowGtk::ShowInactive() { | 152 void ShellWindowGtk::ShowInactive() { |
| 135 gtk_window_set_focus_on_map(window_, false); | 153 gtk_window_set_focus_on_map(window_, false); |
| 136 gtk_widget_show(GTK_WIDGET(window_)); | 154 gtk_widget_show(GTK_WIDGET(window_)); |
| 137 } | 155 } |
| 138 | 156 |
| 139 void ShellWindowGtk::Close() { | 157 void ShellWindowGtk::Close() { |
| 158 shell_window_->SaveWindowPosition(); |
| 159 |
| 160 // Cancel any pending callback from the window configure debounce timer. |
| 161 window_configure_debounce_timer_.Stop(); |
| 162 |
| 140 GtkWidget* window = GTK_WIDGET(window_); | 163 GtkWidget* window = GTK_WIDGET(window_); |
| 141 // To help catch bugs in any event handlers that might get fired during the | 164 // To help catch bugs in any event handlers that might get fired during the |
| 142 // destruction, set window_ to NULL before any handlers will run. | 165 // destruction, set window_ to NULL before any handlers will run. |
| 143 window_ = NULL; | 166 window_ = NULL; |
| 144 | 167 |
| 145 // OnNativeClose does a delete this so no other members should | 168 // OnNativeClose does a delete this so no other members should |
| 146 // be accessed after. gtk_widget_destroy is safe (and must | 169 // be accessed after. gtk_widget_destroy is safe (and must |
| 147 // be last). | 170 // be last). |
| 148 shell_window_->OnNativeClose(); | 171 shell_window_->OnNativeClose(); |
| 149 gtk_widget_destroy(window); | 172 gtk_widget_destroy(window); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 GdkEvent* event) { | 223 GdkEvent* event) { |
| 201 Close(); | 224 Close(); |
| 202 | 225 |
| 203 // Return true to prevent the GTK window from being destroyed. Close will | 226 // Return true to prevent the GTK window from being destroyed. Close will |
| 204 // destroy it for us. | 227 // destroy it for us. |
| 205 return TRUE; | 228 return TRUE; |
| 206 } | 229 } |
| 207 | 230 |
| 208 gboolean ShellWindowGtk::OnConfigure(GtkWidget* widget, | 231 gboolean ShellWindowGtk::OnConfigure(GtkWidget* widget, |
| 209 GdkEventConfigure* event) { | 232 GdkEventConfigure* event) { |
| 210 // TODO(mihaip): Do we need an explicit gtk_window_get_position call like in | 233 // We update |bounds_| but not |restored_bounds_| here. The latter needs |
| 211 // in BrowserWindowGtk::OnConfigure? | 234 // to be updated conditionally when the window is non-maximized and non- |
| 235 // fullscreen, but whether those state updates have been processed yet is |
| 236 // window-manager specific. We update |restored_bounds_| in the debounced |
| 237 // handler below, after the window state has been updated. |
| 212 bounds_.SetRect(event->x, event->y, event->width, event->height); | 238 bounds_.SetRect(event->x, event->y, event->width, event->height); |
| 213 if (!IsMaximized()) | 239 |
| 214 restored_bounds_ = bounds_; | 240 // The GdkEventConfigure* we get here doesn't have quite the right |
| 241 // coordinates though (they're relative to the drawable window area, rather |
| 242 // than any window manager decorations, if enabled), so we need to call |
| 243 // gtk_window_get_position() to get the right values. (Otherwise session |
| 244 // restore, if enabled, will restore windows to incorrect positions.) That's |
| 245 // a round trip to the X server though, so we set a debounce timer and only |
| 246 // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a |
| 247 // reconfigure event in a short while. |
| 248 // We don't use Reset() because the timer may not yet be running. |
| 249 // (In that case Stop() is a no-op.) |
| 250 window_configure_debounce_timer_.Stop(); |
| 251 window_configure_debounce_timer_.Start(FROM_HERE, |
| 252 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), this, |
| 253 &ShellWindowGtk::OnDebouncedBoundsChanged); |
| 215 | 254 |
| 216 return FALSE; | 255 return FALSE; |
| 217 } | 256 } |
| 218 | 257 |
| 258 void ShellWindowGtk::OnDebouncedBoundsChanged() { |
| 259 gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_); |
| 260 shell_window_->SaveWindowPosition(); |
| 261 } |
| 262 |
| 219 gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender, | 263 gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender, |
| 220 GdkEventWindowState* event) { | 264 GdkEventWindowState* event) { |
| 221 state_ = event->new_window_state; | 265 state_ = event->new_window_state; |
| 222 | 266 |
| 223 if (content_thinks_its_fullscreen_ && | 267 if (content_thinks_its_fullscreen_ && |
| 224 !(state_ & GDK_WINDOW_STATE_FULLSCREEN)) { | 268 !(state_ & GDK_WINDOW_STATE_FULLSCREEN)) { |
| 225 content_thinks_its_fullscreen_ = false; | 269 content_thinks_its_fullscreen_ = false; |
| 226 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); | 270 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); |
| 227 if (rvh) | 271 if (rvh) |
| 228 rvh->ExitFullscreen(); | 272 rvh->ExitFullscreen(); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 } | 354 } |
| 311 | 355 |
| 312 draggable_region_ = draggable_region; | 356 draggable_region_ = draggable_region; |
| 313 } | 357 } |
| 314 | 358 |
| 315 // static | 359 // static |
| 316 NativeShellWindow* NativeShellWindow::Create( | 360 NativeShellWindow* NativeShellWindow::Create( |
| 317 ShellWindow* shell_window, const ShellWindow::CreateParams& params) { | 361 ShellWindow* shell_window, const ShellWindow::CreateParams& params) { |
| 318 return new ShellWindowGtk(shell_window, params); | 362 return new ShellWindowGtk(shell_window, params); |
| 319 } | 363 } |
| OLD | NEW |