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/app_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/extensions/extension_keybinding_registry_gtk.h" | 9 #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h" |
10 #include "chrome/browser/ui/gtk/gtk_util.h" | 10 #include "chrome/browser/ui/gtk/gtk_util.h" |
11 #include "chrome/browser/ui/gtk/gtk_window_util.h" | 11 #include "chrome/browser/ui/gtk/gtk_window_util.h" |
12 #include "chrome/browser/web_applications/web_app.h" | 12 #include "chrome/browser/web_applications/web_app.h" |
13 #include "chrome/common/extensions/extension.h" | 13 #include "chrome/common/extensions/extension.h" |
14 #include "content/public/browser/render_view_host.h" | 14 #include "content/public/browser/render_view_host.h" |
15 #include "content/public/browser/render_widget_host_view.h" | 15 #include "content/public/browser/render_widget_host_view.h" |
16 #include "content/public/browser/web_contents.h" | 16 #include "content/public/browser/web_contents.h" |
17 #include "content/public/browser/web_contents_view.h" | 17 #include "content/public/browser/web_contents_view.h" |
18 #include "ui/base/x/active_window_watcher_x.h" | 18 #include "ui/base/x/active_window_watcher_x.h" |
19 #include "ui/gfx/image/image.h" | 19 #include "ui/gfx/image/image.h" |
20 #include "ui/gfx/rect.h" | 20 #include "ui/gfx/rect.h" |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 // The timeout in milliseconds before we'll get the true window position with | 24 // The timeout in milliseconds before we'll get the true window position with |
25 // gtk_window_get_position() after the last GTK configure-event signal. | 25 // gtk_window_get_position() after the last GTK configure-event signal. |
26 const int kDebounceTimeoutMilliseconds = 100; | 26 const int kDebounceTimeoutMilliseconds = 100; |
27 | 27 |
28 } // namespace | 28 } // namespace |
29 | 29 |
30 ShellWindowGtk::ShellWindowGtk(ShellWindow* shell_window, | 30 AppWindowGtk::AppWindowGtk(ShellWindow* shell_window, |
31 const ShellWindow::CreateParams& params) | 31 const ShellWindow::CreateParams& params) |
32 : shell_window_(shell_window), | 32 : shell_window_(shell_window), |
33 window_(NULL), | 33 window_(NULL), |
34 state_(GDK_WINDOW_STATE_WITHDRAWN), | 34 state_(GDK_WINDOW_STATE_WITHDRAWN), |
35 is_active_(false), | 35 is_active_(false), |
36 content_thinks_its_fullscreen_(false), | 36 content_thinks_its_fullscreen_(false), |
37 frameless_(params.frame == ShellWindow::CreateParams::FRAME_NONE) { | 37 frameless_(params.frame == ShellWindow::CreateParams::FRAME_NONE) { |
38 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); | 38 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); |
39 | 39 |
40 gfx::NativeView native_view = | 40 gfx::NativeView native_view = |
41 web_contents()->GetView()->GetNativeView(); | 41 web_contents()->GetView()->GetNativeView(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 // Add the keybinding registry. | 116 // Add the keybinding registry. |
117 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk( | 117 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk( |
118 shell_window_->profile(), | 118 shell_window_->profile(), |
119 window_, | 119 window_, |
120 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, | 120 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, |
121 shell_window_)); | 121 shell_window_)); |
122 | 122 |
123 ui::ActiveWindowWatcherX::AddObserver(this); | 123 ui::ActiveWindowWatcherX::AddObserver(this); |
124 } | 124 } |
125 | 125 |
126 ShellWindowGtk::~ShellWindowGtk() { | 126 AppWindowGtk::~AppWindowGtk() { |
127 ui::ActiveWindowWatcherX::RemoveObserver(this); | 127 ui::ActiveWindowWatcherX::RemoveObserver(this); |
128 } | 128 } |
129 | 129 |
130 bool ShellWindowGtk::IsActive() const { | 130 bool AppWindowGtk::IsActive() const { |
131 if (ui::ActiveWindowWatcherX::WMSupportsActivation()) | 131 if (ui::ActiveWindowWatcherX::WMSupportsActivation()) |
132 return is_active_; | 132 return is_active_; |
133 | 133 |
134 // This still works even though we don't get the activation notification. | 134 // This still works even though we don't get the activation notification. |
135 return gtk_window_is_active(window_); | 135 return gtk_window_is_active(window_); |
136 } | 136 } |
137 | 137 |
138 bool ShellWindowGtk::IsMaximized() const { | 138 bool AppWindowGtk::IsMaximized() const { |
139 return (state_ & GDK_WINDOW_STATE_MAXIMIZED); | 139 return (state_ & GDK_WINDOW_STATE_MAXIMIZED); |
140 } | 140 } |
141 | 141 |
142 bool ShellWindowGtk::IsMinimized() const { | 142 bool AppWindowGtk::IsMinimized() const { |
143 return (state_ & GDK_WINDOW_STATE_ICONIFIED); | 143 return (state_ & GDK_WINDOW_STATE_ICONIFIED); |
144 } | 144 } |
145 | 145 |
146 bool ShellWindowGtk::IsFullscreen() const { | 146 bool AppWindowGtk::IsFullscreen() const { |
147 return false; | 147 return false; |
148 } | 148 } |
149 | 149 |
150 gfx::NativeWindow ShellWindowGtk::GetNativeWindow() { | 150 gfx::NativeWindow AppWindowGtk::GetNativeWindow() { |
151 return window_; | 151 return window_; |
152 } | 152 } |
153 | 153 |
154 gfx::Rect ShellWindowGtk::GetRestoredBounds() const { | 154 gfx::Rect AppWindowGtk::GetRestoredBounds() const { |
155 return restored_bounds_; | 155 return restored_bounds_; |
156 } | 156 } |
157 | 157 |
158 gfx::Rect ShellWindowGtk::GetBounds() const { | 158 gfx::Rect AppWindowGtk::GetBounds() const { |
159 return bounds_; | 159 return bounds_; |
160 } | 160 } |
161 | 161 |
162 void ShellWindowGtk::Show() { | 162 void AppWindowGtk::Show() { |
163 gtk_window_present(window_); | 163 gtk_window_present(window_); |
164 } | 164 } |
165 | 165 |
166 void ShellWindowGtk::ShowInactive() { | 166 void AppWindowGtk::ShowInactive() { |
167 gtk_window_set_focus_on_map(window_, false); | 167 gtk_window_set_focus_on_map(window_, false); |
168 gtk_widget_show(GTK_WIDGET(window_)); | 168 gtk_widget_show(GTK_WIDGET(window_)); |
169 } | 169 } |
170 | 170 |
171 void ShellWindowGtk::Hide() { | 171 void AppWindowGtk::Hide() { |
172 gtk_widget_hide(GTK_WIDGET(window_)); | 172 gtk_widget_hide(GTK_WIDGET(window_)); |
173 } | 173 } |
174 | 174 |
175 void ShellWindowGtk::Close() { | 175 void AppWindowGtk::Close() { |
176 shell_window_->SaveWindowPosition(); | 176 shell_window_->SaveWindowPosition(); |
177 | 177 |
178 // Cancel any pending callback from the window configure debounce timer. | 178 // Cancel any pending callback from the window configure debounce timer. |
179 window_configure_debounce_timer_.Stop(); | 179 window_configure_debounce_timer_.Stop(); |
180 | 180 |
181 GtkWidget* window = GTK_WIDGET(window_); | 181 GtkWidget* window = GTK_WIDGET(window_); |
182 // To help catch bugs in any event handlers that might get fired during the | 182 // To help catch bugs in any event handlers that might get fired during the |
183 // destruction, set window_ to NULL before any handlers will run. | 183 // destruction, set window_ to NULL before any handlers will run. |
184 window_ = NULL; | 184 window_ = NULL; |
185 | 185 |
186 // OnNativeClose does a delete this so no other members should | 186 // OnNativeClose does a delete this so no other members should |
187 // be accessed after. gtk_widget_destroy is safe (and must | 187 // be accessed after. gtk_widget_destroy is safe (and must |
188 // be last). | 188 // be last). |
189 shell_window_->OnNativeClose(); | 189 shell_window_->OnNativeClose(); |
190 gtk_widget_destroy(window); | 190 gtk_widget_destroy(window); |
191 } | 191 } |
192 | 192 |
193 void ShellWindowGtk::Activate() { | 193 void AppWindowGtk::Activate() { |
194 gtk_window_present(window_); | 194 gtk_window_present(window_); |
195 } | 195 } |
196 | 196 |
197 void ShellWindowGtk::Deactivate() { | 197 void AppWindowGtk::Deactivate() { |
198 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_))); | 198 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_))); |
199 } | 199 } |
200 | 200 |
201 void ShellWindowGtk::Maximize() { | 201 void AppWindowGtk::Maximize() { |
202 gtk_window_maximize(window_); | 202 gtk_window_maximize(window_); |
203 } | 203 } |
204 | 204 |
205 void ShellWindowGtk::Minimize() { | 205 void AppWindowGtk::Minimize() { |
206 gtk_window_iconify(window_); | 206 gtk_window_iconify(window_); |
207 } | 207 } |
208 | 208 |
209 void ShellWindowGtk::Restore() { | 209 void AppWindowGtk::Restore() { |
210 if (IsMaximized()) | 210 if (IsMaximized()) |
211 gtk_window_unmaximize(window_); | 211 gtk_window_unmaximize(window_); |
212 else if (IsMinimized()) | 212 else if (IsMinimized()) |
213 gtk_window_deiconify(window_); | 213 gtk_window_deiconify(window_); |
214 } | 214 } |
215 | 215 |
216 void ShellWindowGtk::SetBounds(const gfx::Rect& bounds) { | 216 void AppWindowGtk::SetBounds(const gfx::Rect& bounds) { |
217 gtk_window_move(window_, bounds.x(), bounds.y()); | 217 gtk_window_move(window_, bounds.x(), bounds.y()); |
218 gtk_window_util::SetWindowSize(window_, | 218 gtk_window_util::SetWindowSize(window_, |
219 gfx::Size(bounds.width(), bounds.height())); | 219 gfx::Size(bounds.width(), bounds.height())); |
220 } | 220 } |
221 | 221 |
222 void ShellWindowGtk::FlashFrame(bool flash) { | 222 void AppWindowGtk::FlashFrame(bool flash) { |
223 gtk_window_set_urgency_hint(window_, flash); | 223 gtk_window_set_urgency_hint(window_, flash); |
224 } | 224 } |
225 | 225 |
226 bool ShellWindowGtk::IsAlwaysOnTop() const { | 226 bool AppWindowGtk::IsAlwaysOnTop() const { |
227 return false; | 227 return false; |
228 } | 228 } |
229 | 229 |
230 void ShellWindowGtk::ActiveWindowChanged(GdkWindow* active_window) { | 230 void AppWindowGtk::ActiveWindowChanged(GdkWindow* active_window) { |
231 // Do nothing if we're in the process of closing the browser window. | 231 // Do nothing if we're in the process of closing the browser window. |
232 if (!window_) | 232 if (!window_) |
233 return; | 233 return; |
234 | 234 |
235 is_active_ = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window; | 235 is_active_ = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window; |
236 } | 236 } |
237 | 237 |
238 // Callback for the delete event. This event is fired when the user tries to | 238 // Callback for the delete event. This event is fired when the user tries to |
239 // close the window (e.g., clicking on the X in the window manager title bar). | 239 // close the window (e.g., clicking on the X in the window manager title bar). |
240 gboolean ShellWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget, | 240 gboolean AppWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget, |
241 GdkEvent* event) { | 241 GdkEvent* event) { |
242 Close(); | 242 Close(); |
243 | 243 |
244 // Return true to prevent the GTK window from being destroyed. Close will | 244 // Return true to prevent the GTK window from being destroyed. Close will |
245 // destroy it for us. | 245 // destroy it for us. |
246 return TRUE; | 246 return TRUE; |
247 } | 247 } |
248 | 248 |
249 gboolean ShellWindowGtk::OnConfigure(GtkWidget* widget, | 249 gboolean AppWindowGtk::OnConfigure(GtkWidget* widget, |
250 GdkEventConfigure* event) { | 250 GdkEventConfigure* event) { |
251 // We update |bounds_| but not |restored_bounds_| here. The latter needs | 251 // We update |bounds_| but not |restored_bounds_| here. The latter needs |
252 // to be updated conditionally when the window is non-maximized and non- | 252 // to be updated conditionally when the window is non-maximized and non- |
253 // fullscreen, but whether those state updates have been processed yet is | 253 // fullscreen, but whether those state updates have been processed yet is |
254 // window-manager specific. We update |restored_bounds_| in the debounced | 254 // window-manager specific. We update |restored_bounds_| in the debounced |
255 // handler below, after the window state has been updated. | 255 // handler below, after the window state has been updated. |
256 bounds_.SetRect(event->x, event->y, event->width, event->height); | 256 bounds_.SetRect(event->x, event->y, event->width, event->height); |
257 | 257 |
258 // The GdkEventConfigure* we get here doesn't have quite the right | 258 // The GdkEventConfigure* we get here doesn't have quite the right |
259 // coordinates though (they're relative to the drawable window area, rather | 259 // coordinates though (they're relative to the drawable window area, rather |
260 // than any window manager decorations, if enabled), so we need to call | 260 // than any window manager decorations, if enabled), so we need to call |
261 // gtk_window_get_position() to get the right values. (Otherwise session | 261 // gtk_window_get_position() to get the right values. (Otherwise session |
262 // restore, if enabled, will restore windows to incorrect positions.) That's | 262 // restore, if enabled, will restore windows to incorrect positions.) That's |
263 // a round trip to the X server though, so we set a debounce timer and only | 263 // a round trip to the X server though, so we set a debounce timer and only |
264 // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a | 264 // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a |
265 // reconfigure event in a short while. | 265 // reconfigure event in a short while. |
266 // We don't use Reset() because the timer may not yet be running. | 266 // We don't use Reset() because the timer may not yet be running. |
267 // (In that case Stop() is a no-op.) | 267 // (In that case Stop() is a no-op.) |
268 window_configure_debounce_timer_.Stop(); | 268 window_configure_debounce_timer_.Stop(); |
269 window_configure_debounce_timer_.Start(FROM_HERE, | 269 window_configure_debounce_timer_.Start(FROM_HERE, |
270 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), this, | 270 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), this, |
271 &ShellWindowGtk::OnDebouncedBoundsChanged); | 271 &AppWindowGtk::OnDebouncedBoundsChanged); |
272 | 272 |
273 return FALSE; | 273 return FALSE; |
274 } | 274 } |
275 | 275 |
276 void ShellWindowGtk::OnDebouncedBoundsChanged() { | 276 void AppWindowGtk::OnDebouncedBoundsChanged() { |
277 gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_); | 277 gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_); |
278 shell_window_->SaveWindowPosition(); | 278 shell_window_->SaveWindowPosition(); |
279 } | 279 } |
280 | 280 |
281 gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender, | 281 gboolean AppWindowGtk::OnWindowState(GtkWidget* sender, |
282 GdkEventWindowState* event) { | 282 GdkEventWindowState* event) { |
283 state_ = event->new_window_state; | 283 state_ = event->new_window_state; |
284 | 284 |
285 if (content_thinks_its_fullscreen_ && | 285 if (content_thinks_its_fullscreen_ && |
286 !(state_ & GDK_WINDOW_STATE_FULLSCREEN)) { | 286 !(state_ & GDK_WINDOW_STATE_FULLSCREEN)) { |
287 content_thinks_its_fullscreen_ = false; | 287 content_thinks_its_fullscreen_ = false; |
288 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); | 288 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); |
289 if (rvh) | 289 if (rvh) |
290 rvh->ExitFullscreen(); | 290 rvh->ExitFullscreen(); |
291 } | 291 } |
292 | 292 |
293 return FALSE; | 293 return FALSE; |
294 } | 294 } |
295 | 295 |
296 gboolean ShellWindowGtk::OnButtonPress(GtkWidget* widget, | 296 gboolean AppWindowGtk::OnButtonPress(GtkWidget* widget, |
297 GdkEventButton* event) { | 297 GdkEventButton* event) { |
298 if (draggable_region_ && draggable_region_->contains(event->x, event->y)) { | 298 if (draggable_region_ && draggable_region_->contains(event->x, event->y)) { |
299 if (event->button == 1) { | 299 if (event->button == 1) { |
300 if (GDK_BUTTON_PRESS == event->type) { | 300 if (GDK_BUTTON_PRESS == event->type) { |
301 if (!suppress_window_raise_) | 301 if (!suppress_window_raise_) |
302 gdk_window_raise(GTK_WIDGET(widget)->window); | 302 gdk_window_raise(GTK_WIDGET(widget)->window); |
303 | 303 |
304 return gtk_window_util::HandleTitleBarLeftMousePress( | 304 return gtk_window_util::HandleTitleBarLeftMousePress( |
305 GTK_WINDOW(widget), bounds_, event); | 305 GTK_WINDOW(widget), bounds_, event); |
306 } else if (GDK_2BUTTON_PRESS == event->type) { | 306 } else if (GDK_2BUTTON_PRESS == event->type) { |
307 bool is_maximized = gdk_window_get_state(GTK_WIDGET(widget)->window) & | 307 bool is_maximized = gdk_window_get_state(GTK_WIDGET(widget)->window) & |
308 GDK_WINDOW_STATE_MAXIMIZED; | 308 GDK_WINDOW_STATE_MAXIMIZED; |
309 if (is_maximized) { | 309 if (is_maximized) { |
310 gtk_window_util::UnMaximize(GTK_WINDOW(widget), | 310 gtk_window_util::UnMaximize(GTK_WINDOW(widget), |
311 bounds_, restored_bounds_); | 311 bounds_, restored_bounds_); |
312 } else { | 312 } else { |
313 gtk_window_maximize(GTK_WINDOW(widget)); | 313 gtk_window_maximize(GTK_WINDOW(widget)); |
314 } | 314 } |
315 return TRUE; | 315 return TRUE; |
316 } | 316 } |
317 } else if (event->button == 2) { | 317 } else if (event->button == 2) { |
318 gdk_window_lower(GTK_WIDGET(widget)->window); | 318 gdk_window_lower(GTK_WIDGET(widget)->window); |
319 return TRUE; | 319 return TRUE; |
320 } | 320 } |
321 } | 321 } |
322 | 322 |
323 return FALSE; | 323 return FALSE; |
324 } | 324 } |
325 | 325 |
326 void ShellWindowGtk::SetFullscreen(bool fullscreen) { | 326 void AppWindowGtk::SetFullscreen(bool fullscreen) { |
327 content_thinks_its_fullscreen_ = fullscreen; | 327 content_thinks_its_fullscreen_ = fullscreen; |
328 if (fullscreen) | 328 if (fullscreen) |
329 gtk_window_fullscreen(window_); | 329 gtk_window_fullscreen(window_); |
330 else | 330 else |
331 gtk_window_unfullscreen(window_); | 331 gtk_window_unfullscreen(window_); |
332 } | 332 } |
333 | 333 |
334 bool ShellWindowGtk::IsFullscreenOrPending() const { | 334 bool AppWindowGtk::IsFullscreenOrPending() const { |
335 return content_thinks_its_fullscreen_; | 335 return content_thinks_its_fullscreen_; |
336 } | 336 } |
337 | 337 |
338 void ShellWindowGtk::UpdateWindowIcon() { | 338 void AppWindowGtk::UpdateWindowIcon() { |
339 Profile* profile = shell_window_->profile(); | 339 Profile* profile = shell_window_->profile(); |
340 gfx::Image app_icon = shell_window_->app_icon(); | 340 gfx::Image app_icon = shell_window_->app_icon(); |
341 if (!app_icon.IsEmpty()) | 341 if (!app_icon.IsEmpty()) |
342 gtk_util::SetWindowIcon(window_, profile, app_icon.ToGdkPixbuf()); | 342 gtk_util::SetWindowIcon(window_, profile, app_icon.ToGdkPixbuf()); |
343 else | 343 else |
344 gtk_util::SetWindowIcon(window_, profile); | 344 gtk_util::SetWindowIcon(window_, profile); |
345 } | 345 } |
346 | 346 |
347 void ShellWindowGtk::UpdateWindowTitle() { | 347 void AppWindowGtk::UpdateWindowTitle() { |
348 string16 title = shell_window_->GetTitle(); | 348 string16 title = shell_window_->GetTitle(); |
349 gtk_window_set_title(window_, UTF16ToUTF8(title).c_str()); | 349 gtk_window_set_title(window_, UTF16ToUTF8(title).c_str()); |
350 } | 350 } |
351 | 351 |
352 void ShellWindowGtk::HandleKeyboardEvent( | 352 void AppWindowGtk::HandleKeyboardEvent( |
353 const content::NativeWebKeyboardEvent& event) { | 353 const content::NativeWebKeyboardEvent& event) { |
354 // No-op. | 354 // No-op. |
355 } | 355 } |
356 | 356 |
357 void ShellWindowGtk::UpdateDraggableRegions( | 357 void AppWindowGtk::UpdateDraggableRegions( |
358 const std::vector<extensions::DraggableRegion>& regions) { | 358 const std::vector<extensions::DraggableRegion>& regions) { |
359 // Draggable region is not supported for non-frameless window. | 359 // Draggable region is not supported for non-frameless window. |
360 if (!frameless_) | 360 if (!frameless_) |
361 return; | 361 return; |
362 | 362 |
363 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions)); | 363 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions)); |
364 } | 364 } |
365 | 365 |
366 // static | 366 // static |
367 NativeShellWindow* NativeShellWindow::Create( | 367 AppBaseWindow* AppBaseWindow::Create( |
368 ShellWindow* shell_window, const ShellWindow::CreateParams& params) { | 368 ShellWindow* shell_window, const ShellWindow::CreateParams& params) { |
369 return new ShellWindowGtk(shell_window, params); | 369 return new AppWindowGtk(shell_window, params); |
370 } | 370 } |
OLD | NEW |