| Index: chrome/browser/ui/gtk/browser_window_gtk.cc
|
| diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
|
| deleted file mode 100644
|
| index 9c6c24368e69eeb7b2862fad54b2d4720b8b81ac..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/gtk/browser_window_gtk.cc
|
| +++ /dev/null
|
| @@ -1,2385 +0,0 @@
|
| -// Copyright 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/ui/gtk/browser_window_gtk.h"
|
| -
|
| -#include <gdk/gdkkeysyms.h>
|
| -
|
| -#include <algorithm>
|
| -#include <string>
|
| -
|
| -#include "base/base_paths.h"
|
| -#include "base/bind.h"
|
| -#include "base/command_line.h"
|
| -#include "base/debug/trace_event.h"
|
| -#include "base/environment.h"
|
| -#include "base/i18n/file_util_icu.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/memory/singleton.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/nix/xdg_util.h"
|
| -#include "base/path_service.h"
|
| -#include "base/prefs/pref_service.h"
|
| -#include "base/prefs/scoped_user_pref_update.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "base/time/time.h"
|
| -#include "chrome/app/chrome_command_ids.h"
|
| -#include "chrome/browser/app_mode/app_mode_utils.h"
|
| -#include "chrome/browser/browser_process.h"
|
| -#include "chrome/browser/chrome_notification_types.h"
|
| -#include "chrome/browser/download/download_item_model.h"
|
| -#include "chrome/browser/extensions/tab_helper.h"
|
| -#include "chrome/browser/infobars/infobar_service.h"
|
| -#include "chrome/browser/profiles/profile.h"
|
| -#include "chrome/browser/themes/theme_properties.h"
|
| -#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
|
| -#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
|
| -#include "chrome/browser/ui/browser.h"
|
| -#include "chrome/browser/ui/browser_command_controller.h"
|
| -#include "chrome/browser/ui/browser_commands.h"
|
| -#include "chrome/browser/ui/browser_dialogs.h"
|
| -#include "chrome/browser/ui/browser_list.h"
|
| -#include "chrome/browser/ui/browser_window_state.h"
|
| -#include "chrome/browser/ui/find_bar/find_bar_controller.h"
|
| -#include "chrome/browser/ui/find_bar/find_tab_helper.h"
|
| -#include "chrome/browser/ui/gtk/accelerators_gtk.h"
|
| -#include "chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h"
|
| -#include "chrome/browser/ui/gtk/avatar_menu_button_gtk.h"
|
| -#include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h"
|
| -#include "chrome/browser/ui/gtk/browser_titlebar.h"
|
| -#include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
|
| -#include "chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h"
|
| -#include "chrome/browser/ui/gtk/download/download_in_progress_dialog_gtk.h"
|
| -#include "chrome/browser/ui/gtk/download/download_shelf_gtk.h"
|
| -#include "chrome/browser/ui/gtk/edit_search_engine_dialog.h"
|
| -#include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
|
| -#include "chrome/browser/ui/gtk/find_bar_gtk.h"
|
| -#include "chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h"
|
| -#include "chrome/browser/ui/gtk/global_menu_bar.h"
|
| -#include "chrome/browser/ui/gtk/gtk_theme_service.h"
|
| -#include "chrome/browser/ui/gtk/gtk_util.h"
|
| -#include "chrome/browser/ui/gtk/gtk_window_util.h"
|
| -#include "chrome/browser/ui/gtk/infobars/infobar_container_gtk.h"
|
| -#include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
|
| -#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
|
| -#include "chrome/browser/ui/gtk/nine_box.h"
|
| -#include "chrome/browser/ui/gtk/one_click_signin_bubble_gtk.h"
|
| -#include "chrome/browser/ui/gtk/password_generation_bubble_gtk.h"
|
| -#include "chrome/browser/ui/gtk/reload_button_gtk.h"
|
| -#include "chrome/browser/ui/gtk/status_bubble_gtk.h"
|
| -#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
|
| -#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
|
| -#include "chrome/browser/ui/gtk/task_manager_gtk.h"
|
| -#include "chrome/browser/ui/gtk/update_recommended_dialog.h"
|
| -#include "chrome/browser/ui/gtk/website_settings/website_settings_popup_gtk.h"
|
| -#include "chrome/browser/ui/omnibox/location_bar.h"
|
| -#include "chrome/browser/ui/omnibox/omnibox_view.h"
|
| -#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
| -#include "chrome/browser/web_applications/web_app.h"
|
| -#include "chrome/common/chrome_switches.h"
|
| -#include "chrome/common/pref_names.h"
|
| -#include "components/user_prefs/pref_registry_syncable.h"
|
| -#include "content/public/browser/download_manager.h"
|
| -#include "content/public/browser/native_web_keyboard_event.h"
|
| -#include "content/public/browser/notification_service.h"
|
| -#include "content/public/browser/render_view_host.h"
|
| -#include "content/public/browser/render_widget_host_view.h"
|
| -#include "content/public/browser/web_contents.h"
|
| -#include "content/public/browser/web_contents_view.h"
|
| -#include "grit/chromium_strings.h"
|
| -#include "grit/generated_resources.h"
|
| -#include "grit/theme_resources.h"
|
| -#include "grit/ui_resources.h"
|
| -#include "ui/base/accelerators/platform_accelerator_gtk.h"
|
| -#include "ui/base/gtk/gtk_floating_container.h"
|
| -#include "ui/base/gtk/gtk_hig_constants.h"
|
| -#include "ui/base/gtk/gtk_screen_util.h"
|
| -#include "ui/base/l10n/l10n_util.h"
|
| -#include "ui/base/resource/resource_bundle.h"
|
| -#include "ui/base/x/active_window_watcher_x.h"
|
| -#include "ui/events/keycodes/keyboard_codes.h"
|
| -#include "ui/gfx/gtk_util.h"
|
| -#include "ui/gfx/image/cairo_cached_surface.h"
|
| -#include "ui/gfx/image/image.h"
|
| -#include "ui/gfx/rect.h"
|
| -#include "ui/gfx/screen.h"
|
| -#include "ui/gfx/skia_utils_gtk.h"
|
| -
|
| -using content::NativeWebKeyboardEvent;
|
| -using content::SSLStatus;
|
| -using content::WebContents;
|
| -using web_modal::WebContentsModalDialogHost;
|
| -
|
| -#error "The GTK+ port will be deleted later this week. If you are seeing this, you are trying to compile it. Please check your gyp flags for 'use_aura=0' and remove them."
|
| -
|
| -namespace {
|
| -
|
| -// The number of milliseconds between loading animation frames.
|
| -const int kLoadingAnimationFrameTimeMs = 30;
|
| -
|
| -const char* kBrowserWindowKey = "__BROWSER_WINDOW_GTK__";
|
| -
|
| -// While resize areas on Windows are normally the same size as the window
|
| -// borders, our top area is shrunk by 1 px to make it easier to move the window
|
| -// around with our thinner top grabbable strip. (Incidentally, our side and
|
| -// bottom resize areas don't match the frame border thickness either -- they
|
| -// span the whole nonclient area, so there's no "dead zone" for the mouse.)
|
| -const int kTopResizeAdjust = 1;
|
| -// The thickness of the shadow around the toolbar+web content area. There are
|
| -// actually a couple pixels more that should overlap the toolbar and web
|
| -// content area, but we don't use those pixels.
|
| -const int kContentShadowThickness = 2;
|
| -// The offset to the background when the custom frame is off. We want the
|
| -// window background to line up with the tab background regardless of whether
|
| -// we're in custom frame mode or not. Since themes are designed with the
|
| -// custom frame in mind, we need to offset the background when the custom frame
|
| -// is off.
|
| -const int kCustomFrameBackgroundVerticalOffset = 15;
|
| -
|
| -// The timeout in milliseconds before we'll get the true window position with
|
| -// gtk_window_get_position() after the last GTK configure-event signal.
|
| -const int kDebounceTimeoutMilliseconds = 100;
|
| -
|
| -// Using gtk_window_get_position/size creates a race condition, so only use
|
| -// this to get the initial bounds. After window creation, we pick up the
|
| -// normal bounds by connecting to the configure-event signal.
|
| -gfx::Rect GetInitialWindowBounds(GtkWindow* window) {
|
| - gint x, y, width, height;
|
| - gtk_window_get_position(window, &x, &y);
|
| - gtk_window_get_size(window, &width, &height);
|
| - return gfx::Rect(x, y, width, height);
|
| -}
|
| -
|
| -// Get the command ids of the key combinations that are not valid gtk
|
| -// accelerators.
|
| -int GetCustomCommandId(GdkEventKey* event) {
|
| - // Filter modifier to only include accelerator modifiers.
|
| - guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
|
| - switch (event->keyval) {
|
| - // Gtk doesn't allow GDK_Tab or GDK_ISO_Left_Tab to be an accelerator (see
|
| - // gtk_accelerator_valid), so we need to handle these accelerators
|
| - // manually.
|
| - // Some X clients (e.g. cygwin, NX client, etc.) also send GDK_KP_Tab when
|
| - // typing a tab key. We should also handle GDK_KP_Tab for such X clients as
|
| - // Firefox does.
|
| - case GDK_Tab:
|
| - case GDK_ISO_Left_Tab:
|
| - case GDK_KP_Tab:
|
| - if (GDK_CONTROL_MASK == modifier) {
|
| - return IDC_SELECT_NEXT_TAB;
|
| - } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
|
| - return IDC_SELECT_PREVIOUS_TAB;
|
| - }
|
| - break;
|
| -
|
| - default:
|
| - break;
|
| - }
|
| - return -1;
|
| -}
|
| -
|
| -// Get the command ids of the accelerators that we don't want the native widget
|
| -// to be able to override.
|
| -int GetPreHandleCommandId(GdkEventKey* event) {
|
| - // Filter modifier to only include accelerator modifiers.
|
| - guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
|
| - switch (event->keyval) {
|
| - case GDK_Page_Down:
|
| - if (GDK_CONTROL_MASK == modifier) {
|
| - return IDC_SELECT_NEXT_TAB;
|
| - } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
|
| - return IDC_MOVE_TAB_NEXT;
|
| - }
|
| - break;
|
| -
|
| - case GDK_Page_Up:
|
| - if (GDK_CONTROL_MASK == modifier) {
|
| - return IDC_SELECT_PREVIOUS_TAB;
|
| - } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
|
| - return IDC_MOVE_TAB_PREVIOUS;
|
| - }
|
| - break;
|
| -
|
| - default:
|
| - break;
|
| - }
|
| - return -1;
|
| -}
|
| -
|
| -GQuark GetBrowserWindowQuarkKey() {
|
| - static GQuark quark = g_quark_from_static_string(kBrowserWindowKey);
|
| - return quark;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -BrowserWindowGtk::BrowserWindowGtk(Browser* browser)
|
| - : window_(NULL),
|
| - window_has_shown_(false),
|
| - window_container_(NULL),
|
| - window_vbox_(NULL),
|
| - render_area_vbox_(NULL),
|
| - render_area_floating_container_(NULL),
|
| - render_area_event_box_(NULL),
|
| - toolbar_border_(NULL),
|
| - browser_(browser),
|
| - state_(GDK_WINDOW_STATE_WITHDRAWN),
|
| - devtools_window_(NULL),
|
| - devtools_floating_container_(NULL),
|
| - frame_cursor_(NULL),
|
| - is_active_(false),
|
| - show_state_after_show_(ui::SHOW_STATE_DEFAULT),
|
| - suppress_window_raise_(false),
|
| - accel_group_(NULL),
|
| - is_fullscreen_(false) {
|
| -}
|
| -
|
| -BrowserWindowGtk::~BrowserWindowGtk() {
|
| - ui::ActiveWindowWatcherX::RemoveObserver(this);
|
| -
|
| - browser_->tab_strip_model()->RemoveObserver(this);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Init() {
|
| - // We register first so that other views like the toolbar can use the
|
| - // is_active() function in their ActiveWindowChanged() handlers.
|
| - ui::ActiveWindowWatcherX::AddObserver(this);
|
| -
|
| - use_custom_frame_pref_.Init(
|
| - prefs::kUseCustomChromeFrame,
|
| - browser_->profile()->GetPrefs(),
|
| - base::Bind(&BrowserWindowGtk::OnUseCustomChromeFrameChanged,
|
| - base::Unretained(this)));
|
| -
|
| - // Register to be notified of changes to the profile's avatar icon.
|
| - if (!browser_->profile()->IsOffTheRecord()) {
|
| - registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
|
| - content::NotificationService::AllSources());
|
| - }
|
| -
|
| - // In some (older) versions of compiz, raising top-level windows when they
|
| - // are partially off-screen causes them to get snapped back on screen, not
|
| - // always even on the current virtual desktop. If we are running under
|
| - // compiz, suppress such raises, as they are not necessary in compiz anyway.
|
| - if (ui::GuessWindowManager() == ui::WM_COMPIZ)
|
| - suppress_window_raise_ = true;
|
| -
|
| - window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
|
| - g_object_set_qdata(G_OBJECT(window_), GetBrowserWindowQuarkKey(), this);
|
| - gtk_widget_add_events(GTK_WIDGET(window_), GDK_BUTTON_PRESS_MASK |
|
| - GDK_POINTER_MOTION_MASK);
|
| -
|
| - // Disable the resize gripper on Ubuntu.
|
| - gtk_window_util::DisableResizeGrip(window_);
|
| -
|
| - // Add this window to its own unique window group to allow for
|
| - // window-to-parent modality.
|
| - gtk_window_group_add_window(gtk_window_group_new(), window_);
|
| - g_object_unref(gtk_window_get_group(window_));
|
| -
|
| - // Set up a custom WM_CLASS for some sorts of window types. This allows
|
| - // task switchers to distinguish between main browser windows and e.g
|
| - // app windows.
|
| - const CommandLine& command_line = *CommandLine::ForCurrentProcess();
|
| - if (browser_->is_app()) {
|
| - std::string app_name = browser_->app_name();
|
| - if (app_name != DevToolsWindow::kDevToolsApp) {
|
| - gtk_window_util::SetWindowCustomClass(window_,
|
| - web_app::GetWMClassFromAppName(app_name));
|
| - }
|
| - } else if (command_line.HasSwitch(switches::kUserDataDir)) {
|
| - // Set the class name to e.g. "Chrome (/tmp/my-user-data)". The
|
| - // class name will show up in the alt-tab list in gnome-shell if
|
| - // you're running a binary that doesn't have a matching .desktop
|
| - // file.
|
| - const std::string user_data_dir =
|
| - command_line.GetSwitchValueNative(switches::kUserDataDir);
|
| - gtk_window_util::SetWindowCustomClass(window_,
|
| - std::string(gdk_get_program_class()) + " (" + user_data_dir + ")");
|
| - }
|
| -
|
| - // For popups, we initialize widgets then set the window geometry, because
|
| - // popups need the widgets inited before they can set the window size
|
| - // properly. For other windows, we set the geometry first to prevent resize
|
| - // flicker.
|
| - if (browser_->is_type_popup()) {
|
| - gtk_window_set_role(window_, "pop-up");
|
| - InitWidgets();
|
| - SetGeometryHints();
|
| - } else {
|
| - gtk_window_set_role(window_, "browser");
|
| - SetGeometryHints();
|
| - InitWidgets();
|
| - }
|
| -
|
| - ConnectAccelerators();
|
| -
|
| - // Set the initial background color of widgets.
|
| - SetBackgroundColor();
|
| - HideUnsupportedWindowFeatures();
|
| -
|
| - if (UseCustomFrame()) {
|
| - // Setting _GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED tells gnome-shell to not force
|
| - // fullscreen on the window when it matches the desktop size.
|
| - ui::SetHideTitlebarWhenMaximizedProperty(
|
| - ui::GetX11WindowFromGtkWidget(GTK_WIDGET(window_)),
|
| - ui::HIDE_TITLEBAR_WHEN_MAXIMIZED);
|
| - }
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget,
|
| - GdkEventExpose* event) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::OnCustomFrameExpose");
|
| -
|
| - // Draw the default background.
|
| - cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget));
|
| - gdk_cairo_rectangle(cr, &event->area);
|
| - cairo_clip(cr);
|
| -
|
| - if (UsingCustomPopupFrame()) {
|
| - DrawPopupFrame(cr, widget, event);
|
| - } else {
|
| - DrawCustomFrame(cr, widget, event);
|
| - }
|
| -
|
| - DrawContentShadow(cr);
|
| -
|
| - cairo_destroy(cr);
|
| -
|
| - if (UseCustomFrame() && !IsMaximized())
|
| - DrawCustomFrameBorder(widget);
|
| -
|
| - return FALSE; // Allow subwidgets to paint.
|
| -}
|
| -
|
| -void BrowserWindowGtk::DrawCustomFrameBorder(GtkWidget* widget) {
|
| - static NineBox* custom_frame_border = NULL;
|
| - if (!custom_frame_border) {
|
| - custom_frame_border = new NineBox(IDR_WINDOW_TOP_LEFT_CORNER,
|
| - IDR_WINDOW_TOP_CENTER,
|
| - IDR_WINDOW_TOP_RIGHT_CORNER,
|
| - IDR_WINDOW_LEFT_SIDE,
|
| - 0,
|
| - IDR_WINDOW_RIGHT_SIDE,
|
| - IDR_WINDOW_BOTTOM_LEFT_CORNER,
|
| - IDR_WINDOW_BOTTOM_CENTER,
|
| - IDR_WINDOW_BOTTOM_RIGHT_CORNER);
|
| - }
|
| - custom_frame_border->RenderToWidget(widget);
|
| -}
|
| -
|
| -void BrowserWindowGtk::DrawContentShadow(cairo_t* cr) {
|
| - // Draw the shadow above the toolbar. Tabs on the tabstrip will draw over us.
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - int left_x, top_y;
|
| - gtk_widget_translate_coordinates(toolbar_->widget(),
|
| - GTK_WIDGET(window_), 0, 0, &left_x,
|
| - &top_y);
|
| -
|
| - GtkAllocation window_vbox_allocation;
|
| - gtk_widget_get_allocation(window_vbox_, &window_vbox_allocation);
|
| - int center_width = window_vbox_allocation.width;
|
| -
|
| - gfx::CairoCachedSurface* top_center =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_TOP_CENTER).ToCairo();
|
| - gfx::CairoCachedSurface* top_right =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_TOP_RIGHT_CORNER).ToCairo();
|
| - gfx::CairoCachedSurface* top_left =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_TOP_LEFT_CORNER).ToCairo();
|
| -
|
| - int center_left_x = left_x;
|
| - if (ShouldDrawContentDropShadow()) {
|
| - // Don't draw over the corners.
|
| - center_left_x += top_left->Width() - kContentShadowThickness;
|
| - center_width -= (top_left->Width() + top_right->Width());
|
| - center_width += 2 * kContentShadowThickness;
|
| - }
|
| -
|
| - top_center->SetSource(cr, GTK_WIDGET(window_),
|
| - center_left_x, top_y - kContentShadowThickness);
|
| - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
|
| - cairo_rectangle(cr, center_left_x, top_y - kContentShadowThickness,
|
| - center_width, top_center->Height());
|
| - cairo_fill(cr);
|
| -
|
| - // Only draw the rest of the shadow if the user has the custom frame enabled
|
| - // and the browser is not maximized.
|
| - if (!ShouldDrawContentDropShadow())
|
| - return;
|
| -
|
| - // The top left corner has a width of 3 pixels. On Windows, the last column
|
| - // of pixels overlap the toolbar. We just crop it off on Linux. The top
|
| - // corners extend to the base of the toolbar (one pixel above the dividing
|
| - // line).
|
| - int right_x = center_left_x + center_width;
|
| - top_left->SetSource(cr, GTK_WIDGET(window_),
|
| - left_x - kContentShadowThickness, top_y - kContentShadowThickness);
|
| - // The toolbar is shorter in location bar only mode so clip the image to the
|
| - // height of the toolbar + the amount of shadow above the toolbar.
|
| - cairo_rectangle(cr,
|
| - left_x - kContentShadowThickness,
|
| - top_y - kContentShadowThickness,
|
| - top_left->Width(),
|
| - top_left->Height());
|
| - cairo_fill(cr);
|
| -
|
| - // Likewise, we crop off the left column of pixels for the top right corner.
|
| - top_right->SetSource(cr, GTK_WIDGET(window_),
|
| - right_x, top_y - kContentShadowThickness);
|
| - cairo_rectangle(cr,
|
| - right_x,
|
| - top_y - kContentShadowThickness,
|
| - top_right->Width(),
|
| - top_right->Height());
|
| - cairo_fill(cr);
|
| -
|
| - // Fill in the sides. As above, we only draw 2 of the 3 columns on Linux.
|
| - int bottom_y;
|
| - gtk_widget_translate_coordinates(window_vbox_,
|
| - GTK_WIDGET(window_),
|
| - 0, window_vbox_allocation.height,
|
| - NULL, &bottom_y);
|
| - // |side_y| is where to start drawing the side shadows. The top corners draw
|
| - // the sides down to the bottom of the toolbar.
|
| - int side_y = top_y - kContentShadowThickness + top_right->Height();
|
| - // |side_height| is how many pixels to draw for the side borders. We do one
|
| - // pixel before the bottom of the web contents because that extra pixel is
|
| - // drawn by the bottom corners.
|
| - int side_height = bottom_y - side_y - 1;
|
| - if (side_height > 0) {
|
| - gfx::CairoCachedSurface* left =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_LEFT_SIDE).ToCairo();
|
| - left->SetSource(cr, GTK_WIDGET(window_),
|
| - left_x - kContentShadowThickness, side_y);
|
| - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
|
| - cairo_rectangle(cr,
|
| - left_x - kContentShadowThickness,
|
| - side_y,
|
| - kContentShadowThickness,
|
| - side_height);
|
| - cairo_fill(cr);
|
| -
|
| - gfx::CairoCachedSurface* right =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_RIGHT_SIDE).ToCairo();
|
| - int right_side_x =
|
| - right_x + top_right->Width() - kContentShadowThickness - 1;
|
| - right->SetSource(cr, GTK_WIDGET(window_), right_side_x, side_y);
|
| - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
|
| - cairo_rectangle(cr,
|
| - right_side_x,
|
| - side_y,
|
| - kContentShadowThickness,
|
| - side_height);
|
| - cairo_fill(cr);
|
| - }
|
| -
|
| - // Draw the bottom corners. The bottom corners also draw the bottom row of
|
| - // pixels of the side shadows.
|
| - gfx::CairoCachedSurface* bottom_left =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER).ToCairo();
|
| - bottom_left->SetSource(cr, GTK_WIDGET(window_),
|
| - left_x - kContentShadowThickness, bottom_y - 1);
|
| - cairo_paint(cr);
|
| -
|
| - gfx::CairoCachedSurface* bottom_right =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER).ToCairo();
|
| - bottom_right->SetSource(cr, GTK_WIDGET(window_), right_x - 1, bottom_y - 1);
|
| - cairo_paint(cr);
|
| -
|
| - // Finally, draw the bottom row. Since we don't overlap the contents, we clip
|
| - // the top row of pixels.
|
| - gfx::CairoCachedSurface* bottom =
|
| - rb.GetNativeImageNamed(IDR_CONTENT_BOTTOM_CENTER).ToCairo();
|
| - bottom->SetSource(cr, GTK_WIDGET(window_), left_x + 1, bottom_y - 1);
|
| - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
|
| - cairo_rectangle(cr,
|
| - left_x + 1,
|
| - bottom_y,
|
| - window_vbox_allocation.width - 2,
|
| - kContentShadowThickness);
|
| - cairo_fill(cr);
|
| -}
|
| -
|
| -void BrowserWindowGtk::DrawPopupFrame(cairo_t* cr,
|
| - GtkWidget* widget,
|
| - GdkEventExpose* event) {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| -
|
| - // Like DrawCustomFrame(), except that we use the unthemed resources to draw
|
| - // the background. We do this because we can't rely on sane images in the
|
| - // theme that we can draw text on. (We tried using the tab background, but
|
| - // that has inverse saturation from what the user usually expects).
|
| - int image_name = GetThemeFrameResource();
|
| - gfx::CairoCachedSurface* surface =
|
| - rb.GetNativeImageNamed(image_name).ToCairo();
|
| - surface->SetSource(cr, widget, 0, GetVerticalOffset());
|
| - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REFLECT);
|
| - cairo_rectangle(cr, event->area.x, event->area.y,
|
| - event->area.width, event->area.height);
|
| - cairo_fill(cr);
|
| -}
|
| -
|
| -void BrowserWindowGtk::DrawCustomFrame(cairo_t* cr,
|
| - GtkWidget* widget,
|
| - GdkEventExpose* event) {
|
| - GtkThemeService* theme_provider = GtkThemeService::GetFrom(
|
| - browser()->profile());
|
| -
|
| - int image_name = GetThemeFrameResource();
|
| -
|
| - gfx::CairoCachedSurface* surface = theme_provider->GetImageNamed(
|
| - image_name).ToCairo();
|
| - if (event->area.y < surface->Height()) {
|
| - surface->SetSource(cr, widget, 0, GetVerticalOffset());
|
| -
|
| - // The frame background isn't tiled vertically.
|
| - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
|
| - cairo_rectangle(cr, event->area.x, event->area.y,
|
| - event->area.width, surface->Height() - event->area.y);
|
| - cairo_fill(cr);
|
| - }
|
| -
|
| - if (theme_provider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) &&
|
| - !browser()->profile()->IsOffTheRecord()) {
|
| - gfx::CairoCachedSurface* theme_overlay = theme_provider->GetImageNamed(
|
| - DrawFrameAsActive() ? IDR_THEME_FRAME_OVERLAY
|
| - : IDR_THEME_FRAME_OVERLAY_INACTIVE).ToCairo();
|
| - theme_overlay->SetSource(cr, widget, 0, GetVerticalOffset());
|
| - cairo_paint(cr);
|
| - }
|
| -}
|
| -
|
| -int BrowserWindowGtk::GetVerticalOffset() {
|
| - return (IsMaximized() || (!UseCustomFrame())) ?
|
| - -kCustomFrameBackgroundVerticalOffset : 0;
|
| -}
|
| -
|
| -int BrowserWindowGtk::GetThemeFrameResource() {
|
| - bool incognito = browser()->profile()->IsOffTheRecord();
|
| - int image_name;
|
| - if (DrawFrameAsActive()) {
|
| - image_name = incognito ? IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
|
| - } else {
|
| - image_name = incognito ? IDR_THEME_FRAME_INCOGNITO_INACTIVE :
|
| - IDR_THEME_FRAME_INACTIVE;
|
| - }
|
| -
|
| - return image_name;
|
| -}
|
| -
|
| -void BrowserWindowGtk::Show() {
|
| - // The Browser associated with this browser window must become the active
|
| - // browser at the time Show() is called. This is the natural behaviour under
|
| - // Windows, but gtk_widget_show won't show the widget (and therefore won't
|
| - // call OnFocusIn()) until we return to the runloop. Therefore any calls to
|
| - // chrome::FindLastActiveWithHostDesktopType will return the previous
|
| - // browser instead if we don't explicitly set it here.
|
| - BrowserList::SetLastActive(browser());
|
| -
|
| - gtk_window_present(window_);
|
| - if (show_state_after_show_ == ui::SHOW_STATE_MAXIMIZED) {
|
| - gtk_window_maximize(window_);
|
| - show_state_after_show_ = ui::SHOW_STATE_NORMAL;
|
| - } else if (show_state_after_show_ == ui::SHOW_STATE_MINIMIZED) {
|
| - gtk_window_iconify(window_);
|
| - show_state_after_show_ = ui::SHOW_STATE_NORMAL;
|
| - }
|
| -
|
| - // If we have sized the window by setting a size request for the render
|
| - // area, then undo it so that the render view can later adjust its own
|
| - // size.
|
| - gtk_widget_set_size_request(devtools_floating_container_, -1, -1);
|
| -
|
| - window_has_shown_ = true;
|
| - browser()->OnWindowDidShow();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowInactive() {
|
| - gtk_window_set_focus_on_map(window_, false);
|
| - gtk_widget_show(GTK_WIDGET(window_));
|
| -}
|
| -
|
| -void BrowserWindowGtk::Hide() {
|
| - // Not implemented.
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetBoundsImpl(const gfx::Rect& bounds,
|
| - bool exterior,
|
| - bool move) {
|
| - gint x = static_cast<gint>(bounds.x());
|
| - gint y = static_cast<gint>(bounds.y());
|
| - gint width = static_cast<gint>(bounds.width());
|
| - gint height = static_cast<gint>(bounds.height());
|
| -
|
| - if (move)
|
| - gtk_window_move(window_, x, y);
|
| -
|
| - if (exterior) {
|
| - gtk_window_util::SetWindowSize(window_, gfx::Size(width, height));
|
| - } else {
|
| - gtk_widget_set_size_request(devtools_floating_container_,
|
| - width, height);
|
| - }
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetBounds(const gfx::Rect& bounds) {
|
| - if (IsFullscreen())
|
| - ExitFullscreen();
|
| - SetBoundsImpl(bounds, true, true);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Close() {
|
| - // We're already closing. Do nothing.
|
| - if (!window_)
|
| - return;
|
| -
|
| - if (!CanClose())
|
| - return;
|
| -
|
| - // We're going to destroy the window, make sure the tab strip isn't running
|
| - // any animations which may still reference GtkWidgets.
|
| - tabstrip_->StopAnimation();
|
| -
|
| - SaveWindowPosition();
|
| -
|
| - if (accel_group_) {
|
| - // Disconnecting the keys we connected to our accelerator group frees the
|
| - // closures allocated in ConnectAccelerators.
|
| - AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
|
| - for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
|
| - iter != accelerators->end(); ++iter) {
|
| - gtk_accel_group_disconnect_key(accel_group_,
|
| - ui::GetGdkKeyCodeForAccelerator(iter->second),
|
| - ui::GetGdkModifierForAccelerator(iter->second));
|
| - }
|
| - gtk_window_remove_accel_group(window_, accel_group_);
|
| - g_object_unref(accel_group_);
|
| - accel_group_ = NULL;
|
| - }
|
| -
|
| - // Cancel any pending callback from the window configure debounce timer.
|
| - window_configure_debounce_timer_.Stop();
|
| -
|
| - // Likewise for the loading animation.
|
| - loading_animation_timer_.Stop();
|
| -
|
| - GtkWidget* window = GTK_WIDGET(window_);
|
| - // To help catch bugs in any event handlers that might get fired during the
|
| - // destruction, set window_ to NULL before any handlers will run.
|
| - window_ = NULL;
|
| - // Avoid use-after-free in any code that runs after Close() and forgets to
|
| - // check window_.
|
| - window_container_ = NULL;
|
| - window_vbox_ = NULL;
|
| - render_area_vbox_ = NULL;
|
| - render_area_floating_container_ = NULL;
|
| - render_area_event_box_ = NULL;
|
| - toolbar_border_ = NULL;
|
| - devtools_floating_container_ = NULL;
|
| -
|
| - window_has_shown_ = false;
|
| - titlebar_->set_window(NULL);
|
| -
|
| - // We don't want GlobalMenuBar handling any notifications or commands after
|
| - // the window is destroyed.
|
| - global_menu_bar_->Disable();
|
| - gtk_widget_destroy(window);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Activate() {
|
| - gtk_window_present(window_);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Deactivate() {
|
| - gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsActive() const {
|
| - if (ui::ActiveWindowWatcherX::WMSupportsActivation())
|
| - return is_active_;
|
| -
|
| - // This still works even though we don't get the activation notification.
|
| - return window_ && gtk_window_is_active(window_);
|
| -}
|
| -
|
| -void BrowserWindowGtk::FlashFrame(bool flash) {
|
| - // May not be respected by all window managers.
|
| - gtk_window_set_urgency_hint(window_, flash);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsAlwaysOnTop() const {
|
| - return false;
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetAlwaysOnTop(bool always_on_top) {
|
| - // Not implemented for browser windows.
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -gfx::NativeWindow BrowserWindowGtk::GetNativeWindow() {
|
| - return window_;
|
| -}
|
| -
|
| -BrowserWindowTesting* BrowserWindowGtk::GetBrowserWindowTesting() {
|
| - NOTIMPLEMENTED();
|
| - return NULL;
|
| -}
|
| -
|
| -StatusBubble* BrowserWindowGtk::GetStatusBubble() {
|
| - return status_bubble_.get();
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateTitleBar() {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::UpdateTitleBar");
|
| - base::string16 title = browser_->GetWindowTitleForCurrentTab();
|
| - gtk_window_set_title(window_, base::UTF16ToUTF8(title).c_str());
|
| - if (ShouldShowWindowIcon())
|
| - titlebar_->UpdateTitleAndIcon();
|
| -}
|
| -
|
| -void BrowserWindowGtk::BookmarkBarStateChanged(
|
| - BookmarkBar::AnimateChangeType change_type) {
|
| - MaybeShowBookmarkBar(change_type == BookmarkBar::ANIMATE_STATE_CHANGE);
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateDevTools() {
|
| - UpdateDevToolsForContents(
|
| - browser_->tab_strip_model()->GetActiveWebContents());
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateLoadingAnimations(bool should_animate) {
|
| - if (should_animate) {
|
| - if (!loading_animation_timer_.IsRunning()) {
|
| - // Loads are happening, and the timer isn't running, so start it.
|
| - loading_animation_timer_.Start(FROM_HERE,
|
| - base::TimeDelta::FromMilliseconds(kLoadingAnimationFrameTimeMs), this,
|
| - &BrowserWindowGtk::LoadingAnimationCallback);
|
| - }
|
| - } else {
|
| - if (loading_animation_timer_.IsRunning()) {
|
| - loading_animation_timer_.Stop();
|
| - // Loads are now complete, update the state if a task was scheduled.
|
| - LoadingAnimationCallback();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void BrowserWindowGtk::LoadingAnimationCallback() {
|
| - if (browser_->is_type_tabbed()) {
|
| - // Loading animations are shown in the tab for tabbed windows. We check the
|
| - // browser type instead of calling IsTabStripVisible() because the latter
|
| - // will return false for fullscreen windows, but we still need to update
|
| - // their animations (so that when they come out of fullscreen mode they'll
|
| - // be correct).
|
| - tabstrip_->UpdateLoadingAnimations();
|
| - } else if (ShouldShowWindowIcon()) {
|
| - // ... or in the window icon area for popups and app windows.
|
| - WebContents* web_contents =
|
| - browser_->tab_strip_model()->GetActiveWebContents();
|
| - // GetSelectedTabContents can return NULL for example under Purify when
|
| - // the animations are running slowly and this function is called on
|
| - // a timer through LoadingAnimationCallback.
|
| - titlebar_->UpdateThrobber(web_contents);
|
| - }
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetStarredState(bool is_starred) {
|
| - toolbar_->GetLocationBarView()->SetStarred(is_starred);
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetTranslateIconToggled(bool is_lit) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::OnActiveTabChanged(WebContents* old_contents,
|
| - WebContents* new_contents,
|
| - int index,
|
| - int reason) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::ActiveTabChanged");
|
| - if (old_contents && !old_contents->IsBeingDestroyed())
|
| - old_contents->GetView()->StoreFocus();
|
| -
|
| - // Update various elements that are interested in knowing the current
|
| - // WebContents.
|
| - infobar_container_->ChangeInfoBarManager(
|
| - InfoBarService::FromWebContents(new_contents));
|
| - contents_container_->SetTab(new_contents);
|
| - UpdateDevToolsForContents(new_contents);
|
| -
|
| - // TODO(estade): after we manage browser activation, add a check to make sure
|
| - // we are the active browser before calling RestoreFocus().
|
| - if (!browser_->tab_strip_model()->closing_all()) {
|
| - new_contents->GetView()->RestoreFocus();
|
| - FindTabHelper* find_tab_helper =
|
| - FindTabHelper::FromWebContents(new_contents);
|
| - if (find_tab_helper->find_ui_active())
|
| - browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
|
| - }
|
| -
|
| - // Update all the UI bits.
|
| - UpdateTitleBar();
|
| - MaybeShowBookmarkBar(false);
|
| -}
|
| -void BrowserWindowGtk::ZoomChangedForActiveTab(bool can_show_bubble) {
|
| - toolbar_->GetLocationBarView()->ZoomChangedForActiveTab(
|
| - can_show_bubble && !toolbar_->IsWrenchMenuShowing());
|
| -}
|
| -
|
| -gfx::Rect BrowserWindowGtk::GetRestoredBounds() const {
|
| - return restored_bounds_;
|
| -}
|
| -
|
| -ui::WindowShowState BrowserWindowGtk::GetRestoredState() const {
|
| - if (IsMaximized())
|
| - return ui::SHOW_STATE_MAXIMIZED;
|
| - if (IsMinimized())
|
| - return ui::SHOW_STATE_MINIMIZED;
|
| - return ui::SHOW_STATE_NORMAL;
|
| -}
|
| -
|
| -gfx::Rect BrowserWindowGtk::GetBounds() const {
|
| - return bounds_;
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsMaximized() const {
|
| - return (state_ & GDK_WINDOW_STATE_MAXIMIZED);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsMinimized() const {
|
| - return (state_ & GDK_WINDOW_STATE_ICONIFIED);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Maximize() {
|
| - gtk_window_maximize(window_);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Minimize() {
|
| - gtk_window_iconify(window_);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Restore() {
|
| - if (IsMaximized())
|
| - UnMaximize();
|
| - else if (IsMinimized())
|
| - gtk_window_deiconify(window_);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::ShouldDrawContentDropShadow() const {
|
| - return !IsMaximized() && UseCustomFrame();
|
| -}
|
| -
|
| -void BrowserWindowGtk::EnterFullscreen(
|
| - const GURL& url, FullscreenExitBubbleType type) {
|
| - if (IsFullscreen())
|
| - return; // Nothing to do.
|
| - is_fullscreen_ = true;
|
| -
|
| - // gtk_window_(un)fullscreen asks the window manager to toggle the EWMH
|
| - // for fullscreen windows. Not all window managers support this.
|
| - gtk_window_fullscreen(window_);
|
| -
|
| - browser_->WindowFullscreenStateChanged();
|
| - UpdateCustomFrame();
|
| - toolbar_->Hide();
|
| - tabstrip_->Hide();
|
| - if (bookmark_bar_.get())
|
| - gtk_widget_hide(bookmark_bar_->widget());
|
| - if (!chrome::IsRunningInAppMode()) {
|
| - UpdateFullscreenExitBubbleContent(url, type);
|
| - }
|
| - gtk_widget_hide(titlebar_widget());
|
| - gtk_widget_hide(toolbar_border_);
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateFullscreenExitBubbleContent(
|
| - const GURL& url, FullscreenExitBubbleType bubble_type) {
|
| - if (!window_) {
|
| - // Don't create a fullscreen bubble for a closing window.
|
| - return;
|
| - } else if (bubble_type == FEB_TYPE_NONE) {
|
| - fullscreen_exit_bubble_.reset();
|
| - } else if (fullscreen_exit_bubble_.get()) {
|
| - fullscreen_exit_bubble_->UpdateContent(url, bubble_type);
|
| - } else {
|
| - fullscreen_exit_bubble_.reset(new FullscreenExitBubbleGtk(
|
| - GTK_FLOATING_CONTAINER(render_area_floating_container_),
|
| - browser(),
|
| - url,
|
| - bubble_type));
|
| - }
|
| -}
|
| -
|
| -void BrowserWindowGtk::ExitFullscreen() {
|
| - if (!IsFullscreen())
|
| - return; // Nothing to do.
|
| - is_fullscreen_ = false;
|
| -
|
| - // Work around a bug where if we try to unfullscreen, metacity immediately
|
| - // fullscreens us again. This is a little flickery and not necessary if
|
| - // there's a gnome-panel, but it's not easy to detect whether there's a
|
| - // panel or not.
|
| - bool unmaximize_before_unfullscreen = IsMaximized() &&
|
| - ui::GuessWindowManager() == ui::WM_METACITY;
|
| - if (unmaximize_before_unfullscreen)
|
| - UnMaximize();
|
| -
|
| - gtk_window_unfullscreen(window_);
|
| -
|
| - if (unmaximize_before_unfullscreen)
|
| - gtk_window_maximize(window_);
|
| -
|
| - browser_->WindowFullscreenStateChanged();
|
| - gtk_widget_show(titlebar_widget());
|
| - UpdateFullscreenExitBubbleContent(GURL(), FEB_TYPE_NONE);
|
| - UpdateCustomFrame();
|
| - ShowSupportedWindowFeatures();
|
| -}
|
| -
|
| -bool BrowserWindowGtk::ShouldHideUIForFullscreen() const {
|
| - return IsFullscreen();
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsFullscreen() const {
|
| - return is_fullscreen_;
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsFullscreenBubbleVisible() const {
|
| - return fullscreen_exit_bubble_ != NULL;
|
| -}
|
| -
|
| -LocationBar* BrowserWindowGtk::GetLocationBar() const {
|
| - return toolbar_->GetLocationBar();
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetFocusToLocationBar(bool select_all) {
|
| - if (!IsFullscreen())
|
| - GetLocationBar()->FocusLocation(select_all);
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateReloadStopState(bool is_loading, bool force) {
|
| - toolbar_->GetReloadButton()->ChangeMode(
|
| - is_loading ? ReloadButtonGtk::MODE_STOP : ReloadButtonGtk::MODE_RELOAD,
|
| - force);
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateToolbar(content::WebContents* contents) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::UpdateToolbar");
|
| - toolbar_->UpdateWebContents(contents);
|
| -}
|
| -
|
| -void BrowserWindowGtk::FocusToolbar() {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::FocusAppMenu() {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::FocusBookmarksToolbar() {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::FocusInfobars() {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::RotatePaneFocus(bool forwards) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsBookmarkBarVisible() const {
|
| - return browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR) &&
|
| - bookmark_bar_.get() &&
|
| - browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsBookmarkBarAnimating() const {
|
| - if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
|
| - return true;
|
| - return false;
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsTabStripEditable() const {
|
| - return !tabstrip()->IsDragSessionActive() &&
|
| - !tabstrip()->IsActiveDropTarget();
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsToolbarVisible() const {
|
| - return IsToolbarSupported();
|
| -}
|
| -
|
| -gfx::Rect BrowserWindowGtk::GetRootWindowResizerRect() const {
|
| - return gfx::Rect();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ConfirmAddSearchProvider(TemplateURL* template_url,
|
| - Profile* profile) {
|
| - new EditSearchEngineDialog(window_, template_url, NULL, profile);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowUpdateChromeDialog() {
|
| - UpdateRecommendedDialog::Show(window_);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowBookmarkBubble(const GURL& url,
|
| - bool already_bookmarked) {
|
| - toolbar_->GetLocationBarView()->ShowStarBubble(url, !already_bookmarked);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowBookmarkAppBubble(
|
| - const WebApplicationInfo& web_app_info,
|
| - const std::string& extension_id) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowTranslateBubble(content::WebContents* contents,
|
| - translate::TranslateStep step,
|
| - TranslateErrors::Type error_type) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -#if defined(ENABLE_ONE_CLICK_SIGNIN)
|
| -void BrowserWindowGtk::ShowOneClickSigninBubble(
|
| - OneClickSigninBubbleType type,
|
| - const base::string16& email,
|
| - const base::string16& error_message,
|
| - const StartSyncCallback& start_sync_callback) {
|
| -
|
| - new OneClickSigninBubbleGtk(this, type, email,
|
| - error_message, start_sync_callback);
|
| -}
|
| -#endif
|
| -
|
| -bool BrowserWindowGtk::IsDownloadShelfVisible() const {
|
| - return download_shelf_.get() && download_shelf_->IsShowing();
|
| -}
|
| -
|
| -DownloadShelf* BrowserWindowGtk::GetDownloadShelf() {
|
| - if (!download_shelf_.get())
|
| - download_shelf_.reset(new DownloadShelfGtk(browser_.get(),
|
| - render_area_vbox_));
|
| - return download_shelf_.get();
|
| -}
|
| -
|
| -void BrowserWindowGtk::UserChangedTheme() {
|
| - SetBackgroundColor();
|
| - InvalidateWindow();
|
| - UpdateWindowShape(bounds_.width(), bounds_.height());
|
| -}
|
| -
|
| -int BrowserWindowGtk::GetExtraRenderViewHeight() const {
|
| - int sum = infobar_container_->TotalHeightOfAnimatingBars();
|
| - if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
|
| - sum += bookmark_bar_->GetHeight();
|
| - if (download_shelf_.get() && download_shelf_->IsClosing())
|
| - sum += download_shelf_->GetHeight();
|
| - return sum;
|
| -}
|
| -
|
| -void BrowserWindowGtk::WebContentsFocused(WebContents* contents) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowWebsiteSettings(
|
| - Profile* profile,
|
| - content::WebContents* web_contents,
|
| - const GURL& url,
|
| - const content::SSLStatus& ssl) {
|
| - WebsiteSettingsPopupGtk::Show(GetNativeWindow(), profile, web_contents, url,
|
| - ssl);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowAppMenu() {
|
| - toolbar_->ShowAppMenu();
|
| -}
|
| -
|
| -bool BrowserWindowGtk::PreHandleKeyboardEvent(
|
| - const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
|
| - GdkEventKey* os_event = &event.os_event->key;
|
| -
|
| - if (!os_event || event.type != blink::WebInputEvent::RawKeyDown)
|
| - return false;
|
| -
|
| - if (ExtensionKeybindingRegistryGtk::shortcut_handling_suspended())
|
| - return false;
|
| -
|
| - // We first find out the browser command associated to the |event|.
|
| - // Then if the command is a reserved one, and should be processed immediately
|
| - // according to the |event|, the command will be executed immediately.
|
| - // Otherwise we just set |*is_keyboard_shortcut| properly and return false.
|
| -
|
| - // First check if it's a custom accelerator.
|
| - int id = GetCustomCommandId(os_event);
|
| -
|
| - // Then check if it's a predefined accelerator bound to the window.
|
| - if (id == -1) {
|
| - // This piece of code is based on the fact that calling
|
| - // gtk_window_activate_key() method against |window_| may only trigger a
|
| - // browser command execution, by matching a global accelerator
|
| - // defined in above |kAcceleratorMap|.
|
| - //
|
| - // Here we need to retrieve the command id (if any) associated to the
|
| - // keyboard event. Instead of looking up the command id in above
|
| - // |kAcceleratorMap| table by ourselves, we block the command execution of
|
| - // the |browser_| object then send the keyboard event to the |window_| by
|
| - // calling gtk_window_activate_key() method, as if we are activating an
|
| - // accelerator key. Then we can retrieve the command id from the
|
| - // |browser_| object.
|
| - //
|
| - // Pros of this approach:
|
| - // 1. We don't need to care about keyboard layout problem, as
|
| - // gtk_window_activate_key() method handles it for us.
|
| - //
|
| - // Cons:
|
| - // 1. The logic is a little complicated.
|
| - // 2. We should be careful not to introduce any accelerators that trigger
|
| - // customized code instead of browser commands.
|
| - bool original_block_command_state =
|
| - browser_->command_controller()->block_command_execution();
|
| - browser_->command_controller()->SetBlockCommandExecution(true);
|
| - gtk_window_activate_key(window_, os_event);
|
| - // We don't need to care about the WindowOpenDisposition value,
|
| - // because all commands executed in this path use the default value.
|
| - id = browser_->command_controller()->GetLastBlockedCommand(NULL);
|
| - browser_->command_controller()->SetBlockCommandExecution(
|
| - original_block_command_state);
|
| - }
|
| -
|
| - if (id == -1)
|
| - return false;
|
| -
|
| - // Executing the command may cause |this| object to be destroyed.
|
| - if (browser_->command_controller()->IsReservedCommandOrKey(id, event) &&
|
| - !event.match_edit_command) {
|
| - return chrome::ExecuteCommand(browser_.get(), id);
|
| - }
|
| -
|
| - // The |event| is a keyboard shortcut.
|
| - DCHECK(is_keyboard_shortcut != NULL);
|
| - *is_keyboard_shortcut = true;
|
| -
|
| - return false;
|
| -}
|
| -
|
| -void BrowserWindowGtk::HandleKeyboardEvent(
|
| - const NativeWebKeyboardEvent& event) {
|
| - GdkEventKey* os_event = &event.os_event->key;
|
| -
|
| - if (!os_event || event.type != blink::WebInputEvent::RawKeyDown)
|
| - return;
|
| -
|
| - // Handles a key event in following sequence:
|
| - // 1. Our special key accelerators, such as ctrl-tab, etc.
|
| - // 2. Gtk accelerators.
|
| - // This sequence matches the default key press handler of GtkWindow.
|
| - //
|
| - // It's not necessary to care about the keyboard layout, as
|
| - // gtk_window_activate_key() takes care of it automatically.
|
| - int id = GetCustomCommandId(os_event);
|
| - if (id != -1)
|
| - chrome::ExecuteCommand(browser_.get(), id);
|
| - else
|
| - gtk_window_activate_key(window_, os_event);
|
| -}
|
| -
|
| -void BrowserWindowGtk::Cut() {
|
| - gtk_window_util::DoCut(
|
| - window_, browser_->tab_strip_model()->GetActiveWebContents());
|
| -}
|
| -
|
| -void BrowserWindowGtk::Copy() {
|
| - gtk_window_util::DoCopy(
|
| - window_, browser_->tab_strip_model()->GetActiveWebContents());
|
| -}
|
| -
|
| -void BrowserWindowGtk::Paste() {
|
| - gtk_window_util::DoPaste(
|
| - window_, browser_->tab_strip_model()->GetActiveWebContents());
|
| -}
|
| -
|
| -WindowOpenDisposition BrowserWindowGtk::GetDispositionForPopupBounds(
|
| - const gfx::Rect& bounds) {
|
| - return NEW_POPUP;
|
| -}
|
| -
|
| -FindBar* BrowserWindowGtk::CreateFindBar() {
|
| - return new FindBarGtk(this);
|
| -}
|
| -
|
| -WebContentsModalDialogHost* BrowserWindowGtk::GetWebContentsModalDialogHost() {
|
| - return NULL;
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowAvatarBubble(WebContents* web_contents,
|
| - const gfx::Rect& rect) {
|
| - GtkWidget* widget = web_contents->GetView()->GetContentNativeView();
|
| - new AvatarMenuBubbleGtk(browser_.get(), widget, BubbleGtk::ANCHOR_TOP_RIGHT,
|
| - &rect);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode) {
|
| - if (titlebar_->avatar_button())
|
| - titlebar_->avatar_button()->ShowAvatarBubble();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowPasswordGenerationBubble(
|
| - const gfx::Rect& rect,
|
| - const autofill::PasswordForm& form,
|
| - autofill::PasswordGenerator* password_generator) {
|
| - WebContents* web_contents =
|
| - browser_->tab_strip_model()->GetActiveWebContents();
|
| - if (!web_contents || !web_contents->GetView()->GetContentNativeView()) {
|
| - return;
|
| - }
|
| -
|
| - new PasswordGenerationBubbleGtk(rect, form, web_contents, password_generator);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads(
|
| - int download_count,
|
| - Browser::DownloadClosePreventionType dialog_type,
|
| - bool app_modal,
|
| - const base::Callback<void(bool)>& callback) {
|
| - DownloadInProgressDialogGtk::Show(
|
| - GetNativeWindow(), download_count, dialog_type, app_modal, callback);
|
| -}
|
| -
|
| -int
|
| -BrowserWindowGtk::GetRenderViewHeightInsetWithDetachedBookmarkBar() {
|
| - if (!bookmark_bar_.get() ||
|
| - browser_->bookmark_bar_state() != BookmarkBar::DETACHED) {
|
| - return 0;
|
| - }
|
| - return bookmark_bar_->max_height();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ExecuteExtensionCommand(
|
| - const extensions::Extension* extension,
|
| - const extensions::Command& command) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowPageActionPopup(
|
| - const extensions::Extension* extension) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowBrowserActionPopup(
|
| - const extensions::Extension* extension) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void BrowserWindowGtk::Observe(int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, type);
|
| - // The profile avatar icon may have changed.
|
| - gtk_util::SetWindowIcon(window_, browser_->profile());
|
| -}
|
| -
|
| -void BrowserWindowGtk::TabDetachedAt(WebContents* contents, int index) {
|
| - // We use index here rather than comparing |contents| because by this time
|
| - // the model has already removed |contents| from its list, so
|
| - // browser_->tab_strip_model()->GetActiveWebContents() will return NULL or
|
| - // something else.
|
| - if (index == browser_->tab_strip_model()->active_index()) {
|
| - infobar_container_->ChangeInfoBarManager(NULL);
|
| - UpdateDevToolsForContents(NULL);
|
| - }
|
| - contents_container_->DetachTab(contents);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
|
| - // Do nothing if we're in the process of closing the browser window.
|
| - if (!window_)
|
| - return;
|
| -
|
| - bool is_active = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window;
|
| - bool changed = (is_active != is_active_);
|
| -
|
| - if (is_active && changed) {
|
| - // If there's an app modal dialog (e.g., JS alert), try to redirect
|
| - // the user's attention to the window owning the dialog.
|
| - if (AppModalDialogQueue::GetInstance()->HasActiveDialog()) {
|
| - AppModalDialogQueue::GetInstance()->ActivateModalDialog();
|
| - return;
|
| - }
|
| - }
|
| -
|
| - is_active_ = is_active;
|
| - if (changed) {
|
| - SetBackgroundColor();
|
| - InvalidateWindow();
|
| - // For some reason, the above two calls cause the window shape to be
|
| - // lost so reset it.
|
| - UpdateWindowShape(bounds_.width(), bounds_.height());
|
| - }
|
| -}
|
| -
|
| -SkColor BrowserWindowGtk::GetInfoBarSeparatorColor() const {
|
| - GtkThemeService* theme_service = GtkThemeService::GetFrom(
|
| - browser()->profile());
|
| - return gfx::GdkColorToSkColor(theme_service->GetBorderColor());
|
| -}
|
| -
|
| -void BrowserWindowGtk::InfoBarContainerStateChanged(bool is_animating) {
|
| - InvalidateInfoBarBits();
|
| -}
|
| -
|
| -bool BrowserWindowGtk::DrawInfoBarArrows(int* x) const {
|
| - if (x) {
|
| - // This is a views specific call that made its way into the interface. We
|
| - // go through GetXPositionOfLocationIcon() since we need widget relativity.
|
| - *x = 0;
|
| - NOTREACHED();
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -extensions::ActiveTabPermissionGranter*
|
| - BrowserWindowGtk::GetActiveTabPermissionGranter() {
|
| - WebContents* tab = GetDisplayedTab();
|
| - if (!tab)
|
| - return NULL;
|
| - return extensions::TabHelper::FromWebContents(tab)->
|
| - active_tab_permission_granter();
|
| -}
|
| -
|
| -void BrowserWindowGtk::DestroyBrowser() {
|
| - browser_.reset();
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnConfigure(GtkWidget* widget,
|
| - GdkEventConfigure* event) {
|
| - gfx::Rect bounds(event->x, event->y, event->width, event->height);
|
| -
|
| - // When the window moves, we'll get multiple configure-event signals. We can
|
| - // also get events when the bounds haven't changed, but the window's stacking
|
| - // has, which we aren't interested in. http://crbug.com/70125
|
| - if (bounds == configure_bounds_)
|
| - return FALSE;
|
| -
|
| - GetLocationBar()->GetOmniboxView()->CloseOmniboxPopup();
|
| -
|
| - WebContents* tab = GetDisplayedTab();
|
| - if (tab)
|
| - tab->GetRenderViewHost()->NotifyMoveOrResizeStarted();
|
| -
|
| - if (bounds_.size() != bounds.size())
|
| - UpdateWindowShape(bounds.width(), bounds.height());
|
| -
|
| - // We update |bounds_| but not |restored_bounds_| here. The latter needs
|
| - // to be updated conditionally when the window is non-maximized and non-
|
| - // fullscreen, but whether those state updates have been processed yet is
|
| - // window-manager specific. We update |restored_bounds_| in the debounced
|
| - // handler below, after the window state has been updated.
|
| - bounds_ = bounds;
|
| - configure_bounds_ = bounds;
|
| -
|
| - // The GdkEventConfigure* we get here doesn't have quite the right
|
| - // coordinates though (they're relative to the drawable window area, rather
|
| - // than any window manager decorations, if enabled), so we need to call
|
| - // gtk_window_get_position() to get the right values. (Otherwise session
|
| - // restore, if enabled, will restore windows to incorrect positions.) That's
|
| - // a round trip to the X server though, so we set a debounce timer and only
|
| - // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a
|
| - // reconfigure event in a short while.
|
| - // We don't use Reset() because the timer may not yet be running.
|
| - // (In that case Stop() is a no-op.)
|
| - window_configure_debounce_timer_.Stop();
|
| - window_configure_debounce_timer_.Start(FROM_HERE,
|
| - base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), this,
|
| - &BrowserWindowGtk::OnDebouncedBoundsChanged);
|
| -
|
| - return FALSE;
|
| -}
|
| -
|
| -void BrowserWindowGtk::OnDebouncedBoundsChanged() {
|
| - gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_);
|
| - SaveWindowPosition();
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnWindowState(GtkWidget* sender,
|
| - GdkEventWindowState* event) {
|
| - state_ = event->new_window_state;
|
| -
|
| - if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
|
| - content::NotificationService::current()->Notify(
|
| - chrome::NOTIFICATION_BROWSER_WINDOW_MAXIMIZED,
|
| - content::Source<BrowserWindow>(this),
|
| - content::NotificationService::NoDetails());
|
| - }
|
| -
|
| - titlebar_->UpdateCustomFrame(UseCustomFrame() && !IsFullscreen());
|
| - UpdateWindowShape(bounds_.width(), bounds_.height());
|
| - SaveWindowPosition();
|
| - return FALSE;
|
| -}
|
| -
|
| -// Callback for the delete event. This event is fired when the user tries to
|
| -// close the window (e.g., clicking on the X in the window manager title bar).
|
| -gboolean BrowserWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget,
|
| - GdkEvent* event) {
|
| - Close();
|
| -
|
| - // Return true to prevent the gtk window from being destroyed. Close will
|
| - // destroy it for us.
|
| - return TRUE;
|
| -}
|
| -
|
| -void BrowserWindowGtk::OnMainWindowDestroy(GtkWidget* widget) {
|
| - // Make sure we destroy this object while the main window is still valid.
|
| - extension_keybinding_registry_.reset();
|
| -
|
| - // BUG 8712. When we gtk_widget_destroy() in Close(), this will emit the
|
| - // signal right away, and we will be here (while Close() is still in the
|
| - // call stack). In order to not reenter Close(), and to also follow the
|
| - // expectations of BrowserList, we should run the BrowserWindowGtk destructor
|
| - // not now, but after the run loop goes back to process messages. Otherwise
|
| - // we will remove ourself from BrowserList while it's being iterated.
|
| - // Additionally, now that we know the window is gone, we need to make sure to
|
| - // set window_ to NULL, otherwise we will try to close the window again when
|
| - // we call Close() in the destructor.
|
| - //
|
| - // We don't want to use DeleteSoon() here since it won't work on a nested pump
|
| - // (like in UI tests).
|
| - base::MessageLoop::current()->PostTask(
|
| - FROM_HERE, base::Bind(&base::DeletePointer<BrowserWindowGtk>, this));
|
| -}
|
| -
|
| -void BrowserWindowGtk::UnMaximize() {
|
| - gtk_window_util::UnMaximize(window_, bounds_, restored_bounds_);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::CanClose() const {
|
| - // You cannot close a frame for which there is an active originating drag
|
| - // session.
|
| - if (tabstrip_->IsDragSessionActive())
|
| - return false;
|
| -
|
| - // Give beforeunload handlers the chance to cancel the close before we hide
|
| - // the window below.
|
| - if (!browser_->ShouldCloseWindow())
|
| - return false;
|
| -
|
| - bool fast_tab_closing_enabled =
|
| - CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableFastUnload);
|
| -
|
| - if (!browser_->tab_strip_model()->empty()) {
|
| - // Tab strip isn't empty. Hide the window (so it appears to have closed
|
| - // immediately) and close all the tabs, allowing the renderers to shut
|
| - // down. When the tab strip is empty we'll be called back again.
|
| - gtk_widget_hide(GTK_WIDGET(window_));
|
| - browser_->OnWindowClosing();
|
| -
|
| - if (fast_tab_closing_enabled)
|
| - browser_->tab_strip_model()->CloseAllTabs();
|
| - return false;
|
| - } else if (fast_tab_closing_enabled &&
|
| - !browser_->HasCompletedUnloadProcessing()) {
|
| - // The browser needs to finish running unload handlers.
|
| - // Hide the window (so it appears to have closed immediately), and
|
| - // the browser will call us back again when it is ready to close.
|
| - gtk_widget_hide(GTK_WIDGET(window_));
|
| - return false;
|
| - }
|
| -
|
| - // Empty TabStripModel, it's now safe to allow the Window to be closed.
|
| - content::NotificationService::current()->Notify(
|
| - chrome::NOTIFICATION_WINDOW_CLOSED,
|
| - content::Source<GtkWindow>(window_),
|
| - content::NotificationService::NoDetails());
|
| - return true;
|
| -}
|
| -
|
| -bool BrowserWindowGtk::ShouldShowWindowIcon() const {
|
| - return browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR);
|
| -}
|
| -
|
| -void BrowserWindowGtk::AddFindBar(FindBarGtk* findbar) {
|
| - gtk_floating_container_add_floating(
|
| - GTK_FLOATING_CONTAINER(render_area_floating_container_),
|
| - findbar->widget());
|
| -}
|
| -
|
| -void BrowserWindowGtk::ResetCustomFrameCursor() {
|
| - if (!frame_cursor_)
|
| - return;
|
| -
|
| - frame_cursor_ = NULL;
|
| - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(window_)), NULL);
|
| -}
|
| -
|
| -// static
|
| -BrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow(
|
| - gfx::NativeWindow window) {
|
| - if (window) {
|
| - return static_cast<BrowserWindowGtk*>(
|
| - g_object_get_qdata(G_OBJECT(window), GetBrowserWindowQuarkKey()));
|
| - }
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -// static
|
| -GtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) {
|
| - GtkWindow* window = ui::GetGtkWindowFromX11Window(xid);
|
| - // Use GetBrowserWindowForNativeWindow() to verify the GtkWindow we found
|
| - // is actually a browser window (and not e.g. a dialog).
|
| - if (!GetBrowserWindowForNativeWindow(window))
|
| - return NULL;
|
| - return window;
|
| -}
|
| -
|
| -GtkWidget* BrowserWindowGtk::titlebar_widget() const {
|
| - return titlebar_->widget();
|
| -}
|
| -
|
| -// static
|
| -void BrowserWindowGtk::RegisterProfilePrefs(
|
| - user_prefs::PrefRegistrySyncable* registry) {
|
| - bool custom_frame_default = false;
|
| - // Avoid checking the window manager if we're not connected to an X server (as
|
| - // is the case in Valgrind tests).
|
| - if (ui::XDisplayExists())
|
| - custom_frame_default = ui::GetCustomFramePrefDefault();
|
| -
|
| - registry->RegisterBooleanPref(
|
| - prefs::kUseCustomChromeFrame,
|
| - custom_frame_default,
|
| - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
|
| -}
|
| -
|
| -WebContents* BrowserWindowGtk::GetDisplayedTab() {
|
| - return contents_container_->tab();
|
| -}
|
| -
|
| -void BrowserWindowGtk::QueueToolbarRedraw() {
|
| - gtk_widget_queue_draw(toolbar_->widget());
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetGeometryHints() {
|
| - // If we call gtk_window_maximize followed by gtk_window_present, compiz gets
|
| - // confused and maximizes the window, but doesn't set the
|
| - // GDK_WINDOW_STATE_MAXIMIZED bit. So instead, we keep track of whether to
|
| - // maximize and call it after gtk_window_present.
|
| - gfx::Rect bounds;
|
| - chrome::GetSavedWindowBoundsAndShowState(browser_.get(),
|
| - &bounds,
|
| - &show_state_after_show_);
|
| - // We don't blindly call SetBounds here: that sets a forced position
|
| - // on the window and we intentionally *don't* do that for normal
|
| - // windows. Most programs do not restore their window position on
|
| - // Linux, instead letting the window manager choose a position.
|
| - //
|
| - // However, in cases like dropping a tab where the bounds are
|
| - // specifically set, we do want to position explicitly. We also
|
| - // force the position as part of session restore, as applications
|
| - // that restore other, similar state (for instance GIMP, audacity,
|
| - // pidgin, dia, and gkrellm) do tend to restore their positions.
|
| - //
|
| - // For popup windows, we assume that if x == y == 0, the opening page
|
| - // did not specify a position. Let the WM position the popup instead.
|
| - bool is_popup = browser_->is_type_popup();
|
| - bool popup_without_position = is_popup &&
|
| - bounds.x() == 0 && bounds.y() == 0;
|
| - bool move = browser_->bounds_overridden() && !popup_without_position;
|
| - SetBoundsImpl(bounds, !is_popup, move);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ConnectHandlersToSignals() {
|
| - g_signal_connect(window_, "delete-event",
|
| - G_CALLBACK(OnMainWindowDeleteEventThunk), this);
|
| - g_signal_connect(window_, "destroy",
|
| - G_CALLBACK(OnMainWindowDestroyThunk), this);
|
| - g_signal_connect(window_, "configure-event",
|
| - G_CALLBACK(OnConfigureThunk), this);
|
| - g_signal_connect(window_, "window-state-event",
|
| - G_CALLBACK(OnWindowStateThunk), this);
|
| - g_signal_connect(window_, "key-press-event",
|
| - G_CALLBACK(OnKeyPressThunk), this);
|
| - g_signal_connect(window_, "motion-notify-event",
|
| - G_CALLBACK(OnMouseMoveEventThunk), this);
|
| - g_signal_connect(window_, "button-press-event",
|
| - G_CALLBACK(OnButtonPressEventThunk), this);
|
| - g_signal_connect(window_, "focus-in-event",
|
| - G_CALLBACK(OnFocusInThunk), this);
|
| - g_signal_connect(window_, "focus-out-event",
|
| - G_CALLBACK(OnFocusOutThunk), this);
|
| -}
|
| -
|
| -void BrowserWindowGtk::InitWidgets() {
|
| - ConnectHandlersToSignals();
|
| -
|
| - bounds_ = configure_bounds_ = restored_bounds_ =
|
| - GetInitialWindowBounds(window_);
|
| -
|
| - // This vbox encompasses all of the widgets within the browser. This is
|
| - // everything except the custom frame border.
|
| - window_vbox_ = gtk_vbox_new(FALSE, 0);
|
| - gtk_widget_show(window_vbox_);
|
| -
|
| - // We hold an always hidden GtkMenuBar inside our browser window simply to
|
| - // fool the Unity desktop, which will mirror the contents of the first
|
| - // GtkMenuBar it sees into the global menu bar. (It doesn't seem to check the
|
| - // visibility of the GtkMenuBar, so we can just permanently hide it.)
|
| - global_menu_bar_.reset(new GlobalMenuBar(browser_.get()));
|
| - gtk_container_add(GTK_CONTAINER(window_vbox_), global_menu_bar_->widget());
|
| -
|
| - // The window container draws the custom browser frame.
|
| - window_container_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
|
| - gtk_widget_set_name(window_container_, "chrome-custom-frame-border");
|
| - gtk_widget_set_app_paintable(window_container_, TRUE);
|
| - gtk_widget_set_double_buffered(window_container_, FALSE);
|
| - gtk_widget_set_redraw_on_allocate(window_container_, TRUE);
|
| - g_signal_connect(window_container_, "expose-event",
|
| - G_CALLBACK(OnCustomFrameExposeThunk), this);
|
| - gtk_container_add(GTK_CONTAINER(window_container_), window_vbox_);
|
| -
|
| - tabstrip_.reset(new TabStripGtk(browser_->tab_strip_model(), this));
|
| - tabstrip_->Init();
|
| -
|
| - // Build the titlebar (tabstrip + header space + min/max/close buttons).
|
| - titlebar_.reset(new BrowserTitlebar(this, window_));
|
| - titlebar_->Init();
|
| -
|
| - // Insert the tabstrip into the window.
|
| - gtk_box_pack_start(GTK_BOX(window_vbox_), titlebar_->widget(), FALSE, FALSE,
|
| - 0);
|
| -
|
| - toolbar_.reset(new BrowserToolbarGtk(browser_.get(), this));
|
| - toolbar_->Init(window_);
|
| - gtk_box_pack_start(GTK_BOX(window_vbox_), toolbar_->widget(),
|
| - FALSE, FALSE, 0);
|
| - g_signal_connect_after(toolbar_->widget(), "expose-event",
|
| - G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
|
| - // This vbox surrounds the render area: find bar, info bars and render view.
|
| - // The reason is that this area as a whole needs to be grouped in its own
|
| - // GdkWindow hierarchy so that animations originating inside it (infobar,
|
| - // download shelf, find bar) are all clipped to that area. This is why
|
| - // |render_area_vbox_| is packed in |render_area_event_box_|.
|
| - render_area_vbox_ = gtk_vbox_new(FALSE, 0);
|
| - gtk_widget_set_name(render_area_vbox_, "chrome-render-area-vbox");
|
| - render_area_floating_container_ = gtk_floating_container_new();
|
| - gtk_container_add(GTK_CONTAINER(render_area_floating_container_),
|
| - render_area_vbox_);
|
| -
|
| - GtkWidget* location_icon = toolbar_->GetLocationBarView()->
|
| - location_icon_widget();
|
| - g_signal_connect(location_icon, "size-allocate",
|
| - G_CALLBACK(OnLocationIconSizeAllocateThunk), this);
|
| - g_signal_connect_after(location_icon, "expose-event",
|
| - G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
|
| -
|
| - toolbar_border_ = gtk_event_box_new();
|
| - gtk_box_pack_start(GTK_BOX(render_area_vbox_),
|
| - toolbar_border_, FALSE, FALSE, 0);
|
| - gtk_widget_set_size_request(toolbar_border_, -1, 1);
|
| - gtk_widget_set_no_show_all(toolbar_border_, TRUE);
|
| - g_signal_connect_after(toolbar_border_, "expose-event",
|
| - G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
|
| -
|
| - if (IsToolbarSupported())
|
| - gtk_widget_show(toolbar_border_);
|
| -
|
| - infobar_container_.reset(
|
| - new InfoBarContainerGtk(this, browser_->profile()));
|
| - gtk_box_pack_start(GTK_BOX(render_area_vbox_),
|
| - infobar_container_->widget(),
|
| - FALSE, FALSE, 0);
|
| -
|
| - status_bubble_.reset(new StatusBubbleGtk(browser_->profile()));
|
| -
|
| - contents_container_.reset(new TabContentsContainerGtk(
|
| - status_bubble_.get(),
|
| - implicit_cast<content::WebContentsDelegate*>(browser_.get())->
|
| - EmbedsFullscreenWidget()));
|
| - devtools_container_.reset(new TabContentsContainerGtk(NULL, false));
|
| - // DevTools container should only have DevTools-specific view ID.
|
| - ViewIDUtil::SetDelegateForWidget(devtools_container_->widget(), NULL);
|
| - ViewIDUtil::SetID(devtools_container_->widget(), VIEW_ID_DEV_TOOLS_DOCKED);
|
| -
|
| - devtools_floating_container_ = gtk_floating_container_new();
|
| - gtk_container_add(GTK_CONTAINER(devtools_floating_container_),
|
| - devtools_container_->widget());
|
| - gtk_floating_container_add_floating(
|
| - GTK_FLOATING_CONTAINER(devtools_floating_container_),
|
| - contents_container_->widget());
|
| - g_signal_connect(devtools_floating_container_, "set-floating-position",
|
| - G_CALLBACK(OnDevToolsContainerSetFloatingPosition), this);
|
| - gtk_box_pack_end(GTK_BOX(render_area_vbox_),
|
| - devtools_floating_container_, TRUE, TRUE, 0);
|
| -
|
| - gtk_widget_show_all(render_area_floating_container_);
|
| -
|
| - render_area_event_box_ = gtk_event_box_new();
|
| - // Set a white background so during startup the user sees white in the
|
| - // content area before we get a WebContents in place.
|
| - gtk_widget_modify_bg(render_area_event_box_, GTK_STATE_NORMAL,
|
| - &ui::kGdkWhite);
|
| - gtk_container_add(GTK_CONTAINER(render_area_event_box_),
|
| - render_area_floating_container_);
|
| - gtk_widget_show(render_area_event_box_);
|
| - gtk_box_pack_end(GTK_BOX(window_vbox_), render_area_event_box_,
|
| - TRUE, TRUE, 0);
|
| -
|
| - if (IsBookmarkBarSupported()) {
|
| - bookmark_bar_.reset(new BookmarkBarGtk(this,
|
| - browser_.get(),
|
| - tabstrip_.get()));
|
| - PlaceBookmarkBar(false);
|
| - gtk_widget_show(bookmark_bar_->widget());
|
| -
|
| - g_signal_connect_after(bookmark_bar_->widget(), "expose-event",
|
| - G_CALLBACK(OnBookmarkBarExposeThunk), this);
|
| - g_signal_connect(bookmark_bar_->widget(), "size-allocate",
|
| - G_CALLBACK(OnBookmarkBarSizeAllocateThunk), this);
|
| - }
|
| -
|
| - // We have to realize the window before we try to apply a window shape mask.
|
| - gtk_widget_realize(GTK_WIDGET(window_));
|
| - state_ = gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(window_)));
|
| - // Note that calling this the first time is necessary to get the
|
| - // proper control layout.
|
| - UpdateCustomFrame();
|
| -
|
| - // Add the keybinding registry, now that the window has been realized.
|
| - extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
|
| - browser_->profile(),
|
| - window_,
|
| - extensions::ExtensionKeybindingRegistry::ALL_EXTENSIONS,
|
| - this));
|
| -
|
| - // We have to call this after the first window is created, but after that only
|
| - // when the theme changes. This sets the icon that will be used for windows
|
| - // that have not explicitly been assigned an icon.
|
| - static bool default_icon_set = false;
|
| - if (!default_icon_set) {
|
| - gtk_util::SetDefaultWindowIcon(window_);
|
| - default_icon_set = true;
|
| - }
|
| - // Set this window's (potentially profile-avatar-emblemed) icon, overriding
|
| - // the default.
|
| - gtk_util::SetWindowIcon(window_, browser_->profile());
|
| -
|
| - gtk_container_add(GTK_CONTAINER(window_), window_container_);
|
| - gtk_widget_show(window_container_);
|
| - browser_->tab_strip_model()->AddObserver(this);
|
| -}
|
| -
|
| -void BrowserWindowGtk::SetBackgroundColor() {
|
| - Profile* profile = browser()->profile();
|
| - GtkThemeService* theme_provider = GtkThemeService::GetFrom(profile);
|
| - int frame_color_id;
|
| - if (UsingCustomPopupFrame()) {
|
| - frame_color_id = ThemeProperties::COLOR_TOOLBAR;
|
| - } else if (DrawFrameAsActive()) {
|
| - frame_color_id = browser()->profile()->IsOffTheRecord()
|
| - ? ThemeProperties::COLOR_FRAME_INCOGNITO
|
| - : ThemeProperties::COLOR_FRAME;
|
| - } else {
|
| - frame_color_id = browser()->profile()->IsOffTheRecord()
|
| - ? ThemeProperties::COLOR_FRAME_INCOGNITO_INACTIVE
|
| - : ThemeProperties::COLOR_FRAME_INACTIVE;
|
| - }
|
| -
|
| - SkColor frame_color = theme_provider->GetColor(frame_color_id);
|
| -
|
| - // Paint the frame color on the left, right and bottom.
|
| - GdkColor frame_color_gdk = gfx::SkColorToGdkColor(frame_color);
|
| - gtk_widget_modify_bg(GTK_WIDGET(window_), GTK_STATE_NORMAL,
|
| - &frame_color_gdk);
|
| -
|
| - GdkColor border_color = theme_provider->GetBorderColor();
|
| - gtk_widget_modify_bg(toolbar_border_, GTK_STATE_NORMAL, &border_color);
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateWindowShape(int width, int height) {
|
| - using gtk_window_util::kFrameBorderThickness;
|
| - GdkRegion* mask = GetWindowShape(width, height);
|
| - gdk_window_shape_combine_region(
|
| - gtk_widget_get_window(GTK_WIDGET(window_)), mask, 0, 0);
|
| - if (mask)
|
| - gdk_region_destroy(mask);
|
| -
|
| - if (UseCustomFrame() && !IsFullscreen() && !IsMaximized()) {
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 1,
|
| - kFrameBorderThickness, kFrameBorderThickness, kFrameBorderThickness);
|
| - } else {
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 0, 0, 0, 0);
|
| - }
|
| -}
|
| -
|
| -GdkRegion* BrowserWindowGtk::GetWindowShape(int width, int height) const {
|
| - if (UseCustomFrame() && !IsFullscreen() && !IsMaximized()) {
|
| - // Make the corners rounded. We set a mask that includes most of the
|
| - // window except for a few pixels in each corner.
|
| - GdkRectangle top_top_rect = { 3, 0, width - 6, 1 };
|
| - GdkRectangle top_mid_rect = { 1, 1, width - 2, 2 };
|
| - GdkRectangle mid_rect = { 0, 3, width, height - 6 };
|
| - // The bottom two rects are mirror images of the top two rects.
|
| - GdkRectangle bot_mid_rect = top_mid_rect;
|
| - bot_mid_rect.y = height - 3;
|
| - GdkRectangle bot_bot_rect = top_top_rect;
|
| - bot_bot_rect.y = height - 1;
|
| - GdkRegion* mask = gdk_region_rectangle(&top_top_rect);
|
| - gdk_region_union_with_rect(mask, &top_mid_rect);
|
| - gdk_region_union_with_rect(mask, &mid_rect);
|
| - gdk_region_union_with_rect(mask, &bot_mid_rect);
|
| - gdk_region_union_with_rect(mask, &bot_bot_rect);
|
| - return mask;
|
| - } else if (UseCustomFrame()) {
|
| - // Disable rounded corners. Simply passing in a NULL region doesn't
|
| - // seem to work on KWin, so manually set the shape to the whole window.
|
| - GdkRectangle rect = { 0, 0, width, height };
|
| - GdkRegion* mask = gdk_region_rectangle(&rect);
|
| - return mask;
|
| - } else {
|
| - // XFCE disables the system decorations if there's an xshape set. Do not
|
| - // use the KWin hack when the custom frame is not enabled.
|
| - return NULL;
|
| - }
|
| -}
|
| -
|
| -void BrowserWindowGtk::ConnectAccelerators() {
|
| - accel_group_ = gtk_accel_group_new();
|
| - gtk_window_add_accel_group(window_, accel_group_);
|
| -
|
| - AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
|
| - for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
|
| - iter != accelerators->end(); ++iter) {
|
| - gtk_accel_group_connect(
|
| - accel_group_,
|
| - ui::GetGdkKeyCodeForAccelerator(iter->second),
|
| - ui::GetGdkModifierForAccelerator(iter->second),
|
| - GtkAccelFlags(0),
|
| - g_cclosure_new(G_CALLBACK(OnGtkAccelerator),
|
| - GINT_TO_POINTER(iter->first), NULL));
|
| - }
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateCustomFrame() {
|
| - gtk_window_set_decorated(window_, !UseCustomFrame());
|
| - titlebar_->UpdateCustomFrame(UseCustomFrame() && !IsFullscreen());
|
| - UpdateWindowShape(bounds_.width(), bounds_.height());
|
| -}
|
| -
|
| -void BrowserWindowGtk::InvalidateWindow() {
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(GTK_WIDGET(window_), &allocation);
|
| - gdk_window_invalidate_rect(gtk_widget_get_window(GTK_WIDGET(window_)),
|
| - &allocation, TRUE);
|
| -}
|
| -
|
| -void BrowserWindowGtk::SaveWindowPosition() {
|
| - // Browser::SaveWindowPlacement is used for session restore.
|
| - ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL;
|
| - if (IsMaximized())
|
| - show_state = ui::SHOW_STATE_MAXIMIZED;
|
| - else if (IsMinimized())
|
| - show_state = ui::SHOW_STATE_MINIMIZED;
|
| -
|
| - if (chrome::ShouldSaveWindowPlacement(browser_.get()))
|
| - chrome::SaveWindowPlacement(browser_.get(), restored_bounds_, show_state);
|
| -
|
| - // We also need to save the placement for startup.
|
| - // This is a web of calls between views and delegates on Windows, but the
|
| - // crux of the logic follows. See also cocoa/browser_window_controller.mm.
|
| - if (!browser_->profile()->GetPrefs())
|
| - return;
|
| -
|
| - std::string window_name = chrome::GetWindowPlacementKey(browser_.get());
|
| - DictionaryPrefUpdate update(browser_->profile()->GetPrefs(),
|
| - window_name.c_str());
|
| - base::DictionaryValue* window_preferences = update.Get();
|
| - // Note that we store left/top for consistency with Windows, but that we
|
| - // *don't* obey them; we only use them for computing width/height. See
|
| - // comments in SetGeometryHints().
|
| - window_preferences->SetInteger("left", restored_bounds_.x());
|
| - window_preferences->SetInteger("top", restored_bounds_.y());
|
| - window_preferences->SetInteger("right", restored_bounds_.right());
|
| - window_preferences->SetInteger("bottom", restored_bounds_.bottom());
|
| - window_preferences->SetBoolean("maximized", IsMaximized());
|
| -
|
| - gfx::Rect work_area(gfx::Screen::GetNativeScreen()->GetDisplayMatching(
|
| - restored_bounds_).work_area());
|
| - window_preferences->SetInteger("work_area_left", work_area.x());
|
| - window_preferences->SetInteger("work_area_top", work_area.y());
|
| - window_preferences->SetInteger("work_area_right", work_area.right());
|
| - window_preferences->SetInteger("work_area_bottom", work_area.bottom());
|
| -}
|
| -
|
| -void BrowserWindowGtk::InvalidateInfoBarBits() {
|
| - gtk_widget_queue_draw(toolbar_border_);
|
| - gtk_widget_queue_draw(toolbar_->widget());
|
| - if (bookmark_bar_.get() &&
|
| - browser_->bookmark_bar_state() != BookmarkBar::DETACHED) {
|
| - gtk_widget_queue_draw(bookmark_bar_->widget());
|
| - }
|
| -}
|
| -
|
| -int BrowserWindowGtk::GetXPositionOfLocationIcon(GtkWidget* relative_to) {
|
| - GtkWidget* location_icon = toolbar_->GetLocationBarView()->
|
| - location_icon_widget();
|
| -
|
| - GtkAllocation location_icon_allocation;
|
| - gtk_widget_get_allocation(location_icon, &location_icon_allocation);
|
| -
|
| - int x = 0;
|
| - gtk_widget_translate_coordinates(
|
| - location_icon, relative_to,
|
| - (location_icon_allocation.width + 1) / 2,
|
| - 0, &x, NULL);
|
| -
|
| - if (!gtk_widget_get_has_window(relative_to)) {
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(relative_to, &allocation);
|
| - x += allocation.x;
|
| - }
|
| -
|
| - return x;
|
| -}
|
| -
|
| -void BrowserWindowGtk::MaybeShowBookmarkBar(bool animate) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::MaybeShowBookmarkBar");
|
| - if (!IsBookmarkBarSupported())
|
| - return;
|
| -
|
| - if (GetDisplayedTab())
|
| - bookmark_bar_->SetPageNavigator(browser_.get());
|
| -
|
| - BookmarkBar::State state = browser_->bookmark_bar_state();
|
| - toolbar_->UpdateForBookmarkBarVisibility(state == BookmarkBar::DETACHED);
|
| - PlaceBookmarkBar(state == BookmarkBar::DETACHED);
|
| - bookmark_bar_->SetBookmarkBarState(
|
| - state,
|
| - animate ? BookmarkBar::ANIMATE_STATE_CHANGE :
|
| - BookmarkBar::DONT_ANIMATE_STATE_CHANGE);
|
| -}
|
| -
|
| -void BrowserWindowGtk::OnLocationIconSizeAllocate(GtkWidget* sender,
|
| - GtkAllocation* allocation) {
|
| - // The position of the arrow may have changed, so we'll have to redraw it.
|
| - InvalidateInfoBarBits();
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnExposeDrawInfobarBits(GtkWidget* sender,
|
| - GdkEventExpose* expose) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::OnExposeDrawInfobarBits");
|
| - // Maybe draw infobars
|
| - infobar_container_->PaintInfobarBitsOn(sender, expose, NULL);
|
| -
|
| - return FALSE;
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnBookmarkBarExpose(GtkWidget* sender,
|
| - GdkEventExpose* expose) {
|
| - if (browser_->bookmark_bar_state() == BookmarkBar::DETACHED)
|
| - return FALSE;
|
| -
|
| - return OnExposeDrawInfobarBits(sender, expose);
|
| -}
|
| -
|
| -void BrowserWindowGtk::OnBookmarkBarSizeAllocate(GtkWidget* sender,
|
| - GtkAllocation* allocation) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::OnBookmarkBarSizeAllocate");
|
| - // The size of the bookmark bar affects how the infobar arrow is drawn on
|
| - // the toolbar.
|
| - if (infobar_container_->ContainsInfobars())
|
| - InvalidateInfoBarBits();
|
| -
|
| - // Pass the new size to our infobar container.
|
| - int arrow_size = InfoBar::kDefaultArrowTargetHeight;
|
| - if (browser_->bookmark_bar_state() != BookmarkBar::DETACHED)
|
| - arrow_size += allocation->height;
|
| - infobar_container_->SetMaxTopArrowHeight(arrow_size);
|
| -}
|
| -
|
| -// static
|
| -gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
|
| - GObject* acceleratable,
|
| - guint keyval,
|
| - GdkModifierType modifier,
|
| - void* user_data) {
|
| - int command_id = GPOINTER_TO_INT(user_data);
|
| - BrowserWindowGtk* browser_window =
|
| - GetBrowserWindowForNativeWindow(GTK_WINDOW(acceleratable));
|
| - DCHECK(browser_window != NULL);
|
| - return chrome::ExecuteCommand(browser_window->browser(), command_id);
|
| -}
|
| -
|
| -// Let the focused widget have first crack at the key event so we don't
|
| -// override their accelerators, except if there is a priority keybinding
|
| -// handler registered (it should take precedence).
|
| -gboolean BrowserWindowGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
|
| - if (extension_keybinding_registry_->HasPriorityHandler(event))
|
| - return FALSE;
|
| -
|
| - // If a widget besides the native view is focused, we have to try to handle
|
| - // the custom accelerators before letting it handle them.
|
| - WebContents* current_web_contents =
|
| - browser()->tab_strip_model()->GetActiveWebContents();
|
| - // The current tab might not have a render view if it crashed.
|
| - if (!current_web_contents ||
|
| - !current_web_contents->GetView()->GetContentNativeView() ||
|
| - !gtk_widget_is_focus(
|
| - current_web_contents->GetView()->GetContentNativeView())) {
|
| - int command_id = GetCustomCommandId(event);
|
| - if (command_id == -1)
|
| - command_id = GetPreHandleCommandId(event);
|
| -
|
| - if (command_id != -1 && chrome::ExecuteCommand(browser_.get(), command_id))
|
| - return TRUE;
|
| -
|
| - // Propagate the key event to child widget first, so we don't override their
|
| - // accelerators.
|
| - if (!gtk_window_propagate_key_event(GTK_WINDOW(widget), event)) {
|
| - if (!gtk_window_activate_key(GTK_WINDOW(widget), event)) {
|
| - gtk_bindings_activate_event(GTK_OBJECT(widget), event);
|
| - }
|
| - }
|
| - } else {
|
| - bool rv = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
|
| - DCHECK(rv);
|
| - }
|
| -
|
| - // Prevents the default handler from handling this event.
|
| - return TRUE;
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnMouseMoveEvent(GtkWidget* widget,
|
| - GdkEventMotion* event) {
|
| - // This method is used to update the mouse cursor when over the edge of the
|
| - // custom frame. If the custom frame is off or we're over some other widget,
|
| - // do nothing.
|
| - if (!UseCustomFrame() || event->window != gtk_widget_get_window(widget)) {
|
| - // Reset the cursor.
|
| - if (frame_cursor_) {
|
| - frame_cursor_ = NULL;
|
| - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(window_)), NULL);
|
| - }
|
| - return FALSE;
|
| - }
|
| -
|
| - // Update the cursor if we're on the custom frame border.
|
| - GdkWindowEdge edge;
|
| - bool has_hit_edge = GetWindowEdge(static_cast<int>(event->x),
|
| - static_cast<int>(event->y), &edge);
|
| - GdkCursorType new_cursor = GDK_LAST_CURSOR;
|
| - if (has_hit_edge)
|
| - new_cursor = gtk_window_util::GdkWindowEdgeToGdkCursorType(edge);
|
| -
|
| - GdkCursorType last_cursor = GDK_LAST_CURSOR;
|
| - if (frame_cursor_)
|
| - last_cursor = frame_cursor_->type;
|
| -
|
| - if (last_cursor != new_cursor) {
|
| - if (has_hit_edge) {
|
| - frame_cursor_ = gfx::GetCursor(new_cursor);
|
| - } else {
|
| - frame_cursor_ = NULL;
|
| - }
|
| - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(window_)),
|
| - frame_cursor_);
|
| - }
|
| - return FALSE;
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnButtonPressEvent(GtkWidget* widget,
|
| - GdkEventButton* event) {
|
| - // Handle back/forward.
|
| - if (event->type == GDK_BUTTON_PRESS) {
|
| - if (event->button == 8) {
|
| - chrome::GoBack(browser_.get(), CURRENT_TAB);
|
| - return TRUE;
|
| - } else if (event->button == 9) {
|
| - chrome::GoForward(browser_.get(), CURRENT_TAB);
|
| - return TRUE;
|
| - }
|
| - }
|
| -
|
| - // Handle left, middle and right clicks. In particular, we care about clicks
|
| - // in the custom frame border and clicks in the titlebar.
|
| -
|
| - // Make the button press coordinate relative to the browser window.
|
| - int win_x, win_y;
|
| - GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
|
| - gdk_window_get_origin(gdk_window, &win_x, &win_y);
|
| -
|
| - GdkWindowEdge edge;
|
| - gfx::Point point(static_cast<int>(event->x_root - win_x),
|
| - static_cast<int>(event->y_root - win_y));
|
| - bool has_hit_edge = GetWindowEdge(point.x(), point.y(), &edge);
|
| -
|
| - // Ignore clicks that are in/below the browser toolbar.
|
| - GtkWidget* toolbar = toolbar_->widget();
|
| - if (!gtk_widget_get_visible(toolbar)) {
|
| - // If the toolbar is not showing, use the location of web contents as the
|
| - // boundary of where to ignore clicks.
|
| - toolbar = render_area_vbox_;
|
| - }
|
| - gint toolbar_y;
|
| - gtk_widget_get_pointer(toolbar, NULL, &toolbar_y);
|
| - bool has_hit_titlebar = !IsFullscreen() && (toolbar_y < 0)
|
| - && !has_hit_edge;
|
| - if (event->button == 1) {
|
| - if (GDK_BUTTON_PRESS == event->type) {
|
| - // Raise the window after a click on either the titlebar or the border to
|
| - // match the behavior of most window managers, unless that behavior has
|
| - // been suppressed.
|
| - if ((has_hit_titlebar || has_hit_edge) && !suppress_window_raise_)
|
| - gdk_window_raise(gdk_window);
|
| -
|
| - if (has_hit_titlebar) {
|
| - return gtk_window_util::HandleTitleBarLeftMousePress(
|
| - window_, bounds_, event);
|
| - } else if (has_hit_edge) {
|
| - gtk_window_begin_resize_drag(window_, edge, event->button,
|
| - static_cast<gint>(event->x_root),
|
| - static_cast<gint>(event->y_root),
|
| - event->time);
|
| - return TRUE;
|
| - }
|
| - } else if (GDK_2BUTTON_PRESS == event->type) {
|
| - if (has_hit_titlebar) {
|
| - // Maximize/restore on double click.
|
| - if (IsMaximized()) {
|
| - UnMaximize();
|
| - } else {
|
| - gtk_window_maximize(window_);
|
| - }
|
| - return TRUE;
|
| - }
|
| - }
|
| - } else if (event->button == 2) {
|
| - if (has_hit_titlebar || has_hit_edge) {
|
| - gdk_window_lower(gdk_window);
|
| - }
|
| - return TRUE;
|
| - } else if (event->button == 3) {
|
| - if (has_hit_titlebar) {
|
| - titlebar_->ShowContextMenu(event);
|
| - return TRUE;
|
| - }
|
| - }
|
| -
|
| - return FALSE; // Continue to propagate the event.
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnFocusIn(GtkWidget* widget,
|
| - GdkEventFocus* event) {
|
| - BrowserList::SetLastActive(browser_.get());
|
| - return FALSE;
|
| -}
|
| -
|
| -gboolean BrowserWindowGtk::OnFocusOut(GtkWidget* widget,
|
| - GdkEventFocus* event) {
|
| - return FALSE;
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowSupportedWindowFeatures() {
|
| - if (IsTabStripSupported())
|
| - tabstrip_->Show();
|
| -
|
| - if (IsToolbarSupported()) {
|
| - toolbar_->Show();
|
| - gtk_widget_show(toolbar_border_);
|
| - gdk_window_lower(gtk_widget_get_window(toolbar_border_));
|
| - }
|
| -
|
| - if (IsBookmarkBarSupported())
|
| - MaybeShowBookmarkBar(false);
|
| -}
|
| -
|
| -void BrowserWindowGtk::HideUnsupportedWindowFeatures() {
|
| - if (!IsTabStripSupported())
|
| - tabstrip_->Hide();
|
| -
|
| - if (!IsToolbarSupported())
|
| - toolbar_->Hide();
|
| -
|
| - // If the bookmark bar shelf is unsupported, then we never create it.
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsTabStripSupported() const {
|
| - return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsToolbarSupported() const {
|
| - return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
|
| - browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::IsBookmarkBarSupported() const {
|
| - return browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::UsingCustomPopupFrame() const {
|
| - GtkThemeService* theme_provider = GtkThemeService::GetFrom(
|
| - browser()->profile());
|
| - return !theme_provider->UsingNativeTheme() && browser()->is_type_popup();
|
| -}
|
| -
|
| -bool BrowserWindowGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) {
|
| - if (!UseCustomFrame())
|
| - return false;
|
| -
|
| - if (IsMaximized() || IsFullscreen())
|
| - return false;
|
| -
|
| - return gtk_window_util::GetWindowEdge(
|
| - bounds_.size(), kTopResizeAdjust, x, y, edge);
|
| -}
|
| -
|
| -bool BrowserWindowGtk::UseCustomFrame() const {
|
| - // We don't use the custom frame for app mode windows or app window popups.
|
| - return use_custom_frame_pref_.GetValue() && !browser_->is_app();
|
| -}
|
| -
|
| -void BrowserWindowGtk::PlaceBookmarkBar(bool is_floating) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::PlaceBookmarkBar");
|
| -
|
| - GtkWidget* target_parent = NULL;
|
| - if (!is_floating) {
|
| - // Place the bookmark bar at the end of |window_vbox_|; this happens after
|
| - // we have placed the render area at the end of |window_vbox_| so we will
|
| - // be above the render area.
|
| - target_parent = window_vbox_;
|
| - } else {
|
| - // Place the bookmark bar at the end of the render area; this happens after
|
| - // the tab contents container has been placed there so we will be
|
| - // above the webpage (in terms of y).
|
| - target_parent = render_area_vbox_;
|
| - }
|
| -
|
| - GtkWidget* parent = gtk_widget_get_parent(bookmark_bar_->widget());
|
| - if (parent != target_parent) {
|
| - if (parent)
|
| - gtk_container_remove(GTK_CONTAINER(parent), bookmark_bar_->widget());
|
| -
|
| - gtk_box_pack_end(GTK_BOX(target_parent), bookmark_bar_->widget(),
|
| - FALSE, FALSE, 0);
|
| - }
|
| -}
|
| -
|
| -bool BrowserWindowGtk::DrawFrameAsActive() const {
|
| - if (ui::ActiveWindowWatcherX::WMSupportsActivation())
|
| - return is_active_;
|
| -
|
| - // Since we don't get notifications when the active state of the frame
|
| - // changes, we can't consistently repaint the frame at the right time. Instead
|
| - // we always draw the frame as active.
|
| - return true;
|
| -}
|
| -
|
| -void BrowserWindowGtk::UpdateDevToolsForContents(WebContents* contents) {
|
| - TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::UpdateDevToolsForContents");
|
| - DevToolsWindow* new_devtools_window = contents ?
|
| - DevToolsWindow::GetDockedInstanceForInspectedTab(contents) : NULL;
|
| -
|
| - // Replace tab contents.
|
| - if (devtools_window_ != new_devtools_window) {
|
| - if (devtools_window_)
|
| - devtools_container_->DetachTab(devtools_window_->web_contents());
|
| - devtools_container_->SetTab(
|
| - new_devtools_window ? new_devtools_window->web_contents() : NULL);
|
| - if (new_devtools_window) {
|
| - // WebContentsViewGtk::WasShown is not called when a web contents is shown
|
| - // by anything other than user selecting a Tab.
|
| - // See TabContentsViewViews::OnWindowPosChanged for reference on how it
|
| - // should be implemented.
|
| - new_devtools_window->web_contents()->WasShown();
|
| - }
|
| - }
|
| -
|
| - // Show / hide container if necessary.
|
| - bool should_hide = devtools_window_ && !new_devtools_window;
|
| - bool should_show = new_devtools_window && !devtools_window_;
|
| -
|
| - if (should_hide)
|
| - HideDevToolsContainer();
|
| -
|
| - devtools_window_ = new_devtools_window;
|
| - if (devtools_window_) {
|
| - contents_resizing_strategy_.CopyFrom(
|
| - devtools_window_->GetContentsResizingStrategy());
|
| - } else {
|
| - contents_resizing_strategy_.CopyFrom(DevToolsContentsResizingStrategy());
|
| - }
|
| -
|
| - if (should_show)
|
| - ShowDevToolsContainer();
|
| -
|
| - gtk_widget_queue_resize(devtools_floating_container_);
|
| - gtk_widget_queue_draw(devtools_floating_container_);
|
| -}
|
| -
|
| -void BrowserWindowGtk::ShowDevToolsContainer() {
|
| - // Move devtools below contents.
|
| - GdkWindow* const devtools_gdk_window =
|
| - gtk_widget_get_window(devtools_container_->widget());
|
| - if (devtools_gdk_window)
|
| - gdk_window_lower(devtools_gdk_window);
|
| -}
|
| -
|
| -void BrowserWindowGtk::HideDevToolsContainer() {
|
| - // This method is left intentionally blank.
|
| -}
|
| -
|
| -// static
|
| -void BrowserWindowGtk::OnDevToolsContainerSetFloatingPosition(
|
| - GtkFloatingContainer* container, GtkAllocation* allocation,
|
| - BrowserWindowGtk* browser_window) {
|
| - GtkAllocation contents_allocation;
|
| - gtk_widget_get_allocation(browser_window->contents_container_->widget(),
|
| - &contents_allocation);
|
| -
|
| - gfx::Size container_size(allocation->width, allocation->height);
|
| - gfx::Rect old_devtools_bounds(0, 0, allocation->width, allocation->height);
|
| - gfx::Rect old_contents_bounds(contents_allocation.x, contents_allocation.y,
|
| - contents_allocation.width, contents_allocation.height);
|
| - gfx::Rect new_devtools_bounds;
|
| - gfx::Rect new_contents_bounds;
|
| -
|
| - ApplyDevToolsContentsResizingStrategy(
|
| - browser_window->contents_resizing_strategy_, container_size,
|
| - old_devtools_bounds, old_contents_bounds,
|
| - &new_devtools_bounds, &new_contents_bounds);
|
| -
|
| - gtk_widget_set_size_request(browser_window->contents_container_->widget(),
|
| - new_contents_bounds.width(), new_contents_bounds.height());
|
| -
|
| - GValue value = { 0, };
|
| - g_value_init(&value, G_TYPE_INT);
|
| - g_value_set_int(&value, new_contents_bounds.x());
|
| - gtk_container_child_set_property(GTK_CONTAINER(container),
|
| - browser_window->contents_container_->widget(), "x", &value);
|
| - g_value_set_int(&value, new_contents_bounds.y());
|
| - gtk_container_child_set_property(GTK_CONTAINER(container),
|
| - browser_window->contents_container_->widget(), "y", &value);
|
| - g_value_unset(&value);
|
| -}
|
| -
|
| -void BrowserWindowGtk::OnUseCustomChromeFrameChanged() {
|
| - UpdateCustomFrame();
|
| - ui::SetHideTitlebarWhenMaximizedProperty(
|
| - ui::GetX11WindowFromGtkWidget(GTK_WIDGET(window_)),
|
| - UseCustomFrame() ? ui::HIDE_TITLEBAR_WHEN_MAXIMIZED :
|
| - ui::SHOW_TITLEBAR_WHEN_MAXIMIZED);
|
| -}
|
| -
|
| -// static
|
| -BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) {
|
| - BrowserWindowGtk* browser_window_gtk = new BrowserWindowGtk(browser);
|
| - browser_window_gtk->Init();
|
| - return browser_window_gtk;
|
| -}
|
| -
|
| -// static
|
| -chrome::HostDesktopType BrowserWindow::AdjustHostDesktopType(
|
| - chrome::HostDesktopType desktop_type) {
|
| - return desktop_type;
|
| -}
|
|
|