172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_window_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gdk/gdkkeysyms.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <dlfcn.h>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/base_paths.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/environment.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/i18n/file_util_icu.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/nix/xdg_util.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h"
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/app/chrome_command_ids.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_utils.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/debugger/devtools_window.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_item_model.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_manager.h"
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/page_info_window.h"
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h"
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h"
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/themes/theme_service.h"
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/browser_dialogs.h"
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/find_bar/find_bar_controller.h"
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/find_bar/find_tab_helper.h"
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/about_chrome_dialog.h"
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/accelerators_gtk.h"
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h"
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_titlebar.h"
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/collected_cookies_gtk.h"
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h"
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/download/download_in_progress_dialog_gtk.h"
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/download/download_shelf_gtk.h"
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/edit_search_engine_dialog.h"
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/find_bar_gtk.h"
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h"
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/global_menu_bar.h"
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_floating_container.h"
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/infobars/infobar_container_gtk.h"
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/nine_box.h"
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/reload_button_gtk.h"
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/repost_form_warning_gtk.h"
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/status_bubble_gtk.h"
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/task_manager_gtk.h"
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/theme_install_bubble_view_gtk.h"
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/update_recommended_dialog.h"
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/omnibox/location_bar.h"
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/bug_report_ui.h"
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/window_sizer.h"
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/web_applications/web_app.h"
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h"
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/render_widget_host_view.h"
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_view.h"
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/native_web_keyboard_event.h"
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h"
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h"
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/keycodes/keyboard_codes.h"
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h"
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/rect.h"
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skia_utils_gtk.h"
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of milliseconds between loading animation frames.
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kLoadingAnimationFrameTimeMs = 30;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Default height of dev tools pane when docked to the browser window.  This
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// matches the value in Views.
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDefaultDevToolsHeight = 200;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
105513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst int kMinDevToolsHeight = 50;
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kBrowserWindowKey = "__BROWSER_WINDOW_GTK__";
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The frame border is only visible in restored mode and is hardcoded to 4 px
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on each side regardless of the system window border size.
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kFrameBorderThickness = 4;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// While resize areas on Windows are normally the same size as the window
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// borders, our top area is shrunk by 1 px to make it easier to move the window
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// around with our thinner top grabbable strip.  (Incidentally, our side and
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// bottom resize areas don't match the frame border thickness either -- they
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// span the whole nonclient area, so there's no "dead zone" for the mouse.)
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTopResizeAdjust = 1;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In the window corners, the resize areas don't actually expand bigger, but
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the 16 px at the end of each edge triggers diagonal resizing.
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kResizeAreaCornerSize = 16;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The thickness of the shadow around the toolbar+web content area.  There are
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// actually a couple pixels more that should overlap the toolbar and web
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// content area, but we don't use those pixels.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kContentShadowThickness = 2;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The offset to the background when the custom frame is off.  We want the
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// window background to line up with the tab background regardless of whether
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// we're in custom frame mode or not.  Since themes are designed with the
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// custom frame in mind, we need to offset the background when the custom frame
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is off.
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCustomFrameBackgroundVerticalOffset = 15;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The timeout in milliseconds before we'll get the true window position with
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// gtk_window_get_position() after the last GTK configure-event signal.
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDebounceTimeoutMilliseconds = 100;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Ubuntu patches their verrsion of GTK+ so that there is always a
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// gripper in the bottom right corner of the window. We dynamically
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// look up this symbol because it's a non-standard Ubuntu extension to
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// GTK+. We always need to disable this feature since we can't
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// communicate this to WebKit easily.
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsentypedef void (*gtk_window_set_has_resize_grip_func)(GtkWindow*, gboolean);
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsengtk_window_set_has_resize_grip_func gtk_window_set_has_resize_grip_sym;
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid  EnsureResizeGripFunction() {
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static bool resize_grip_looked_up = false;
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!resize_grip_looked_up) {
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    resize_grip_looked_up = true;
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    gtk_window_set_has_resize_grip_sym =
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        reinterpret_cast<gtk_window_set_has_resize_grip_func>(
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            dlsym(NULL, "gtk_window_set_has_resize_grip"));
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Using gtk_window_get_position/size creates a race condition, so only use
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// this to get the initial bounds.  After window creation, we pick up the
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// normal bounds by connecting to the configure-event signal.
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect GetInitialWindowBounds(GtkWindow* window) {
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint x, y, width, height;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_position(window, &x, &y);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_size(window, &width, &height);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(x, y, width, height);
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Get the command ids of the key combinations that are not valid gtk
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// accelerators.
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint GetCustomCommandId(GdkEventKey* event) {
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Filter modifier to only include accelerator modifiers.
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (event->keyval) {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Gtk doesn't allow GDK_Tab or GDK_ISO_Left_Tab to be an accelerator (see
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // gtk_accelerator_valid), so we need to handle these accelerators
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // manually.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Some X clients (e.g. cygwin, NX client, etc.) also send GDK_KP_Tab when
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // typing a tab key. We should also handle GDK_KP_Tab for such X clients as
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Firefox does.
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Tab:
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_ISO_Left_Tab:
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_KP_Tab:
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (GDK_CONTROL_MASK == modifier) {
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return IDC_SELECT_NEXT_TAB;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return IDC_SELECT_PREVIOUS_TAB;
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return -1;
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Get the command ids of the accelerators that we don't want the native widget
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to be able to override.
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint GetPreHandleCommandId(GdkEventKey* event) {
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Filter modifier to only include accelerator modifiers.
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (event->keyval) {
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Page_Down:
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (GDK_CONTROL_MASK == modifier) {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return IDC_SELECT_NEXT_TAB;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return IDC_MOVE_TAB_NEXT;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Page_Up:
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (GDK_CONTROL_MASK == modifier) {
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return IDC_SELECT_PREVIOUS_TAB;
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return IDC_MOVE_TAB_PREVIOUS;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return -1;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGdkCursorType GdkWindowEdgeToGdkCursorType(GdkWindowEdge edge) {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (edge) {
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_NORTH_WEST:
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_TOP_LEFT_CORNER;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_NORTH:
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_TOP_SIDE;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_NORTH_EAST:
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_TOP_RIGHT_CORNER;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_WEST:
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_LEFT_SIDE;
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_EAST:
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_RIGHT_SIDE;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_SOUTH_WEST:
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_BOTTOM_LEFT_CORNER;
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_SOUTH:
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_BOTTOM_SIDE;
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_WINDOW_EDGE_SOUTH_EAST:
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return GDK_BOTTOM_RIGHT_CORNER;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GDK_LAST_CURSOR;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A helper method for setting the GtkWindow size that should be used in place
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// of calling gtk_window_resize directly.  This is done to avoid a WM "feature"
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// where setting the window size to the monitor size causes the WM to set the
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// EWMH for full screen mode.
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SetWindowSize(GtkWindow* window, const gfx::Size& size) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkScreen* screen = gtk_window_get_screen(window);
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gint num_monitors = gdk_screen_get_n_monitors(screen);
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure the window doesn't match any monitor size.  We compare against
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // all monitors because we don't know which monitor the window is going to
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // open on (the WM decides that).
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (gint i = 0; i < num_monitors; ++i) {
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    GdkRectangle monitor_size;
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    gdk_screen_get_monitor_geometry(screen, i, &monitor_size);
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (gfx::Size(monitor_size.width, monitor_size.height) == size) {
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      gtk_window_resize(window, size.width(), size.height() - 1);
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return;
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_window_resize(window, size.width(), size.height());
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGQuark GetBrowserWindowQuarkKey() {
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static GQuark quark = g_quark_from_static_string(kBrowserWindowKey);
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return quark;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::map<XID, GtkWindow*> BrowserWindowGtk::xid_map_;
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserWindowGtk::BrowserWindowGtk(Browser* browser)
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    :  browser_(browser),
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       state_(GDK_WINDOW_STATE_WITHDRAWN),
277731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       bookmark_bar_is_floating_(false),
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       frame_cursor_(NULL),
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()),
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       last_click_time_(0),
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       maximize_after_show_(false),
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       suppress_window_raise_(false),
283731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       accel_group_(NULL),
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       debounce_timer_disabled_(false),
285513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch       infobar_arrow_model_(this) {
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBrowserWindowGtk::~BrowserWindowGtk() {
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ui::ActiveWindowWatcherX::RemoveObserver(this);
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser_->tabstrip_model()->RemoveObserver(this);
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserWindowGtk::Init() {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We register first so that other views like the toolbar can use the
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // is_active() function in their ActiveWindowChanged() handlers.
29772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::ActiveWindowWatcherX::AddObserver(this);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  use_custom_frame_pref_.Init(prefs::kUseCustomChromeFrame,
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_->profile()->GetPrefs(), this);
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // In some (older) versions of compiz, raising top-level windows when they
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // are partially off-screen causes them to get snapped back on screen, not
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // always even on the current virtual desktop.  If we are running under
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // compiz, suppress such raises, as they are not necessary in compiz anyway.
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string wm_name;
30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::GetWindowManagerName(&wm_name) && wm_name == "compiz")
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    suppress_window_raise_ = true;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_set_qdata(G_OBJECT(window_), GetBrowserWindowQuarkKey(), this);
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_add_events(GTK_WIDGET(window_), GDK_BUTTON_PRESS_MASK |
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             GDK_POINTER_MOTION_MASK);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Disable the resize gripper on Ubuntu.
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EnsureResizeGripFunction();
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (gtk_window_set_has_resize_grip_sym)
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    gtk_window_set_has_resize_grip_sym(GTK_WINDOW(window_), FALSE);
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add this window to its own unique window group to allow for
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window-to-parent modality.
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_group_add_window(gtk_window_group_new(), window_);
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(gtk_window_get_group(window_));
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (browser_->type() & Browser::TYPE_APP) {
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string app_name = browser_->app_name();
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (app_name != DevToolsWindow::kDevToolsApp) {
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::string wmclassname = web_app::GetWMClassFromAppName(app_name);
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      scoped_ptr<base::Environment> env(base::Environment::Create());
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (base::nix::GetDesktopEnvironment(env.get()) ==
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::nix::DESKTOP_ENVIRONMENT_XFCE) {
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Workaround for XFCE. XFCE seems to treat the class as a user
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // displayed title, which our app name certainly isn't. They don't have
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // a dock or application based behaviour so do what looks good.
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        gtk_window_set_wmclass(window_,
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               wmclassname.c_str(),
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               gdk_get_program_class());
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      } else {
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Most everything else uses the wmclass_class to group windows
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // together (docks, per application stuff, etc). Hopefully they won't
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // display wmclassname to the user.
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        gtk_window_set_wmclass(window_,
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               g_get_prgname(),
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               wmclassname.c_str());
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      gtk_window_set_role(window_, wmclassname.c_str());
349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // For popups, we initialize widgets then set the window geometry, because
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // popups need the widgets inited before they can set the window size
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // properly. For other windows, we set the geometry first to prevent resize
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // flicker.
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_->type() & Browser::TYPE_POPUP) {
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InitWidgets();
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetGeometryHints();
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetGeometryHints();
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InitWidgets();
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ConnectAccelerators();
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the initial background color of widgets.
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetBackgroundColor();
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HideUnsupportedWindowFeatures();
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  registrar_.Add(this, NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 NotificationService::AllSources());
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget,
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                               GdkEventExpose* event) {
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the default background.
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_cairo_rectangle(cr, &event->area);
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_clip(cr);
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (UsingCustomPopupFrame()) {
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DrawPopupFrame(cr, widget, event);
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DrawCustomFrame(cr, widget, event);
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DrawContentShadow(cr);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_destroy(cr);
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (UseCustomFrame() && !IsMaximized()) {
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    static NineBox custom_frame_border(
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_TOP_LEFT_CORNER,
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_TOP_CENTER,
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_TOP_RIGHT_CORNER,
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_LEFT_SIDE,
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        0,
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_RIGHT_SIDE,
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_BOTTOM_LEFT_CORNER,
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_BOTTOM_CENTER,
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_WINDOW_BOTTOM_RIGHT_CORNER);
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    custom_frame_border.RenderToWidget(widget);
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;  // Allow subwidgets to paint.
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::DrawContentShadow(cairo_t* cr) {
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the shadow above the toolbar. Tabs on the tabstrip will draw over us.
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GtkThemeService* theme_provider = GtkThemeService::GetFrom(
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser()->profile());
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int left_x, top_y;
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_translate_coordinates(toolbar_->widget(),
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_WIDGET(window_), 0, 0, &left_x,
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &top_y);
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int center_width = window_vbox_->allocation.width;
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* top_center = theme_provider->GetSurfaceNamed(
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_CONTENT_TOP_CENTER, GTK_WIDGET(window_));
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* top_right = theme_provider->GetSurfaceNamed(
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_CONTENT_TOP_RIGHT_CORNER, GTK_WIDGET(window_));
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* top_left = theme_provider->GetSurfaceNamed(
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_CONTENT_TOP_LEFT_CORNER, GTK_WIDGET(window_));
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int center_left_x = left_x;
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ShouldDrawContentDropShadow()) {
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Don't draw over the corners.
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    center_left_x += top_left->Width() - kContentShadowThickness;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    center_width -= (top_left->Width() + top_right->Width());
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    center_width += 2 * kContentShadowThickness;
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  top_center->SetSource(cr, center_left_x, top_y - kContentShadowThickness);
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_rectangle(cr, center_left_x, top_y - kContentShadowThickness,
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  center_width, top_center->Height());
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_fill(cr);
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Only draw the rest of the shadow if the user has the custom frame enabled
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and the browser is not maximized.
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ShouldDrawContentDropShadow())
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The top left corner has a width of 3 pixels. On Windows, the last column
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of pixels overlap the toolbar. We just crop it off on Linux.  The top
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // corners extend to the base of the toolbar (one pixel above the dividing
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // line).
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int right_x = center_left_x + center_width;
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  top_left->SetSource(
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      cr, left_x - kContentShadowThickness, top_y - kContentShadowThickness);
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The toolbar is shorter in location bar only mode so clip the image to the
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // height of the toolbar + the amount of shadow above the toolbar.
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_rectangle(cr,
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      left_x - kContentShadowThickness,
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_y - kContentShadowThickness,
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_left->Width(),
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_left->Height());
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_fill(cr);
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Likewise, we crop off the left column of pixels for the top right corner.
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  top_right->SetSource(cr, right_x, top_y - kContentShadowThickness);
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_rectangle(cr,
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      right_x,
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_y - kContentShadowThickness,
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_right->Width(),
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_right->Height());
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_fill(cr);
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Fill in the sides.  As above, we only draw 2 of the 3 columns on Linux.
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int bottom_y;
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_translate_coordinates(window_vbox_,
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_WIDGET(window_),
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, window_vbox_->allocation.height,
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL, &bottom_y);
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |side_y| is where to start drawing the side shadows.  The top corners draw
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the sides down to the bottom of the toolbar.
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int side_y = top_y - kContentShadowThickness + top_right->Height();
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |side_height| is how many pixels to draw for the side borders.  We do one
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pixel before the bottom of the web contents because that extra pixel is
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // drawn by the bottom corners.
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int side_height = bottom_y - side_y - 1;
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (side_height > 0) {
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CairoCachedSurface* left = theme_provider->GetSurfaceNamed(
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_CONTENT_LEFT_SIDE, GTK_WIDGET(window_));
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    left->SetSource(cr, left_x - kContentShadowThickness, side_y);
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_rectangle(cr,
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        left_x - kContentShadowThickness,
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        side_y,
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kContentShadowThickness,
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        side_height);
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_fill(cr);
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CairoCachedSurface* right = theme_provider->GetSurfaceNamed(
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_CONTENT_RIGHT_SIDE, GTK_WIDGET(window_));
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int right_side_x =
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        right_x + top_right->Width() - kContentShadowThickness - 1;
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    right->SetSource(cr, right_side_x, side_y);
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_rectangle(cr,
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        right_side_x,
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        side_y,
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kContentShadowThickness,
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        side_height);
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_fill(cr);
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the bottom corners.  The bottom corners also draw the bottom row of
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pixels of the side shadows.
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* bottom_left = theme_provider->GetSurfaceNamed(
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_CONTENT_BOTTOM_LEFT_CORNER, GTK_WIDGET(window_));
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bottom_left->SetSource(cr, left_x - kContentShadowThickness, bottom_y - 1);
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_paint(cr);
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* bottom_right = theme_provider->GetSurfaceNamed(
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_CONTENT_BOTTOM_RIGHT_CORNER, GTK_WIDGET(window_));
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bottom_right->SetSource(cr, right_x - 1, bottom_y - 1);
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_paint(cr);
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Finally, draw the bottom row. Since we don't overlap the contents, we clip
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the top row of pixels.
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* bottom = theme_provider->GetSurfaceNamed(
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_CONTENT_BOTTOM_CENTER, GTK_WIDGET(window_));
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bottom->SetSource(cr, left_x + 1, bottom_y - 1);
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_rectangle(cr,
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      left_x + 1,
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bottom_y,
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      window_vbox_->allocation.width - 2,
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kContentShadowThickness);
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_fill(cr);
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::DrawPopupFrame(cairo_t* cr,
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      GtkWidget* widget,
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      GdkEventExpose* event) {
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GtkThemeService* theme_provider = GtkThemeService::GetFrom(
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser()->profile());
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Like DrawCustomFrame(), except that we use the unthemed resources to draw
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the background. We do this because we can't rely on sane images in the
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // theme that we can draw text on. (We tried using the tab background, but
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that has inverse saturation from what the user usually expects).
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int image_name = GetThemeFrameResource();
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* surface = theme_provider->GetUnthemedSurfaceNamed(
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      image_name, widget);
548201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  surface->SetSource(cr, 0, GetVerticalOffset());
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REFLECT);
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_rectangle(cr, event->area.x, event->area.y,
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  event->area.width, event->area.height);
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_fill(cr);
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::DrawCustomFrame(cairo_t* cr,
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       GtkWidget* widget,
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       GdkEventExpose* event) {
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GtkThemeService* theme_provider = GtkThemeService::GetFrom(
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser()->profile());
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int image_name = GetThemeFrameResource();
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CairoCachedSurface* surface = theme_provider->GetSurfaceNamed(
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      image_name, widget);
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event->area.y < surface->Height()) {
566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    surface->SetSource(cr, 0, GetVerticalOffset());
5674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The frame background isn't tiled vertically.
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_rectangle(cr, event->area.x, event->area.y,
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    event->area.width, surface->Height() - event->area.y);
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_fill(cr);
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (theme_provider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) &&
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !browser()->profile()->IsOffTheRecord()) {
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CairoCachedSurface* theme_overlay = theme_provider->GetSurfaceNamed(
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IsActive() ? IDR_THEME_FRAME_OVERLAY
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        : IDR_THEME_FRAME_OVERLAY_INACTIVE, widget);
580201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    theme_overlay->SetSource(cr, 0, GetVerticalOffset());
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_paint(cr);
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
585201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochint BrowserWindowGtk::GetVerticalOffset() {
586201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return (IsMaximized() || (!UseCustomFrame())) ?
587201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      -kCustomFrameBackgroundVerticalOffset : 0;
588201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserWindowGtk::GetThemeFrameResource() {
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool incognito = browser()->profile()->IsOffTheRecord();
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int image_name;
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsActive()) {
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    image_name = incognito ? IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    image_name = incognito ? IDR_THEME_FRAME_INCOGNITO_INACTIVE :
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 IDR_THEME_FRAME_INACTIVE;
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return image_name;
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::Show() {
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The Browser associated with this browser window must become the active
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // browser at the time Show() is called. This is the natural behaviour under
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows, but gtk_widget_show won't show the widget (and therefore won't
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // call OnFocusIn()) until we return to the runloop. Therefore any calls to
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // BrowserList::GetLastActive() (for example, in bookmark_util), will return
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the previous browser instead if we don't explicitly set it here.
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserList::SetLastActive(browser());
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_present(window_);
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (maximize_after_show_) {
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_maximize(window_);
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    maximize_after_show_ = false;
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we have sized the window by setting a size request for the render
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // area, then undo it so that the render view can later adjust its own
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // size.
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_size_request(contents_container_->widget(), -1, -1);
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserWindowGtk::ShowInactive() {
625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gtk_window_set_focus_on_map(window_, false);
626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gtk_widget_show(GTK_WIDGET(window_));
627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
6293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowserWindowGtk::SetBoundsImpl(const gfx::Rect& bounds,
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     bool exterior,
6313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     bool move) {
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint x = static_cast<gint>(bounds.x());
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint y = static_cast<gint>(bounds.y());
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint width = static_cast<gint>(bounds.width());
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint height = static_cast<gint>(bounds.height());
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (move)
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    gtk_window_move(window_, x, y);
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (exterior) {
6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SetWindowSize(window_, gfx::Size(width, height));
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(contents_container_->widget(),
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                width, height);
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::SetBounds(const gfx::Rect& bounds) {
64972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (IsFullscreen())
65072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SetFullscreen(false);
6513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetBoundsImpl(bounds, true, true);
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::Close() {
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We're already closing.  Do nothing.
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!window_)
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!CanClose())
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We're going to destroy the window, make sure the tab strip isn't running
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // any animations which may still reference GtkWidgets.
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tabstrip_->StopAnimation();
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SaveWindowPosition();
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (accel_group_) {
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Disconnecting the keys we connected to our accelerator group frees the
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // closures allocated in ConnectAccelerators.
67121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         iter != accelerators->end(); ++iter) {
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_accel_group_disconnect_key(accel_group_,
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          iter->second.GetGdkKeyCode(),
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          static_cast<GdkModifierType>(iter->second.modifiers()));
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_remove_accel_group(window_, accel_group_);
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_object_unref(accel_group_);
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    accel_group_ = NULL;
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancel any pending callback from the window configure debounce timer.
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_configure_debounce_timer_.Stop();
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Likewise for the loading animation.
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  loading_animation_timer_.Stop();
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* window = GTK_WIDGET(window_);
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // To help catch bugs in any event handlers that might get fired during the
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // destruction, set window_ to NULL before any handlers will run.
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_ = NULL;
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_->set_window(NULL);
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_destroy(window);
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::Activate() {
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_present(window_);
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowserWindowGtk::Deactivate() {
7023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gdk_window_lower(GTK_WIDGET(window_)->window);
7033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsActive() const {
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return is_active_;
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::FlashFrame() {
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // May not be respected by all window managers.
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_urgency_hint(window_, TRUE);
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::NativeWindow BrowserWindowGtk::GetNativeHandle() {
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return window_;
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserWindowTesting* BrowserWindowGtk::GetBrowserWindowTesting() {
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochStatusBubble* BrowserWindowGtk::GetStatusBubble() {
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return status_bubble_.get();
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserWindowGtk::ToolbarSizeChanged(bool is_animating) {
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // On Windows, this is used for a performance optimization.
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // http://code.google.com/p/chromium/issues/detail?id=12291
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UpdateTitleBar() {
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 title = browser_->GetWindowTitleForCurrentTab();
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_title(window_, UTF16ToUTF8(title).c_str());
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ShouldShowWindowIcon())
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    titlebar_->UpdateTitleAndIcon();
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShelfVisibilityChanged() {
740201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MaybeShowBookmarkBar(false);
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UpdateDevTools() {
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateDevToolsForContents(
745201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      browser_->GetSelectedTabContents());
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UpdateLoadingAnimations(bool should_animate) {
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (should_animate) {
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!loading_animation_timer_.IsRunning()) {
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Loads are happening, and the timer isn't running, so start it.
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      loading_animation_timer_.Start(
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          base::TimeDelta::FromMilliseconds(kLoadingAnimationFrameTimeMs), this,
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &BrowserWindowGtk::LoadingAnimationCallback);
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (loading_animation_timer_.IsRunning()) {
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      loading_animation_timer_.Stop();
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Loads are now complete, update the state if a task was scheduled.
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LoadingAnimationCallback();
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::LoadingAnimationCallback() {
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_->type() == Browser::TYPE_NORMAL) {
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Loading animations are shown in the tab for tabbed windows.  We check the
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // browser type instead of calling IsTabStripVisible() because the latter
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // will return false for fullscreen windows, but we still need to update
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // their animations (so that when they come out of fullscreen mode they'll
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // be correct).
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip_->UpdateLoadingAnimations();
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (ShouldShowWindowIcon()) {
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // ... or in the window icon area for popups and app windows.
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabContents* tab_contents = browser_->GetSelectedTabContents();
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // GetSelectedTabContents can return NULL for example under Purify when
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the animations are running slowly and this function is called on
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // a timer through LoadingAnimationCallback.
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    titlebar_->UpdateThrobber(tab_contents);
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::SetStarredState(bool is_starred) {
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->GetLocationBarView()->SetStarred(is_starred);
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect BrowserWindowGtk::GetRestoredBounds() const {
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return restored_bounds_;
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengfx::Rect BrowserWindowGtk::GetBounds() const {
79272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return bounds_;
79372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
79472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsMaximized() const {
796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (state_ & GDK_WINDOW_STATE_MAXIMIZED);
797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::ShouldDrawContentDropShadow() {
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return !IsMaximized() && UseCustomFrame();
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::SetFullscreen(bool fullscreen) {
804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // gtk_window_(un)fullscreen asks the window manager to toggle the EWMH
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // for fullscreen windows.  Not all window managers support this.
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (fullscreen) {
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_fullscreen(window_);
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
8093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Work around a bug where if we try to unfullscreen, metacity immediately
8103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // fullscreens us again.  This is a little flickery and not necessary if
8113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // there's a gnome-panel, but it's not easy to detect whether there's a
8123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // panel or not.
8133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string wm_name;
8143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool unmaximize_before_unfullscreen = IsMaximized() &&
81572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        ui::GetWindowManagerName(&wm_name) && wm_name == "Metacity";
8163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (unmaximize_before_unfullscreen)
8173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      UnMaximize();
8183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_unfullscreen(window_);
8203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
8213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (unmaximize_before_unfullscreen)
8223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      gtk_window_maximize(window_);
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsFullscreen() const {
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (state_ & GDK_WINDOW_STATE_FULLSCREEN);
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsFullscreenBubbleVisible() const {
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return fullscreen_exit_bubble_.get() ? true : false;
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLocationBar* BrowserWindowGtk::GetLocationBar() const {
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return toolbar_->GetLocationBar();
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::SetFocusToLocationBar(bool select_all) {
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsFullscreen())
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GetLocationBar()->FocusLocation(select_all);
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UpdateReloadStopState(bool is_loading, bool force) {
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->GetReloadButton()->ChangeMode(
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      is_loading ? ReloadButtonGtk::MODE_STOP : ReloadButtonGtk::MODE_RELOAD,
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      force);
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
849201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserWindowGtk::UpdateToolbar(TabContentsWrapper* contents,
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     bool should_restore_state) {
851201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  toolbar_->UpdateTabContents(contents->tab_contents(), should_restore_state);
852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::FocusToolbar() {
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::FocusAppMenu() {
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::FocusBookmarksToolbar() {
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::FocusChromeOSStatus() {
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::RotatePaneFocus(bool forwards) {
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsBookmarkBarVisible() const {
875ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return (browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR) &&
876ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          bookmark_bar_.get() &&
877ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          browser_->profile()->GetPrefs()->GetBoolean(
878ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              prefs::kShowBookmarkBar) &&
879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          browser_->profile()->GetPrefs()->GetBoolean(
880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              prefs::kEnableBookmarkBar));
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsBookmarkBarAnimating() const {
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool BrowserWindowGtk::IsTabStripEditable() const {
89021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return !tabstrip()->IsDragSessionActive() &&
89121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      !tabstrip()->IsActiveDropTarget();
89221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
89321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsToolbarVisible() const {
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return IsToolbarSupported();
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ConfirmAddSearchProvider(const TemplateURL* template_url,
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                Profile* profile) {
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new EditSearchEngineDialog(window_, template_url, NULL, profile);
901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ToggleBookmarkBar() {
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bookmark_utils::ToggleWhenVisible(browser_->profile());
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
907dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid BrowserWindowGtk::ShowAboutChromeDialog() {
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowAboutDialogForProfile(window_, browser_->profile());
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowUpdateChromeDialog() {
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateRecommendedDialog::Show(window_);
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowTaskManager() {
91672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TaskManagerGtk::Show(false);
91772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
91872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BrowserWindowGtk::ShowBackgroundPages() {
92072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TaskManagerGtk::Show(true);
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowBookmarkBubble(const GURL& url,
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          bool already_bookmarked) {
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->GetLocationBarView()->ShowStarBubble(url, !already_bookmarked);
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsDownloadShelfVisible() const {
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return download_shelf_.get() && download_shelf_->IsShowing();
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadShelf* BrowserWindowGtk::GetDownloadShelf() {
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!download_shelf_.get())
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download_shelf_.reset(new DownloadShelfGtk(browser_.get(),
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                               render_area_vbox_));
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return download_shelf_.get();
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowRepostFormWarningDialog(TabContents* tab_contents) {
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new RepostFormWarningGtk(GetNativeHandle(), tab_contents);
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowCollectedCookiesDialog(TabContents* tab_contents) {
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Deletes itself on close.
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new CollectedCookiesGtk(GetNativeHandle(), tab_contents);
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowThemeInstallBubble() {
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ThemeInstallBubbleViewGtk::Show(window_);
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      gfx::NativeWindow parent_window) {
95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser::ShowHtmlDialog(parent_window, browser_->profile(), delegate);
955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UserChangedTheme() {
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetBackgroundColor();
959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_window_invalidate_rect(GTK_WIDGET(window_)->window,
960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &GTK_WIDGET(window_)->allocation, TRUE);
961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateWindowShape(bounds_.width(), bounds_.height());
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserWindowGtk::GetExtraRenderViewHeight() const {
965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int sum = infobar_container_->TotalHeightOfAnimatingBars();
966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sum += bookmark_bar_->GetHeight();
968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (download_shelf_.get() && download_shelf_->IsClosing())
969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sum += download_shelf_->GetHeight();
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return sum;
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::TabContentsFocused(TabContents* tab_contents) {
974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowPageInfo(Profile* profile,
978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    const GURL& url,
979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    const NavigationEntry::SSLStatus& ssl,
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    bool show_history) {
981731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  browser::ShowPageInfoBubble(window_, profile, url, ssl, show_history);
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowAppMenu() {
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->ShowAppMenu();
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::PreHandleKeyboardEvent(
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkEventKey* os_event = event.os_event;
991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown)
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We first find out the browser command associated to the |event|.
996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Then if the command is a reserved one, and should be processed immediately
997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // according to the |event|, the command will be executed immediately.
998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise we just set |*is_keyboard_shortcut| properly and return false.
999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First check if it's a custom accelerator.
1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int id = GetCustomCommandId(os_event);
1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Then check if it's a predefined accelerator bound to the window.
1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (id == -1) {
1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This piece of code is based on the fact that calling
1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // gtk_window_activate_key() method against |window_| may only trigger a
1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // browser command execution, by matching a global accelerator
1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // defined in above |kAcceleratorMap|.
1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Here we need to retrieve the command id (if any) associated to the
1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // keyboard event. Instead of looking up the command id in above
1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // |kAcceleratorMap| table by ourselves, we block the command execution of
1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the |browser_| object then send the keyboard event to the |window_| by
1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // calling gtk_window_activate_key() method, as if we are activating an
1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // accelerator key. Then we can retrieve the command id from the
1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // |browser_| object.
1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Pros of this approach:
1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // 1. We don't need to care about keyboard layout problem, as
1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //    gtk_window_activate_key() method handles it for us.
1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Cons:
1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // 1. The logic is a little complicated.
1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // 2. We should be careful not to introduce any accelerators that trigger
1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //    customized code instead of browser commands.
1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_->SetBlockCommandExecution(true);
1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_activate_key(window_, os_event);
1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We don't need to care about the WindowOpenDisposition value,
1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // because all commands executed in this path use the default value.
1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    id = browser_->GetLastBlockedCommand(NULL);
1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_->SetBlockCommandExecution(false);
1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (id == -1)
1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Executing the command may cause |this| object to be destroyed.
103872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (browser_->IsReservedCommandOrKey(id, event) && !event.match_edit_command)
103921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return browser_->ExecuteCommandIfEnabled(id);
1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The |event| is a keyboard shortcut.
1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(is_keyboard_shortcut != NULL);
1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *is_keyboard_shortcut = true;
1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::HandleKeyboardEvent(
1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const NativeWebKeyboardEvent& event) {
1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkEventKey* os_event = event.os_event;
1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown)
1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Handles a key event in following sequence:
1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 1. Our special key accelerators, such as ctrl-tab, etc.
1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 2. Gtk accelerators.
1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This sequence matches the default key press handler of GtkWindow.
1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It's not necessary to care about the keyboard layout, as
1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // gtk_window_activate_key() takes care of it automatically.
1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int id = GetCustomCommandId(os_event);
1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (id != -1)
106421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    browser_->ExecuteCommandIfEnabled(id);
1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_activate_key(window_, os_event);
1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1069201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserWindowGtk::ShowCreateWebAppShortcutsDialog(
1070ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TabContentsWrapper* tab_contents) {
1071201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  CreateWebApplicationShortcutsDialogGtk::Show(window_, tab_contents);
1072201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
1073201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1074201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserWindowGtk::ShowCreateChromeAppShortcutsDialog(
1075201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    Profile* profile, const Extension* app) {
1076201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  CreateChromeApplicationShortcutsDialogGtk::Show(window_, app);
1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::Cut() {
10804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  gtk_util::DoCut(this);
1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::Copy() {
10844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  gtk_util::DoCopy(this);
1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::Paste() {
10884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  gtk_util::DoPaste(this);
10894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
10904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
10914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid BrowserWindowGtk::PrepareForInstant() {
1092ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContentsWrapper* contents = contents_container_->tab();
1093201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (contents)
1094ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FadeForInstant(true);
1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1097ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserWindowGtk::ShowInstant(TabContentsWrapper* preview) {
1098ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  contents_container_->SetPreview(preview);
1099201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MaybeShowBookmarkBar(false);
1100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContentsWrapper* contents = contents_container_->tab();
1102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (contents)
1103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CancelInstantFade();
11043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserWindowGtk::HideInstant(bool instant_is_active) {
1107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  contents_container_->PopPreview();
1108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MaybeShowBookmarkBar(false);
1109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContentsWrapper* contents = contents_container_->tab();
1111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (contents) {
1112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (instant_is_active)
1113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      FadeForInstant(false);
1114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    else
1115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CancelInstantFade();
1116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
11173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickgfx::Rect BrowserWindowGtk::GetInstantBounds() {
1120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return gtk_util::GetWidgetScreenBounds(contents_container_->widget());
11213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads() {
1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new DownloadInProgressDialogGtk(browser());
1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::Observe(NotificationType type,
1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const NotificationSource& source,
1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const NotificationDetails& details) {
1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type.value) {
1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED:
1132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      MaybeShowBookmarkBar(true);
1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::PREF_CHANGED: {
11363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      std::string* pref_name = Details<std::string>(details).ptr();
1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (*pref_name == prefs::kUseCustomChromeFrame) {
1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        UpdateCustomFrame();
1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED() << "Got pref change notification we didn't register for!";
1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Got a notification we didn't register for!";
1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserWindowGtk::TabDetachedAt(TabContentsWrapper* contents, int index) {
1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We use index here rather than comparing |contents| because by this time
1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the model has already removed |contents| from its list, so
1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // browser_->GetSelectedTabContents() will return NULL or something else.
1154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (index == browser_->tabstrip_model()->active_index()) {
1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    infobar_container_->ChangeTabContents(NULL);
1156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UpdateDevToolsForContents(NULL);
1157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  contents_container_->DetachTab(contents);
1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserWindowGtk::TabSelectedAt(TabContentsWrapper* old_contents,
1162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     TabContentsWrapper* new_contents,
1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     int index,
1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     bool user_gesture) {
1165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (old_contents == new_contents)
1166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (old_contents && !old_contents->tab_contents()->is_being_destroyed())
1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    old_contents->view()->StoreFocus();
1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update various elements that are interested in knowing the current
1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabContents.
1173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  infobar_container_->ChangeTabContents(new_contents->tab_contents());
1174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  contents_container_->SetTab(new_contents);
1175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  UpdateDevToolsForContents(new_contents->tab_contents());
1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  new_contents->tab_contents()->DidBecomeSelected();
1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(estade): after we manage browser activation, add a check to make sure
1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we are the active browser before calling RestoreFocus().
1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!browser_->tabstrip_model()->closing_all()) {
1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_contents->view()->RestoreFocus();
1182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (new_contents->find_tab_helper()->find_ui_active())
1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update all the UI bits.
1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateTitleBar();
1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateToolbar(new_contents, true);
1189201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MaybeShowBookmarkBar(false);
1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do nothing if we're in the process of closing the browser window.
1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!window_)
1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool is_active = (GTK_WIDGET(window_)->window == active_window);
1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool changed = (is_active != is_active_);
1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (is_active && changed) {
1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If there's an app modal dialog (e.g., JS alert), try to redirect
1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the user's attention to the window owning the dialog.
120321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (AppModalDialogQueue::GetInstance()->HasActiveDialog()) {
120421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      AppModalDialogQueue::GetInstance()->ActivateModalDialog();
1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  is_active_ = is_active;
1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (changed) {
1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetBackgroundColor();
1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_window_invalidate_rect(GTK_WIDGET(window_)->window,
1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               &GTK_WIDGET(window_)->allocation, TRUE);
1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // For some reason, the above two calls cause the window shape to be
1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // lost so reset it.
1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    UpdateWindowShape(bounds_.width(), bounds_.height());
1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserWindowGtk::FadeForInstant(bool animate) {
1221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(contents_container_->tab());
1222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RenderWidgetHostView* rwhv =
1223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      contents_container_->tab()->tab_contents()->GetRenderWidgetHostView();
1224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (rwhv) {
1225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SkColor whitish = SkColorSetARGB(192, 255, 255, 255);
1226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    rwhv->SetVisuallyDeemphasized(&whitish, animate);
1227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserWindowGtk::CancelInstantFade() {
1231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(contents_container_->tab());
1232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RenderWidgetHostView* rwhv =
1233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      contents_container_->tab()->tab_contents()->GetRenderWidgetHostView();
1234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (rwhv)
1235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    rwhv->SetVisuallyDeemphasized(NULL, false);
1236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserWindowGtk::MaybeShowBookmarkBar(bool animate) {
1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsBookmarkBarSupported())
1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TabContents* contents = GetDisplayedTabContents();
1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool show_bar = false;
1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (contents) {
1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_bar_->SetProfile(contents->profile());
1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_bar_->SetPageNavigator(contents);
1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    show_bar = true;
1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (show_bar && contents && !contents->ShouldShowBookmarkBar()) {
1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PrefService* prefs = contents->profile()->GetPrefs();
1253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    show_bar = prefs->GetBoolean(prefs::kShowBookmarkBar) &&
1254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               prefs->GetBoolean(prefs::kEnableBookmarkBar) &&
1255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               !IsFullscreen();
1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (show_bar) {
1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_bar_->Show(animate);
1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (IsFullscreen()) {
1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_bar_->EnterFullscreen();
1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_bar_->Hide(animate);
1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UpdateDevToolsForContents(TabContents* contents) {
1268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContentsWrapper* old_devtools = devtools_container_->tab();
1269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContentsWrapper* devtools_contents = contents ?
1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DevToolsWindow::GetDevToolsContents(contents) : NULL;
1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (old_devtools == devtools_contents)
1272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (old_devtools)
1275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    devtools_container_->DetachTab(old_devtools);
1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  devtools_container_->SetTab(devtools_contents);
1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (devtools_contents) {
1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TabContentsViewGtk::WasShown is not called when tab contents is shown by
1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // anything other than user selecting a Tab.
1281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // See TabContentsViewViews::OnWindowPosChanged for reference on how it
1282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // should be implemented.
1283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    devtools_contents->tab_contents()->ShowContents();
1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool should_show = old_devtools == NULL && devtools_contents != NULL;
1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool should_hide = old_devtools != NULL && devtools_contents == NULL;
1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (should_show) {
1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_show(devtools_container_->widget());
1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (should_hide) {
1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Store split offset when hiding devtools window only.
1292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint divider_offset = gtk_paned_get_position(GTK_PANED(contents_split_));
129372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    browser_->profile()->GetPrefs()->
129472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        SetInteger(prefs::kDevToolsSplitLocation, divider_offset);
1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_hide(devtools_container_->widget());
1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::DestroyBrowser() {
1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_.reset();
1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
130372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengboolean BrowserWindowGtk::OnConfigure(GtkWidget* widget,
130472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       GdkEventConfigure* event) {
130572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect bounds(event->x, event->y, event->width, event->height);
130672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
130772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // When the window moves, we'll get multiple configure-event signals. We can
130872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // also get events when the bounds haven't changed, but the window's stacking
130972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // has, which we aren't interested in. http://crbug.com/70125
131072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (bounds == bounds_)
131172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return FALSE;
131272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetLocationBar()->location_entry()->ClosePopup();
1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  TabContents* tab_contents = GetDisplayedTabContents();
131621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (tab_contents)
131721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    tab_contents->WindowMoveOrResizeStarted();
131821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bounds_.size() != bounds.size())
1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OnSizeChanged(bounds.width(), bounds.height());
1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We update |bounds_| but not |restored_bounds_| here.  The latter needs
1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to be updated conditionally when the window is non-maximized and non-
1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // fullscreen, but whether those state updates have been processed yet is
1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window-manager specific.  We update |restored_bounds_| in the debounced
1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // handler below, after the window state has been updated.
1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounds_ = bounds;
1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The GdkEventConfigure* we get here doesn't have quite the right
1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // coordinates though (they're relative to the drawable window area, rather
1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // than any window manager decorations, if enabled), so we need to call
1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // gtk_window_get_position() to get the right values.  (Otherwise session
1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // restore, if enabled, will restore windows to incorrect positions.)  That's
1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a round trip to the X server though, so we set a debounce timer and only
1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a
1336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // reconfigure event in a short while.
1337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't use Reset() because the timer may not yet be running.
1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (In that case Stop() is a no-op.)
1339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!debounce_timer_disabled_) {
1340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    window_configure_debounce_timer_.Stop();
1341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    window_configure_debounce_timer_.Start(base::TimeDelta::FromMilliseconds(
1342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        kDebounceTimeoutMilliseconds), this,
1343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        &BrowserWindowGtk::OnDebouncedBoundsChanged);
1344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
134572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
134672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return FALSE;
1347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::OnDebouncedBoundsChanged() {
1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint x, y;
1351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_position(window_, &x, &y);
1352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point origin(x, y);
1353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounds_.set_origin(origin);
1354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsFullscreen() && !IsMaximized())
1355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    restored_bounds_ = bounds_;
1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SaveWindowPosition();
1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengboolean BrowserWindowGtk::OnWindowState(GtkWidget* sender,
136072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                         GdkEventWindowState* event) {
136172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  state_ = event->new_window_state;
1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
136472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool is_fullscreen = state_ & GDK_WINDOW_STATE_FULLSCREEN;
1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_->UpdateCommandsForFullscreenMode(is_fullscreen);
1366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (is_fullscreen) {
1367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      UpdateCustomFrame();
1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      toolbar_->Hide();
1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tabstrip_->Hide();
1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (IsBookmarkBarSupported())
1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bookmark_bar_->EnterFullscreen();
1372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool is_kiosk =
1373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode);
1374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!is_kiosk) {
1375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        fullscreen_exit_bubble_.reset(new FullscreenExitBubbleGtk(
1376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            GTK_FLOATING_CONTAINER(render_area_floating_container_)));
1377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
1378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(toolbar_border_);
1379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
1380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      fullscreen_exit_bubble_.reset();
1381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      UpdateCustomFrame();
1382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ShowSupportedWindowFeatures();
1383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
1384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateWindowShape(bounds_.width(), bounds_.height());
1387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SaveWindowPosition();
138872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return FALSE;
138972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
139072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
139172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Callback for the delete event.  This event is fired when the user tries to
139272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// close the window (e.g., clicking on the X in the window manager title bar).
139372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengboolean BrowserWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget,
139472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                   GdkEvent* event) {
139572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Close();
139672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
139772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Return true to prevent the gtk window from being destroyed.  Close will
139872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // destroy it for us.
139972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return TRUE;
140072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
140172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
140272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BrowserWindowGtk::OnMainWindowDestroy(GtkWidget* widget) {
140372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // BUG 8712. When we gtk_widget_destroy() in Close(), this will emit the
140472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // signal right away, and we will be here (while Close() is still in the
140572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // call stack).  In order to not reenter Close(), and to also follow the
140672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // expectations of BrowserList, we should run the BrowserWindowGtk destructor
140772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // not now, but after the run loop goes back to process messages.  Otherwise
140872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // we will remove ourself from BrowserList while it's being iterated.
140972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Additionally, now that we know the window is gone, we need to make sure to
141072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // set window_ to NULL, otherwise we will try to close the window again when
141172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // we call Close() in the destructor.
141272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //
141372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // We don't want to use DeleteSoon() here since it won't work on a nested pump
141472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // (like in UI tests).
141572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MessageLoop::current()->PostTask(FROM_HERE,
141672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   new DeleteTask<BrowserWindowGtk>(this));
1417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UnMaximize() {
1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_unmaximize(window_);
1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It can happen that you end up with a window whose restore size is the same
1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // as the size of the screen, so unmaximizing it merely remaximizes it due to
1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the same WM feature that SetWindowSize() works around.  We try to detect
1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // this and resize the window to work around the issue.
1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bounds_.size() == restored_bounds_.size())
1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_resize(window_, bounds_.width(), bounds_.height() - 1);
1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::CanClose() const {
1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // You cannot close a frame for which there is an active originating drag
1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // session.
1433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tabstrip_->IsDragSessionActive())
1434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Give beforeunload handlers the chance to cancel the close before we hide
1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the window below.
1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!browser_->ShouldCloseWindow())
1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1441731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!browser_->tabstrip_model()->empty()) {
1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Tab strip isn't empty.  Hide the window (so it appears to have closed
1443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // immediately) and close all the tabs, allowing the renderers to shut
1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // down. When the tab strip is empty we'll be called back again.
1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_hide(GTK_WIDGET(window_));
1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_->OnWindowClosing();
1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Empty TabStripModel, it's now safe to allow the Window to be closed.
1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::WINDOW_CLOSED,
1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Source<GtkWindow>(window_),
1454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationService::NoDetails());
1455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
1456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::ShouldShowWindowIcon() const {
1459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR);
1460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserWindowGtk::DisableDebounceTimerForTests(bool is_disabled) {
1463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  debounce_timer_disabled_ = is_disabled;
1464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (is_disabled)
1465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    window_configure_debounce_timer_.Stop();
1466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::AddFindBar(FindBarGtk* findbar) {
1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_floating_container_add_floating(
1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_FLOATING_CONTAINER(render_area_floating_container_),
1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      findbar->widget());
1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ResetCustomFrameCursor() {
1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!frame_cursor_)
1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  frame_cursor_ = NULL;
1479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL);
1480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
1483c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow(
1484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::NativeWindow window) {
1485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (window) {
1486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return static_cast<BrowserWindowGtk*>(
1487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_object_get_qdata(G_OBJECT(window), GetBrowserWindowQuarkKey()));
1488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
1491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
1494c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) {
1495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::map<XID, GtkWindow*>::iterator iter =
1496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BrowserWindowGtk::xid_map_.find(xid);
1497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (iter != BrowserWindowGtk::xid_map_.end()) ? iter->second : NULL;
1498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
1501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::RegisterUserPrefs(PrefService* prefs) {
1502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool custom_frame_default = false;
1503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Avoid checking the window manager if we're not connected to an X server (as
1504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // is the case in Valgrind tests).
150572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::XDisplayExists() &&
1506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !prefs->HasPrefPath(prefs::kUseCustomChromeFrame)) {
1507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    custom_frame_default = GetCustomFramePrefDefault();
1508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->RegisterBooleanPref(
1510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs::kUseCustomChromeFrame, custom_frame_default);
1511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::BookmarkBarIsFloating(bool is_floating) {
1514731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bookmark_bar_is_floating_ = is_floating;
1515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->UpdateForBookmarkBarVisibility(is_floating);
1516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This can be NULL during initialization of the bookmark bar.
1518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bookmark_bar_.get())
1519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PlaceBookmarkBar(is_floating);
1520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1522201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTabContents* BrowserWindowGtk::GetDisplayedTabContents() {
1523201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return contents_container_->GetVisibleTabContents();
1524201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
1525201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::QueueToolbarRedraw() {
1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_queue_draw(toolbar_->widget());
1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::SetGeometryHints() {
1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we call gtk_window_maximize followed by gtk_window_present, compiz gets
1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // confused and maximizes the window, but doesn't set the
1533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // GDK_WINDOW_STATE_MAXIMIZED bit.  So instead, we keep track of whether to
1534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // maximize and call it after gtk_window_present.
1535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  maximize_after_show_ = browser_->GetSavedMaximizedState();
1536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect bounds = browser_->GetSavedWindowBounds();
1538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't blindly call SetBounds here: that sets a forced position
1539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // on the window and we intentionally *don't* do that for normal
1540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // windows.  Most programs do not restore their window position on
1541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Linux, instead letting the window manager choose a position.
1542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
1543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // However, in cases like dropping a tab where the bounds are
1544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // specifically set, we do want to position explicitly.  We also
1545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // force the position as part of session restore, as applications
1546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that restore other, similar state (for instance GIMP, audacity,
1547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pidgin, dia, and gkrellm) do tend to restore their positions.
1548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
1549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // For popup windows, we assume that if x == y == 0, the opening page
1550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // did not specify a position.  Let the WM position the popup instead.
1551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool is_popup = browser_->type() & Browser::TYPE_POPUP;
15523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool popup_without_position = is_popup &&
15533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      bounds.x() == 0 && bounds.y() == 0;
15543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool move = browser_->bounds_overridden() && !popup_without_position;
15553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetBoundsImpl(bounds, !is_popup, move);
1556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ConnectHandlersToSignals() {
1559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "delete-event",
156072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   G_CALLBACK(OnMainWindowDeleteEventThunk), this);
1561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "destroy",
156272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   G_CALLBACK(OnMainWindowDestroyThunk), this);
1563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "configure-event",
156472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   G_CALLBACK(OnConfigureThunk), this);
1565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "window-state-event",
156672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   G_CALLBACK(OnWindowStateThunk), this);
1567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "map",
1568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(MainWindowMapped), NULL);
1569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "unmap",
1570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(MainWindowUnMapped), NULL);
1571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "key-press-event",
1572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnKeyPressThunk), this);
1573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "motion-notify-event",
1574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnMouseMoveEventThunk), this);
1575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "button-press-event",
1576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnButtonPressEventThunk), this);
1577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "focus-in-event",
1578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnFocusInThunk), this);
1579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "focus-out-event",
1580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnFocusOutThunk), this);
1581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::InitWidgets() {
1584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ConnectHandlersToSignals();
1585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounds_ = restored_bounds_ = GetInitialWindowBounds(window_);
1586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This vbox encompasses all of the widgets within the browser.  This is
1588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // everything except the custom frame border.
1589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_vbox_ = gtk_vbox_new(FALSE, 0);
1590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show(window_vbox_);
1591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We hold an always hidden GtkMenuBar inside our browser window simply to
1593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // fool the Unity desktop, which will mirror the contents of the first
1594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // GtkMenuBar it sees into the global menu bar. (It doesn't seem to check the
1595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // visibility of the GtkMenuBar, so we can just permanently hide it.)
1596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGlobalGnomeMenu)) {
1597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    global_menu_bar_.reset(new GlobalMenuBar(browser_.get(), this));
1598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    gtk_container_add(GTK_CONTAINER(window_vbox_), global_menu_bar_->widget());
1599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The window container draws the custom browser frame.
1602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_container_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
1603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_name(window_container_, "chrome-custom-frame-border");
1604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_app_paintable(window_container_, TRUE);
1605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_double_buffered(window_container_, FALSE);
1606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_redraw_on_allocate(window_container_, TRUE);
1607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_container_, "expose-event",
1608731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                   G_CALLBACK(OnCustomFrameExposeThunk), this);
1609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(window_container_), window_vbox_);
1610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tabstrip_.reset(new TabStripGtk(browser_->tabstrip_model(), this));
1612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tabstrip_->Init();
1613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Build the titlebar (tabstrip + header space + min/max/close buttons).
1615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_.reset(new BrowserTitlebar(this, window_));
1616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Insert the tabstrip into the window.
1618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(window_vbox_), titlebar_->widget(), FALSE, FALSE,
1619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     0);
1620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_.reset(new BrowserToolbarGtk(browser_.get(), this));
1622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->Init(browser_->profile(), window_);
1623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(window_vbox_), toolbar_->widget(),
1624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     FALSE, FALSE, 0);
1625731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  g_signal_connect_after(toolbar_->widget(), "expose-event",
1626731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
1627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This vbox surrounds the render area: find bar, info bars and render view.
1628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The reason is that this area as a whole needs to be grouped in its own
1629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // GdkWindow hierarchy so that animations originating inside it (infobar,
1630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // download shelf, find bar) are all clipped to that area. This is why
1631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |render_area_vbox_| is packed in |render_area_event_box_|.
1632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  render_area_vbox_ = gtk_vbox_new(FALSE, 0);
1633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_name(render_area_vbox_, "chrome-render-area-vbox");
1634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  render_area_floating_container_ = gtk_floating_container_new();
1635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(render_area_floating_container_),
1636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    render_area_vbox_);
1637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  GtkWidget* location_icon = toolbar_->GetLocationBarView()->
16393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      location_icon_widget();
16403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  g_signal_connect(location_icon, "size-allocate",
16413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                   G_CALLBACK(OnLocationIconSizeAllocateThunk), this);
16423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  g_signal_connect_after(location_icon, "expose-event",
16433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
16443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_border_ = gtk_event_box_new();
1646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(render_area_vbox_),
1647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     toolbar_border_, FALSE, FALSE, 0);
1648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_size_request(toolbar_border_, -1, 1);
1649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_no_show_all(toolbar_border_, TRUE);
1650731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  g_signal_connect_after(toolbar_border_, "expose-event",
1651731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
1652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsToolbarSupported())
1654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_show(toolbar_border_);
1655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  infobar_container_.reset(new InfoBarContainerGtk(browser_->profile()));
1657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(render_area_vbox_),
1658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     infobar_container_->widget(),
1659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     FALSE, FALSE, 0);
1660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  status_bubble_.reset(new StatusBubbleGtk(browser_->profile()));
1662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  contents_container_.reset(new TabContentsContainerGtk(status_bubble_.get()));
1664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  devtools_container_.reset(new TabContentsContainerGtk(NULL));
1665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ViewIDUtil::SetID(devtools_container_->widget(), VIEW_ID_DEV_TOOLS_DOCKED);
1666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  contents_split_ = gtk_vpaned_new();
1667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_paned_pack1(GTK_PANED(contents_split_), contents_container_->widget(),
1668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  TRUE, TRUE);
1669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_paned_pack2(GTK_PANED(contents_split_), devtools_container_->widget(),
1670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  FALSE, TRUE);
1671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(render_area_vbox_), contents_split_, TRUE, TRUE, 0);
1672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Restore split offset.
167372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int split_offset = browser_->profile()->GetPrefs()->
167472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      GetInteger(prefs::kDevToolsSplitLocation);
1675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (split_offset != -1) {
1676513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (split_offset < kMinDevToolsHeight)
1677513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      split_offset = kMinDevToolsHeight;
1678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_paned_set_position(GTK_PANED(contents_split_), split_offset);
1679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
1680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(devtools_container_->widget(), -1,
1681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                kDefaultDevToolsHeight);
1682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(render_area_floating_container_);
1684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_hide(devtools_container_->widget());
1685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  render_area_event_box_ = gtk_event_box_new();
1686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set a white background so during startup the user sees white in the
1687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // content area before we get a TabContents in place.
1688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_bg(render_area_event_box_, GTK_STATE_NORMAL,
1689513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                       &gtk_util::kGdkWhite);
1690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(render_area_event_box_),
1691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    render_area_floating_container_);
1692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show(render_area_event_box_);
1693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(window_vbox_), render_area_event_box_,
1694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   TRUE, TRUE, 0);
1695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsBookmarkBarSupported()) {
1697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_bar_.reset(new BookmarkBarGtk(this,
1698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           browser_->profile(),
1699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           browser_.get(),
1700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           tabstrip_.get()));
1701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PlaceBookmarkBar(false);
1702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_show(bookmark_bar_->widget());
1703731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1704731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    g_signal_connect_after(bookmark_bar_->widget(), "expose-event",
1705731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                           G_CALLBACK(OnBookmarkBarExposeThunk), this);
1706731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    g_signal_connect(bookmark_bar_->widget(), "size-allocate",
1707731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                     G_CALLBACK(OnBookmarkBarSizeAllocateThunk), this);
1708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We have to realize the window before we try to apply a window shape mask.
1711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_realize(GTK_WIDGET(window_));
1712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  state_ = gdk_window_get_state(GTK_WIDGET(window_)->window);
1713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note that calling this the first time is necessary to get the
1714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // proper control layout.
1715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateCustomFrame();
1716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We have to call this after the first window is created, but after that only
1718dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // when the theme changes.
1719dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static bool default_icon_set = false;
1720dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!default_icon_set) {
1721dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    gtk_util::SetDefaultWindowIcon(window_);
1722dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default_icon_set = true;
1723dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1724dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(window_), window_container_);
1726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show(window_container_);
1727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_->tabstrip_model()->AddObserver(this);
1728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::SetBackgroundColor() {
1731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Profile* profile = browser()->profile();
1732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GtkThemeService* theme_provider = GtkThemeService::GetFrom(profile);
1733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int frame_color_id;
1734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (UsingCustomPopupFrame()) {
1735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    frame_color_id = ThemeService::COLOR_TOOLBAR;
1736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (IsActive()) {
1737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    frame_color_id = browser()->profile()->IsOffTheRecord()
1738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ? ThemeService::COLOR_FRAME_INCOGNITO
1739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       : ThemeService::COLOR_FRAME;
1740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
1741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    frame_color_id = browser()->profile()->IsOffTheRecord()
1742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ? ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE
1743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       : ThemeService::COLOR_FRAME_INACTIVE;
1744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkColor frame_color = theme_provider->GetColor(frame_color_id);
1747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Paint the frame color on the left, right and bottom.
1749513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GdkColor frame_color_gdk = gfx::SkColorToGdkColor(frame_color);
1750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_bg(GTK_WIDGET(window_), GTK_STATE_NORMAL,
1751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       &frame_color_gdk);
1752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the color of the dev tools divider.
1754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_bg(contents_split_, GTK_STATE_NORMAL, &frame_color_gdk);
1755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When the cursor is over the divider, GTK+ normally lightens the background
1757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // color by 1.3 (see LIGHTNESS_MULT in gtkstyle.c).  Since we're setting the
1758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // color, override the prelight also.
1759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  color_utils::HSL hsl = { -1, 0.5, 0.65 };
1760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkColor frame_prelight_color = color_utils::HSLShift(frame_color, hsl);
1761513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GdkColor frame_prelight_color_gdk =
1762513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gfx::SkColorToGdkColor(frame_prelight_color);
1763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_bg(contents_split_, GTK_STATE_PRELIGHT,
1764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &frame_prelight_color_gdk);
1765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkColor border_color = theme_provider->GetBorderColor();
1767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_bg(toolbar_border_, GTK_STATE_NORMAL, &border_color);
1768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::OnSizeChanged(int width, int height) {
1771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateWindowShape(width, height);
1772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UpdateWindowShape(int width, int height) {
1775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (UseCustomFrame() && !IsFullscreen() && !IsMaximized()) {
1776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Make the corners rounded.  We set a mask that includes most of the
1777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // window except for a few pixels in each corner.
1778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle top_top_rect = { 3, 0, width - 6, 1 };
1779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle top_mid_rect = { 1, 1, width - 2, 2 };
1780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle mid_rect = { 0, 3, width, height - 6 };
1781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The bottom two rects are mirror images of the top two rects.
1782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle bot_mid_rect = top_mid_rect;
1783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bot_mid_rect.y = height - 3;
1784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle bot_bot_rect = top_top_rect;
1785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bot_bot_rect.y = height - 1;
1786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRegion* mask = gdk_region_rectangle(&top_top_rect);
1787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_region_union_with_rect(mask, &top_mid_rect);
1788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_region_union_with_rect(mask, &mid_rect);
1789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_region_union_with_rect(mask, &bot_mid_rect);
1790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_region_union_with_rect(mask, &bot_bot_rect);
1791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, mask, 0, 0);
1792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_region_destroy(mask);
1793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 1,
1794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kFrameBorderThickness, kFrameBorderThickness, kFrameBorderThickness);
1795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
1796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // XFCE disables the system decorations if there's an xshape set.
1797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (UseCustomFrame()) {
1798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Disable rounded corners.  Simply passing in a NULL region doesn't
1799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // seem to work on KWin, so manually set the shape to the whole window.
1800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GdkRectangle rect = { 0, 0, width, height };
1801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GdkRegion* mask = gdk_region_rectangle(&rect);
1802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, mask, 0, 0);
1803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_region_destroy(mask);
1804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
1805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, NULL, 0, 0);
1806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
1807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 0, 0, 0, 0);
1808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ConnectAccelerators() {
1812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  accel_group_ = gtk_accel_group_new();
1813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_add_accel_group(window_, accel_group_);
1814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
1816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
1817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       iter != accelerators->end(); ++iter) {
1818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_accel_group_connect(
1819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        accel_group_,
1820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        iter->second.GetGdkKeyCode(),
1821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        static_cast<GdkModifierType>(iter->second.modifiers()),
1822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GtkAccelFlags(0),
1823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_cclosure_new(G_CALLBACK(OnGtkAccelerator),
1824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       GINT_TO_POINTER(iter->first), NULL));
1825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::UpdateCustomFrame() {
1829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_decorated(window_, !UseCustomFrame());
1830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_->UpdateCustomFrame(UseCustomFrame() && !IsFullscreen());
1831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateWindowShape(bounds_.width(), bounds_.height());
1832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::SaveWindowPosition() {
1835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Browser::SaveWindowPlacement is used for session restore.
1836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_->ShouldSaveWindowPlacement())
1837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_->SaveWindowPlacement(restored_bounds_, IsMaximized());
1838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We also need to save the placement for startup.
1840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is a web of calls between views and delegates on Windows, but the
1841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // crux of the logic follows.  See also cocoa/browser_window_controller.mm.
184272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!browser_->profile()->GetPrefs())
1843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string window_name = browser_->GetWindowPlacementKey();
1846ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryPrefUpdate update(browser_->profile()->GetPrefs(),
1847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              window_name.c_str());
1848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* window_preferences = update.Get();
1849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note that we store left/top for consistency with Windows, but that we
1850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // *don't* obey them; we only use them for computing width/height.  See
1851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // comments in SetGeometryHints().
18523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("left", restored_bounds_.x());
18533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("top", restored_bounds_.y());
18543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("right", restored_bounds_.right());
18553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("bottom", restored_bounds_.bottom());
18563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetBoolean("maximized", IsMaximized());
1857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_info_provider(
1859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WindowSizer::CreateDefaultMonitorInfoProvider());
1860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect work_area(
1861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      monitor_info_provider->GetMonitorWorkAreaMatching(restored_bounds_));
18623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("work_area_left", work_area.x());
18633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("work_area_top", work_area.y());
18643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("work_area_right", work_area.right());
18653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  window_preferences->SetInteger("work_area_bottom", work_area.bottom());
1866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1868513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserWindowGtk::SetInfoBarShowing(InfoBar* bar, bool animate) {
1869513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  infobar_arrow_model_.ShowArrowFor(bar, animate);
1870731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1871731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1872513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserWindowGtk::PaintStateChanged() {
1873731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  InvalidateInfoBarBits();
1874731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1875731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1876731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid BrowserWindowGtk::InvalidateInfoBarBits() {
1877731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  gtk_widget_queue_draw(toolbar_border_);
1878731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  gtk_widget_queue_draw(toolbar_->widget());
1879513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (bookmark_bar_.get() && !bookmark_bar_is_floating_)
1880731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    gtk_widget_queue_draw(bookmark_bar_->widget());
1881513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
1882513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
1883513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint BrowserWindowGtk::GetXPositionOfLocationIcon(GtkWidget* relative_to) {
1884513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GtkWidget* location_icon = toolbar_->GetLocationBarView()->
1885513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      location_icon_widget();
1886513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int x = 0;
1887513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  gtk_widget_translate_coordinates(
1888513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      location_icon, relative_to,
1889513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      (location_icon->allocation.width + 1) / 2,
1890513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      0, &x, NULL);
1891731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1892513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (GTK_WIDGET_NO_WINDOW(relative_to))
1893513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    x += relative_to->allocation.x;
1894513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
1895513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return x;
1896731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1897731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
18983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BrowserWindowGtk::OnLocationIconSizeAllocate(GtkWidget* sender,
18993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                                  GtkAllocation* allocation) {
19003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // The position of the arrow may have changed, so we'll have to redraw it.
19013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  InvalidateInfoBarBits();
19023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
19033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1904731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickgboolean BrowserWindowGtk::OnExposeDrawInfobarBits(GtkWidget* sender,
1905731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                   GdkEventExpose* expose) {
1906513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!infobar_arrow_model_.NeedToDrawInfoBarArrow())
1907731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return FALSE;
1908731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1909513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int x = GetXPositionOfLocationIcon(sender);
1910731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1911731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  gfx::Rect toolbar_border(toolbar_border_->allocation);
1912731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int y = 0;
1913731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  gtk_widget_translate_coordinates(toolbar_border_, sender,
1914731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   0, toolbar_border.bottom(),
1915731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   NULL, &y);
1916513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (GTK_WIDGET_NO_WINDOW(sender))
1917731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    y += sender->allocation.y;
1918731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // x, y is the bottom middle of the arrow. Now we need to create the bounding
1920ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // rectangle.
1921ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Size arrow_size = GetInfobarArrowSize();
1922ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Rect bounds(
1923ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      gfx::Point(x - arrow_size.width() / 2.0, y - arrow_size.height()),
1924ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      arrow_size);
1925ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1926513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  Profile* profile = browser()->profile();
1927513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  infobar_arrow_model_.Paint(
1928ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      sender, expose, bounds,
1929ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      GtkThemeService::GetFrom(profile)->GetBorderColor());
1930731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return FALSE;
1931731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1932731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsengfx::Size BrowserWindowGtk::GetInfobarArrowSize() {
1934ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const size_t kDefaultWidth =
1935ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      2 * InfoBarArrowModel::kDefaultArrowSize;
1936ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const size_t kDefaultHeight = InfoBarArrowModel::kDefaultArrowSize;
1937ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const size_t kMaxWidth = 30;
1938ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const size_t kMaxHeight = 24;
1939ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1940ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  double progress = bookmark_bar_.get() && !bookmark_bar_is_floating_ ?
1941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bookmark_bar_->animation()->GetCurrentValue() : 0.0;
1942ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t width = kDefaultWidth + (kMaxWidth - kDefaultWidth) * progress;
1943ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t height = kDefaultHeight + (kMaxHeight - kDefaultHeight) * progress;
1944ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1945ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return gfx::Size(width, height);
1946ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1947ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1948731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickgboolean BrowserWindowGtk::OnBookmarkBarExpose(GtkWidget* sender,
1949731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                               GdkEventExpose* expose) {
1950513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!infobar_arrow_model_.NeedToDrawInfoBarArrow())
1951731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return FALSE;
1952731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1953513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (bookmark_bar_is_floating_)
1954513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return FALSE;
1955731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1956513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return OnExposeDrawInfobarBits(sender, expose);
1957731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1958731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1959731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid BrowserWindowGtk::OnBookmarkBarSizeAllocate(GtkWidget* sender,
1960731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                 GtkAllocation* allocation) {
1961731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // The size of the bookmark bar affects how the infobar arrow is drawn on
1962731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // the toolbar.
1963513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (infobar_arrow_model_.NeedToDrawInfoBarArrow())
1964ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InvalidateInfoBarBits();
1965731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1966731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
1968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
1969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            GObject* acceleratable,
1970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            guint keyval,
1971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            GdkModifierType modifier,
1972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            void* user_data) {
1973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int command_id = GPOINTER_TO_INT(user_data);
1974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserWindowGtk* browser_window =
1975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetBrowserWindowForNativeWindow(GTK_WINDOW(acceleratable));
1976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(browser_window != NULL);
197721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return browser_window->browser()->ExecuteCommandIfEnabled(command_id);
1978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Let the focused widget have first crack at the key event so we don't
1981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// override their accelerators.
1982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserWindowGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
1983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If a widget besides the native view is focused, we have to try to handle
1984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the custom accelerators before letting it handle them.
1985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* current_tab_contents =
1986201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      browser()->GetSelectedTabContents();
1987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The current tab might not have a render view if it crashed.
1988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!current_tab_contents || !current_tab_contents->GetContentNativeView() ||
1989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !gtk_widget_is_focus(current_tab_contents->GetContentNativeView())) {
1990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int command_id = GetCustomCommandId(event);
1991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (command_id == -1)
1992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      command_id = GetPreHandleCommandId(event);
1993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (command_id != -1 && browser_->ExecuteCommandIfEnabled(command_id))
1995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return TRUE;
1996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Propagate the key event to child widget first, so we don't override their
1998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // accelerators.
1999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!gtk_window_propagate_key_event(GTK_WINDOW(widget), event)) {
2000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!gtk_window_activate_key(GTK_WINDOW(widget), event)) {
2001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_bindings_activate_event(GTK_OBJECT(widget), event);
2002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
2003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
2005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool rv = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
2006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(rv);
2007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Prevents the default handler from handling this event.
2010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
2011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserWindowGtk::OnMouseMoveEvent(GtkWidget* widget,
2014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            GdkEventMotion* event) {
2015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This method is used to update the mouse cursor when over the edge of the
2016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // custom frame.  If the custom frame is off or we're over some other widget,
2017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // do nothing.
2018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!UseCustomFrame() || event->window != widget->window) {
2019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Reset the cursor.
2020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (frame_cursor_) {
2021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame_cursor_ = NULL;
2022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL);
2023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return FALSE;
2025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the cursor if we're on the custom frame border.
2028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkWindowEdge edge;
2029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool has_hit_edge = GetWindowEdge(static_cast<int>(event->x),
2030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    static_cast<int>(event->y), &edge);
2031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkCursorType new_cursor = GDK_LAST_CURSOR;
2032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (has_hit_edge)
2033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_cursor = GdkWindowEdgeToGdkCursorType(edge);
2034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkCursorType last_cursor = GDK_LAST_CURSOR;
2036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (frame_cursor_)
2037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    last_cursor = frame_cursor_->type;
2038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (last_cursor != new_cursor) {
2040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (has_hit_edge) {
2041201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      frame_cursor_ = gfx::GetCursor(new_cursor);
2042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
2043201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      frame_cursor_ = NULL;
2044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2045201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    gdk_window_set_cursor(GTK_WIDGET(window_)->window, frame_cursor_);
2046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
2048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserWindowGtk::OnButtonPressEvent(GtkWidget* widget,
2051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                              GdkEventButton* event) {
2052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Handle back/forward.
2053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event->type == GDK_BUTTON_PRESS) {
2054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (event->button == 8) {
2055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_->GoBack(CURRENT_TAB);
2056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return TRUE;
2057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (event->button == 9) {
2058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_->GoForward(CURRENT_TAB);
2059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return TRUE;
2060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Handle left, middle and right clicks.  In particular, we care about clicks
2064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in the custom frame border and clicks in the titlebar.
2065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make the button press coordinate relative to the browser window.
2067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int win_x, win_y;
2068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_window_get_origin(GTK_WIDGET(window_)->window, &win_x, &win_y);
2069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkWindowEdge edge;
2071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point point(static_cast<int>(event->x_root - win_x),
2072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   static_cast<int>(event->y_root - win_y));
2073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool has_hit_edge = GetWindowEdge(point.x(), point.y(), &edge);
2074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ignore clicks that are in/below the browser toolbar.
2076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* toolbar = toolbar_->widget();
2077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GTK_WIDGET_VISIBLE(toolbar)) {
2078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If the toolbar is not showing, use the location of web contents as the
2079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // boundary of where to ignore clicks.
2080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    toolbar = render_area_vbox_;
2081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint toolbar_y;
2083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_get_pointer(toolbar, NULL, &toolbar_y);
2084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool has_hit_titlebar = !IsFullscreen() && (toolbar_y < 0)
2085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          && !has_hit_edge;
2086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event->button == 1) {
2087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (GDK_BUTTON_PRESS == event->type) {
2088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      guint32 last_click_time = last_click_time_;
2089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Point last_click_position = last_click_position_;
2090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      last_click_time_ = event->time;
2091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      last_click_position_ = gfx::Point(static_cast<int>(event->x),
2092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        static_cast<int>(event->y));
2093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Raise the window after a click on either the titlebar or the border to
2095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // match the behavior of most window managers, unless that behavior has
2096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // been suppressed.
2097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if ((has_hit_titlebar || has_hit_edge) && !suppress_window_raise_)
2098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gdk_window_raise(GTK_WIDGET(window_)->window);
2099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (has_hit_titlebar) {
2101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // We want to start a move when the user single clicks, but not start a
2102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // move when the user double clicks.  However, a double click sends the
2103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // following GDK events: GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE,
2104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE.  If we
2105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // start a gtk_window_begin_move_drag on the second GDK_BUTTON_PRESS,
2106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // the call to gtk_window_maximize fails.  To work around this, we
2107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // keep track of the last click and if it's going to be a double click,
2108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // we don't call gtk_window_begin_move_drag.
2109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        static GtkSettings* settings = gtk_settings_get_default();
2110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gint double_click_time = 250;
2111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gint double_click_distance = 5;
2112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_object_get(G_OBJECT(settings),
2113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     "gtk-double-click-time", &double_click_time,
2114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     "gtk-double-click-distance", &double_click_distance,
2115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     NULL);
2116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        guint32 click_time = event->time - last_click_time;
21183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        int click_move_x = abs(event->x - last_click_position.x());
21193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        int click_move_y = abs(event->y - last_click_position.y());
2120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (click_time > static_cast<guint32>(double_click_time) ||
2122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            click_move_x > double_click_distance ||
2123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            click_move_y > double_click_distance) {
2124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // Ignore drag requests if the window is the size of the screen.
2125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // We do this to avoid triggering fullscreen mode in metacity
2126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // (without the --no-force-fullscreen flag) and in compiz (with
2127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // Legacy Fullscreen Mode enabled).
21283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          if (!BoundsMatchMonitorSize()) {
2129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            gtk_window_begin_move_drag(window_, event->button,
2130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       static_cast<gint>(event->x_root),
2131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       static_cast<gint>(event->y_root),
2132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       event->time);
2133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
2134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          return TRUE;
2135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
2136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (has_hit_edge) {
2137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_window_begin_resize_drag(window_, edge, event->button,
2138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     static_cast<gint>(event->x_root),
2139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     static_cast<gint>(event->y_root),
2140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     event->time);
2141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return TRUE;
2142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
2143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (GDK_2BUTTON_PRESS == event->type) {
2144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (has_hit_titlebar) {
2145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Maximize/restore on double click.
2146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (IsMaximized()) {
2147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          UnMaximize();
2148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
2149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          gtk_window_maximize(window_);
2150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
2151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return TRUE;
2152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
2153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (event->button == 2) {
2155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (has_hit_titlebar || has_hit_edge) {
2156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_lower(GTK_WIDGET(window_)->window);
2157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return TRUE;
2159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (event->button == 3) {
2160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (has_hit_titlebar) {
216172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      titlebar_->ShowContextMenu(event);
2162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return TRUE;
2163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;  // Continue to propagate the event.
2167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
2170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::MainWindowMapped(GtkWidget* widget) {
2171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Map the X Window ID of the window to our window.
217272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  XID xid = ui::GetX11WindowFromGtkWidget(widget);
2173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserWindowGtk::xid_map_.insert(
2174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::pair<XID, GtkWindow*>(xid, GTK_WINDOW(widget)));
2175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
2178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::MainWindowUnMapped(GtkWidget* widget) {
2179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Unmap the X Window ID.
218072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  XID xid = ui::GetX11WindowFromGtkWidget(widget);
2181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserWindowGtk::xid_map_.erase(xid);
2182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserWindowGtk::OnFocusIn(GtkWidget* widget,
2185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     GdkEventFocus* event) {
2186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserList::SetLastActive(browser_.get());
2187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
2188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserWindowGtk::OnFocusOut(GtkWidget* widget,
2191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      GdkEventFocus* event) {
2192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
2193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::ShowSupportedWindowFeatures() {
2196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsTabStripSupported())
2197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip_->Show();
2198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsToolbarSupported()) {
2200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    toolbar_->Show();
2201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_show(toolbar_border_);
2202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_window_lower(toolbar_border_->window);
2203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsBookmarkBarSupported())
2206201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MaybeShowBookmarkBar(false);
2207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::HideUnsupportedWindowFeatures() {
2210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsTabStripSupported())
2211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip_->Hide();
2212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsToolbarSupported())
2214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    toolbar_->Hide();
2215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the bookmark bar shelf is unsupported, then we never create it.
2217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsTabStripSupported() const {
2220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
2221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsToolbarSupported() const {
2224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
2225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
2226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::IsBookmarkBarSupported() const {
2229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR);
2230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::UsingCustomPopupFrame() const {
2233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GtkThemeService* theme_provider = GtkThemeService::GetFrom(
2234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser()->profile());
2235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return !theme_provider->UseGtkTheme() &&
2236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser()->type() & Browser::TYPE_POPUP;
2237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) {
2240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!UseCustomFrame())
2241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
2242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsMaximized() || IsFullscreen())
2244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
2245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (x < kFrameBorderThickness) {
2247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Left edge.
2248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (y < kResizeAreaCornerSize - kTopResizeAdjust) {
2249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *edge = GDK_WINDOW_EDGE_NORTH_WEST;
2250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (y < bounds_.height() - kResizeAreaCornerSize) {
2251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *edge = GDK_WINDOW_EDGE_WEST;
2252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
2253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *edge = GDK_WINDOW_EDGE_SOUTH_WEST;
2254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
2256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (x < bounds_.width() - kFrameBorderThickness) {
2257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (y < kFrameBorderThickness - kTopResizeAdjust) {
2258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Top edge.
2259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (x < kResizeAreaCornerSize) {
2260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *edge = GDK_WINDOW_EDGE_NORTH_WEST;
2261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (x < bounds_.width() - kResizeAreaCornerSize) {
2262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *edge = GDK_WINDOW_EDGE_NORTH;
2263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
2264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *edge = GDK_WINDOW_EDGE_NORTH_EAST;
2265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
2266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (y < bounds_.height() - kFrameBorderThickness) {
2267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Ignore the middle content area.
2268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
2269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
2270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Bottom edge.
2271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (x < kResizeAreaCornerSize) {
2272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *edge = GDK_WINDOW_EDGE_SOUTH_WEST;
2273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (x < bounds_.width() - kResizeAreaCornerSize) {
2274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *edge = GDK_WINDOW_EDGE_SOUTH;
2275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
2276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *edge = GDK_WINDOW_EDGE_SOUTH_EAST;
2277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
2278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
2280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
2281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Right edge.
2282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (y < kResizeAreaCornerSize - kTopResizeAdjust) {
2283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *edge = GDK_WINDOW_EDGE_NORTH_EAST;
2284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (y < bounds_.height() - kResizeAreaCornerSize) {
2285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *edge = GDK_WINDOW_EDGE_EAST;
2286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
2287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *edge = GDK_WINDOW_EDGE_SOUTH_EAST;
2288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
2290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
229172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTREACHED();
229372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
2294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::UseCustomFrame() {
2297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't use the custom frame for app mode windows or app window popups.
2298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return use_custom_frame_pref_.GetValue() &&
2299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_->type() != Browser::TYPE_APP &&
2300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_->type() != Browser::TYPE_APP_POPUP;
2301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BrowserWindowGtk::BoundsMatchMonitorSize() {
23043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // A screen can be composed of multiple monitors.
23053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GdkScreen* screen = gtk_window_get_screen(window_);
23063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gint monitor_num = gdk_screen_get_monitor_at_window(screen,
23073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      GTK_WIDGET(window_)->window);
23083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GdkRectangle monitor_size;
23103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor_size);
23113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return bounds_.size() == gfx::Size(monitor_size.width, monitor_size.height);
23123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
23133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserWindowGtk::PlaceBookmarkBar(bool is_floating) {
2315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* parent = gtk_widget_get_parent(bookmark_bar_->widget());
2316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (parent)
2317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_remove(GTK_CONTAINER(parent), bookmark_bar_->widget());
2318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!is_floating) {
2320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Place the bookmark bar at the end of |window_vbox_|; this happens after
2321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // we have placed the render area at the end of |window_vbox_| so we will
2322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // be above the render area.
2323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_end(GTK_BOX(window_vbox_), bookmark_bar_->widget(),
2324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     FALSE, FALSE, 0);
2325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
2326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Place the bookmark bar at the end of the render area; this happens after
2327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the tab contents container has been placed there so we will be
2328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // above the webpage (in terms of y).
2329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_end(GTK_BOX(render_area_vbox_), bookmark_bar_->widget(),
2330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     FALSE, FALSE, 0);
2331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
2335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserWindowGtk::GetCustomFramePrefDefault() {
2336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string wm_name;
233772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!ui::GetWindowManagerName(&wm_name))
2338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
2339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ideally, we'd use the custom frame by default and just fall back on using
2341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // system decorations for the few (?) tiling window managers where the custom
2342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // frame doesn't make sense (e.g. awesome, ion3, ratpoison, xmonad, etc.) or
2343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // other WMs where it has issues (e.g. Fluxbox -- see issue 19130).  The EWMH
2344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // _NET_SUPPORTING_WM property makes it easy to look up a name for the current
2345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WM, but at least some of the WMs in the latter group don't set it.
2346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Instead, we default to using system decorations for all WMs and
2347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // special-case the ones where the custom frame should be used.  These names
2348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // are taken from the WMs' source code.
2349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (wm_name == "Blackbox" ||
2350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          wm_name == "compiz" ||
2351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          wm_name == "e16" ||  // Enlightenment DR16
2352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          wm_name == "Metacity" ||
2353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          wm_name == "Mutter" ||
2354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          wm_name == "Openbox" ||
2355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          wm_name == "Xfwm4");
2356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2357