| 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/browser_window_gtk.h" | 5 #include "chrome/browser/ui/gtk/browser_window_gtk.h" |
| 6 | 6 |
| 7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 render_area_floating_container_(NULL), | 291 render_area_floating_container_(NULL), |
| 292 render_area_event_box_(NULL), | 292 render_area_event_box_(NULL), |
| 293 toolbar_border_(NULL), | 293 toolbar_border_(NULL), |
| 294 browser_(browser), | 294 browser_(browser), |
| 295 state_(GDK_WINDOW_STATE_WITHDRAWN), | 295 state_(GDK_WINDOW_STATE_WITHDRAWN), |
| 296 devtools_dock_side_(DEVTOOLS_DOCK_SIDE_BOTTOM), | 296 devtools_dock_side_(DEVTOOLS_DOCK_SIDE_BOTTOM), |
| 297 contents_hsplit_(NULL), | 297 contents_hsplit_(NULL), |
| 298 contents_vsplit_(NULL), | 298 contents_vsplit_(NULL), |
| 299 frame_cursor_(NULL), | 299 frame_cursor_(NULL), |
| 300 is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()), | 300 is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()), |
| 301 last_click_time_(0), | |
| 302 show_state_after_show_(ui::SHOW_STATE_DEFAULT), | 301 show_state_after_show_(ui::SHOW_STATE_DEFAULT), |
| 303 suppress_window_raise_(false), | 302 suppress_window_raise_(false), |
| 304 accel_group_(NULL), | 303 accel_group_(NULL), |
| 305 fullscreen_exit_bubble_type_( | 304 fullscreen_exit_bubble_type_( |
| 306 FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION) { | 305 FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION) { |
| 307 } | 306 } |
| 308 | 307 |
| 309 BrowserWindowGtk::~BrowserWindowGtk() { | 308 BrowserWindowGtk::~BrowserWindowGtk() { |
| 310 ui::ActiveWindowWatcherX::RemoveObserver(this); | 309 ui::ActiveWindowWatcherX::RemoveObserver(this); |
| 311 | 310 |
| (...skipping 1286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 // set window_ to NULL, otherwise we will try to close the window again when | 1597 // set window_ to NULL, otherwise we will try to close the window again when |
| 1599 // we call Close() in the destructor. | 1598 // we call Close() in the destructor. |
| 1600 // | 1599 // |
| 1601 // We don't want to use DeleteSoon() here since it won't work on a nested pump | 1600 // We don't want to use DeleteSoon() here since it won't work on a nested pump |
| 1602 // (like in UI tests). | 1601 // (like in UI tests). |
| 1603 MessageLoop::current()->PostTask( | 1602 MessageLoop::current()->PostTask( |
| 1604 FROM_HERE, base::Bind(&base::DeletePointer<BrowserWindowGtk>, this)); | 1603 FROM_HERE, base::Bind(&base::DeletePointer<BrowserWindowGtk>, this)); |
| 1605 } | 1604 } |
| 1606 | 1605 |
| 1607 void BrowserWindowGtk::UnMaximize() { | 1606 void BrowserWindowGtk::UnMaximize() { |
| 1608 gtk_window_unmaximize(window_); | 1607 gtk_window_util::UnMaximize(window_, bounds_, restored_bounds_); |
| 1609 | |
| 1610 // It can happen that you end up with a window whose restore size is the same | |
| 1611 // as the size of the screen, so unmaximizing it merely remaximizes it due to | |
| 1612 // the same WM feature that SetWindowSize() works around. We try to detect | |
| 1613 // this and resize the window to work around the issue. | |
| 1614 if (bounds_.size() == restored_bounds_.size()) | |
| 1615 gtk_window_resize(window_, bounds_.width(), bounds_.height() - 1); | |
| 1616 } | 1608 } |
| 1617 | 1609 |
| 1618 bool BrowserWindowGtk::CanClose() const { | 1610 bool BrowserWindowGtk::CanClose() const { |
| 1619 // You cannot close a frame for which there is an active originating drag | 1611 // You cannot close a frame for which there is an active originating drag |
| 1620 // session. | 1612 // session. |
| 1621 if (tabstrip_->IsDragSessionActive()) | 1613 if (tabstrip_->IsDragSessionActive()) |
| 1622 return false; | 1614 return false; |
| 1623 | 1615 |
| 1624 // Give beforeunload handlers the chance to cancel the close before we hide | 1616 // Give beforeunload handlers the chance to cancel the close before we hide |
| 1625 // the window below. | 1617 // the window below. |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2267 // If the toolbar is not showing, use the location of web contents as the | 2259 // If the toolbar is not showing, use the location of web contents as the |
| 2268 // boundary of where to ignore clicks. | 2260 // boundary of where to ignore clicks. |
| 2269 toolbar = render_area_vbox_; | 2261 toolbar = render_area_vbox_; |
| 2270 } | 2262 } |
| 2271 gint toolbar_y; | 2263 gint toolbar_y; |
| 2272 gtk_widget_get_pointer(toolbar, NULL, &toolbar_y); | 2264 gtk_widget_get_pointer(toolbar, NULL, &toolbar_y); |
| 2273 bool has_hit_titlebar = !IsFullscreen() && (toolbar_y < 0) | 2265 bool has_hit_titlebar = !IsFullscreen() && (toolbar_y < 0) |
| 2274 && !has_hit_edge; | 2266 && !has_hit_edge; |
| 2275 if (event->button == 1) { | 2267 if (event->button == 1) { |
| 2276 if (GDK_BUTTON_PRESS == event->type) { | 2268 if (GDK_BUTTON_PRESS == event->type) { |
| 2277 guint32 last_click_time = last_click_time_; | |
| 2278 gfx::Point last_click_position = last_click_position_; | |
| 2279 last_click_time_ = event->time; | |
| 2280 last_click_position_ = gfx::Point(static_cast<int>(event->x), | |
| 2281 static_cast<int>(event->y)); | |
| 2282 | |
| 2283 // Raise the window after a click on either the titlebar or the border to | 2269 // Raise the window after a click on either the titlebar or the border to |
| 2284 // match the behavior of most window managers, unless that behavior has | 2270 // match the behavior of most window managers, unless that behavior has |
| 2285 // been suppressed. | 2271 // been suppressed. |
| 2286 if ((has_hit_titlebar || has_hit_edge) && !suppress_window_raise_) | 2272 if ((has_hit_titlebar || has_hit_edge) && !suppress_window_raise_) |
| 2287 gdk_window_raise(gdk_window); | 2273 gdk_window_raise(gdk_window); |
| 2288 | 2274 |
| 2289 if (has_hit_titlebar) { | 2275 if (has_hit_titlebar) { |
| 2290 return HandleTitleBarLeftMousePress( | 2276 return HandleTitleBarLeftMousePress(event); |
| 2291 event, last_click_time, last_click_position); | |
| 2292 } else if (has_hit_edge) { | 2277 } else if (has_hit_edge) { |
| 2293 return HandleWindowEdgeLeftMousePress(window_, edge, event); | 2278 return HandleWindowEdgeLeftMousePress(window_, edge, event); |
| 2294 } | 2279 } |
| 2295 } else if (GDK_2BUTTON_PRESS == event->type) { | 2280 } else if (GDK_2BUTTON_PRESS == event->type) { |
| 2296 if (has_hit_titlebar) { | 2281 if (has_hit_titlebar) { |
| 2297 // Maximize/restore on double click. | 2282 // Maximize/restore on double click. |
| 2298 if (IsMaximized()) { | 2283 if (IsMaximized()) { |
| 2299 UnMaximize(); | 2284 UnMaximize(); |
| 2300 } else { | 2285 } else { |
| 2301 gtk_window_maximize(window_); | 2286 gtk_window_maximize(window_); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2312 if (has_hit_titlebar) { | 2297 if (has_hit_titlebar) { |
| 2313 titlebar_->ShowContextMenu(event); | 2298 titlebar_->ShowContextMenu(event); |
| 2314 return TRUE; | 2299 return TRUE; |
| 2315 } | 2300 } |
| 2316 } | 2301 } |
| 2317 | 2302 |
| 2318 return FALSE; // Continue to propagate the event. | 2303 return FALSE; // Continue to propagate the event. |
| 2319 } | 2304 } |
| 2320 | 2305 |
| 2321 bool BrowserWindowGtk::HandleTitleBarLeftMousePress( | 2306 bool BrowserWindowGtk::HandleTitleBarLeftMousePress( |
| 2322 GdkEventButton* event, | 2307 GdkEventButton* event) { |
| 2323 guint32 last_click_time, | 2308 return gtk_window_util::HandleTitleBarLeftMousePress(window_, bounds_, event); |
| 2324 gfx::Point last_click_position) { | |
| 2325 // We want to start a move when the user single clicks, but not start a | |
| 2326 // move when the user double clicks. However, a double click sends the | |
| 2327 // following GDK events: GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE, | |
| 2328 // GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE. If we | |
| 2329 // start a gtk_window_begin_move_drag on the second GDK_BUTTON_PRESS, | |
| 2330 // the call to gtk_window_maximize fails. To work around this, we | |
| 2331 // keep track of the last click and if it's going to be a double click, | |
| 2332 // we don't call gtk_window_begin_move_drag. | |
| 2333 static GtkSettings* settings = gtk_settings_get_default(); | |
| 2334 gint double_click_time = 250; | |
| 2335 gint double_click_distance = 5; | |
| 2336 g_object_get(G_OBJECT(settings), | |
| 2337 "gtk-double-click-time", &double_click_time, | |
| 2338 "gtk-double-click-distance", &double_click_distance, | |
| 2339 NULL); | |
| 2340 | |
| 2341 guint32 click_time = event->time - last_click_time; | |
| 2342 int click_move_x = abs(event->x - last_click_position.x()); | |
| 2343 int click_move_y = abs(event->y - last_click_position.y()); | |
| 2344 | |
| 2345 if (click_time > static_cast<guint32>(double_click_time) || | |
| 2346 click_move_x > double_click_distance || | |
| 2347 click_move_y > double_click_distance) { | |
| 2348 // Ignore drag requests if the window is the size of the screen. | |
| 2349 // We do this to avoid triggering fullscreen mode in metacity | |
| 2350 // (without the --no-force-fullscreen flag) and in compiz (with | |
| 2351 // Legacy Fullscreen Mode enabled). | |
| 2352 if (!BoundsMatchMonitorSize()) { | |
| 2353 gtk_window_begin_move_drag(window_, event->button, | |
| 2354 static_cast<gint>(event->x_root), | |
| 2355 static_cast<gint>(event->y_root), | |
| 2356 event->time); | |
| 2357 } | |
| 2358 return TRUE; | |
| 2359 } | |
| 2360 return FALSE; | |
| 2361 } | 2309 } |
| 2362 | 2310 |
| 2363 bool BrowserWindowGtk::HandleWindowEdgeLeftMousePress( | 2311 bool BrowserWindowGtk::HandleWindowEdgeLeftMousePress( |
| 2364 GtkWindow* window, | 2312 GtkWindow* window, |
| 2365 GdkWindowEdge edge, | 2313 GdkWindowEdge edge, |
| 2366 GdkEventButton* event) { | 2314 GdkEventButton* event) { |
| 2367 gtk_window_begin_resize_drag(window, edge, event->button, | 2315 gtk_window_begin_resize_drag(window, edge, event->button, |
| 2368 static_cast<gint>(event->x_root), | 2316 static_cast<gint>(event->x_root), |
| 2369 static_cast<gint>(event->y_root), | 2317 static_cast<gint>(event->y_root), |
| 2370 event->time); | 2318 event->time); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2489 | 2437 |
| 2490 NOTREACHED(); | 2438 NOTREACHED(); |
| 2491 return false; | 2439 return false; |
| 2492 } | 2440 } |
| 2493 | 2441 |
| 2494 bool BrowserWindowGtk::UseCustomFrame() const { | 2442 bool BrowserWindowGtk::UseCustomFrame() const { |
| 2495 // We don't use the custom frame for app mode windows or app window popups. | 2443 // We don't use the custom frame for app mode windows or app window popups. |
| 2496 return use_custom_frame_pref_.GetValue() && !browser_->is_app(); | 2444 return use_custom_frame_pref_.GetValue() && !browser_->is_app(); |
| 2497 } | 2445 } |
| 2498 | 2446 |
| 2499 bool BrowserWindowGtk::BoundsMatchMonitorSize() { | |
| 2500 // A screen can be composed of multiple monitors. | |
| 2501 GdkScreen* screen = gtk_window_get_screen(window_); | |
| 2502 gint monitor_num = gdk_screen_get_monitor_at_window(screen, | |
| 2503 gtk_widget_get_window(GTK_WIDGET(window_))); | |
| 2504 | |
| 2505 GdkRectangle monitor_size; | |
| 2506 gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor_size); | |
| 2507 return bounds_.size() == gfx::Size(monitor_size.width, monitor_size.height); | |
| 2508 } | |
| 2509 | |
| 2510 void BrowserWindowGtk::PlaceBookmarkBar(bool is_floating) { | 2447 void BrowserWindowGtk::PlaceBookmarkBar(bool is_floating) { |
| 2511 TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::PlaceBookmarkBar"); | 2448 TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::PlaceBookmarkBar"); |
| 2512 | 2449 |
| 2513 GtkWidget* target_parent = NULL; | 2450 GtkWidget* target_parent = NULL; |
| 2514 if (!is_floating) { | 2451 if (!is_floating) { |
| 2515 // Place the bookmark bar at the end of |window_vbox_|; this happens after | 2452 // Place the bookmark bar at the end of |window_vbox_|; this happens after |
| 2516 // we have placed the render area at the end of |window_vbox_| so we will | 2453 // we have placed the render area at the end of |window_vbox_| so we will |
| 2517 // be above the render area. | 2454 // be above the render area. |
| 2518 target_parent = window_vbox_; | 2455 target_parent = window_vbox_; |
| 2519 } else { | 2456 } else { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2552 wm_type == ui::WM_OPENBOX || | 2489 wm_type == ui::WM_OPENBOX || |
| 2553 wm_type == ui::WM_XFWM4); | 2490 wm_type == ui::WM_XFWM4); |
| 2554 } | 2491 } |
| 2555 | 2492 |
| 2556 // static | 2493 // static |
| 2557 BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) { | 2494 BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) { |
| 2558 BrowserWindowGtk* browser_window_gtk = new BrowserWindowGtk(browser); | 2495 BrowserWindowGtk* browser_window_gtk = new BrowserWindowGtk(browser); |
| 2559 browser_window_gtk->Init(); | 2496 browser_window_gtk->Init(); |
| 2560 return browser_window_gtk; | 2497 return browser_window_gtk; |
| 2561 } | 2498 } |
| OLD | NEW |