Index: chrome/browser/ui/gtk/panels/panel_gtk.cc |
diff --git a/chrome/browser/ui/gtk/panels/panel_gtk.cc b/chrome/browser/ui/gtk/panels/panel_gtk.cc |
deleted file mode 100644 |
index 274cbb3c4887b4405f1c489d80b3f7d078c9734f..0000000000000000000000000000000000000000 |
--- a/chrome/browser/ui/gtk/panels/panel_gtk.cc |
+++ /dev/null |
@@ -1,1255 +0,0 @@ |
-// Copyright (c) 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/panels/panel_gtk.h" |
- |
-#include <gdk/gdk.h> |
-#include <gdk/gdkkeysyms.h> |
-#include <X11/XF86keysym.h> |
- |
-#include "base/bind.h" |
-#include "base/debug/trace_event.h" |
-#include "base/logging.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "chrome/app/chrome_command_ids.h" |
-#include "chrome/browser/chrome_notification_types.h" |
-#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h" |
-#include "chrome/browser/ui/gtk/custom_button.h" |
-#include "chrome/browser/ui/gtk/gtk_util.h" |
-#include "chrome/browser/ui/gtk/gtk_window_util.h" |
-#include "chrome/browser/ui/gtk/panels/panel_drag_gtk.h" |
-#include "chrome/browser/ui/gtk/panels/panel_titlebar_gtk.h" |
-#include "chrome/browser/ui/panels/display_settings_provider.h" |
-#include "chrome/browser/ui/panels/panel.h" |
-#include "chrome/browser/ui/panels/panel_constants.h" |
-#include "chrome/browser/ui/panels/panel_manager.h" |
-#include "chrome/browser/ui/panels/stacked_panel_collection.h" |
-#include "chrome/browser/web_applications/web_app.h" |
-#include "content/public/browser/native_web_keyboard_event.h" |
-#include "content/public/browser/notification_service.h" |
-#include "content/public/browser/web_contents.h" |
-#include "content/public/browser/web_contents_view.h" |
-#include "grit/ui_resources.h" |
-#include "ui/base/accelerators/platform_accelerator_gtk.h" |
-#include "ui/base/gtk/gtk_expanded_container.h" |
-#include "ui/base/gtk/gtk_hig_constants.h" |
-#include "ui/base/x/active_window_watcher_x.h" |
-#include "ui/base/x/x11_util.h" |
-#include "ui/gfx/canvas.h" |
-#include "ui/gfx/gtk_compat.h" |
-#include "ui/gfx/image/cairo_cached_surface.h" |
-#include "ui/gfx/image/image.h" |
- |
-using content::NativeWebKeyboardEvent; |
-using content::WebContents; |
- |
-namespace { |
- |
-const char* kPanelWindowKey = "__PANEL_GTK__"; |
- |
-// The number of milliseconds between loading animation frames. |
-const int kLoadingAnimationFrameTimeMs = 30; |
- |
-// The frame border is only visible in restored mode and is hardcoded to 4 px |
-// on each side regardless of the system window border size. |
-const int kFrameBorderThickness = 4; |
-// 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; |
-// In the window corners, the resize areas don't actually expand bigger, but |
-// the 16 px at the end of each edge triggers diagonal resizing. |
-const int kResizeAreaCornerSize = 16; |
- |
-// Colors used to draw frame background under default theme. |
-const SkColor kActiveBackgroundDefaultColor = SkColorSetRGB(0x3a, 0x3d, 0x3d); |
-const SkColor kInactiveBackgroundDefaultColor = SkColorSetRGB(0x7a, 0x7c, 0x7c); |
-const SkColor kAttentionBackgroundDefaultColor = |
- SkColorSetRGB(0x53, 0xa9, 0x3f); |
-const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0); |
-const SkColor kMinimizeBorderDefaultColor = SkColorSetRGB(0xc9, 0xc9, 0xc9); |
- |
-// Set minimium width for window really small. |
-const int kMinWindowWidth = 26; |
- |
-// Table of supported accelerators in Panels. |
-const struct AcceleratorMapping { |
- guint keyval; |
- int command_id; |
- GdkModifierType modifier_type; |
-} kAcceleratorMap[] = { |
- // Window controls. |
- { GDK_w, IDC_CLOSE_WINDOW, GDK_CONTROL_MASK }, |
- { GDK_w, IDC_CLOSE_WINDOW, |
- GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
- { GDK_q, IDC_EXIT, GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
- |
- // Zoom level. |
- { GDK_KP_Add, IDC_ZOOM_PLUS, GDK_CONTROL_MASK }, |
- { GDK_plus, IDC_ZOOM_PLUS, |
- GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
- { GDK_equal, IDC_ZOOM_PLUS, GDK_CONTROL_MASK }, |
- { XF86XK_ZoomIn, IDC_ZOOM_PLUS, GdkModifierType(0) }, |
- { GDK_KP_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK }, |
- { GDK_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK }, |
- { GDK_KP_Subtract, IDC_ZOOM_MINUS, GDK_CONTROL_MASK }, |
- { GDK_minus, IDC_ZOOM_MINUS, GDK_CONTROL_MASK }, |
- { GDK_underscore, IDC_ZOOM_MINUS, |
- GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
- { XF86XK_ZoomOut, IDC_ZOOM_MINUS, GdkModifierType(0) }, |
- |
- // Navigation. |
- { GDK_Escape, IDC_STOP, GdkModifierType(0) }, |
- { XF86XK_Stop, IDC_STOP, GdkModifierType(0) }, |
- { GDK_r, IDC_RELOAD, GDK_CONTROL_MASK }, |
- { GDK_r, IDC_RELOAD_IGNORING_CACHE, |
- GdkModifierType(GDK_CONTROL_MASK|GDK_SHIFT_MASK) }, |
- { GDK_F5, IDC_RELOAD, GdkModifierType(0) }, |
- { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_CONTROL_MASK }, |
- { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_SHIFT_MASK }, |
- { XF86XK_Reload, IDC_RELOAD, GdkModifierType(0) }, |
- { XF86XK_Refresh, IDC_RELOAD, GdkModifierType(0) }, |
- |
- // Editing. |
- { GDK_c, IDC_COPY, GDK_CONTROL_MASK }, |
- { GDK_x, IDC_CUT, GDK_CONTROL_MASK }, |
- { GDK_v, IDC_PASTE, GDK_CONTROL_MASK }, |
- |
- // Dev tools. |
- { GDK_i, IDC_DEV_TOOLS, |
- GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
- { GDK_j, IDC_DEV_TOOLS_CONSOLE, |
- GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
- |
-}; |
- |
-// Table of accelerator mappings to command ids. |
-typedef std::map<ui::Accelerator, int> AcceleratorMap; |
- |
-const AcceleratorMap& GetAcceleratorTable() { |
- CR_DEFINE_STATIC_LOCAL(AcceleratorMap, accelerator_table, ()); |
- if (accelerator_table.empty()) { |
- for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { |
- const AcceleratorMapping& entry = kAcceleratorMap[i]; |
- ui::Accelerator accelerator = ui::AcceleratorForGdkKeyCodeAndModifier( |
- entry.keyval, entry.modifier_type); |
- accelerator_table[accelerator] = entry.command_id; |
- } |
- } |
- return accelerator_table; |
-} |
- |
-gfx::Image CreateImageForColor(SkColor color) { |
- gfx::Canvas canvas(gfx::Size(1, 1), 1.0f, true); |
- canvas.DrawColor(color); |
- return gfx::Image(gfx::ImageSkia(canvas.ExtractImageRep())); |
-} |
- |
-const gfx::Image GetActiveBackgroundDefaultImage() { |
- CR_DEFINE_STATIC_LOCAL(gfx::Image, image, ()); |
- if (image.IsEmpty()) |
- image = CreateImageForColor(kActiveBackgroundDefaultColor); |
- return image; |
-} |
- |
-gfx::Image GetInactiveBackgroundDefaultImage() { |
- CR_DEFINE_STATIC_LOCAL(gfx::Image, image, ()); |
- if (image.IsEmpty()) |
- image = CreateImageForColor(kInactiveBackgroundDefaultColor); |
- return image; |
-} |
- |
-gfx::Image GetAttentionBackgroundDefaultImage() { |
- CR_DEFINE_STATIC_LOCAL(gfx::Image, image, ()); |
- if (image.IsEmpty()) |
- image = CreateImageForColor(kAttentionBackgroundDefaultColor); |
- return image; |
-} |
- |
-gfx::Image GetMinimizeBackgroundDefaultImage() { |
- CR_DEFINE_STATIC_LOCAL(gfx::Image, image, ()); |
- if (image.IsEmpty()) |
- image = CreateImageForColor(kMinimizeBackgroundDefaultColor); |
- return image; |
-} |
- |
-// Used to stash a pointer to the Panel window inside the native |
-// Gtk window for retrieval in static callbacks. |
-GQuark GetPanelWindowQuarkKey() { |
- static GQuark quark = g_quark_from_static_string(kPanelWindowKey); |
- return quark; |
-} |
- |
-// Size of window frame. Empty until first panel has been allocated |
-// and sized. Frame size won't change for other panels so it can be |
-// computed once for all panels. |
-gfx::Size& GetFrameSize() { |
- CR_DEFINE_STATIC_LOCAL(gfx::Size, frame_size, ()); |
- return frame_size; |
-} |
- |
-void SetFrameSize(const gfx::Size& new_size) { |
- gfx::Size& frame_size = GetFrameSize(); |
- frame_size.SetSize(new_size.width(), new_size.height()); |
-} |
- |
-} // namespace |
- |
-// static |
-NativePanel* Panel::CreateNativePanel(Panel* panel, |
- const gfx::Rect& bounds, |
- bool always_on_top) { |
- PanelGtk* panel_gtk = new PanelGtk(panel, bounds, always_on_top); |
- panel_gtk->Init(); |
- return panel_gtk; |
-} |
- |
-PanelGtk::PanelGtk(Panel* panel, const gfx::Rect& bounds, bool always_on_top) |
- : panel_(panel), |
- bounds_(bounds), |
- always_on_top_(always_on_top), |
- is_shown_(false), |
- paint_state_(PAINT_AS_INACTIVE), |
- is_drawing_attention_(false), |
- frame_cursor_(NULL), |
- is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()), |
- is_minimized_(false), |
- window_(NULL), |
- window_container_(NULL), |
- window_vbox_(NULL), |
- render_area_event_box_(NULL), |
- contents_expanded_(NULL), |
- accel_group_(NULL), |
- corner_style_(panel::ALL_ROUNDED) { |
-} |
- |
-PanelGtk::~PanelGtk() { |
- ui::ActiveWindowWatcherX::RemoveObserver(this); |
-} |
- |
-void PanelGtk::Init() { |
- ui::ActiveWindowWatcherX::AddObserver(this); |
- |
- window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); |
- g_object_set_qdata(G_OBJECT(window_), GetPanelWindowQuarkKey(), this); |
- gtk_widget_add_events(GTK_WIDGET(window_), GDK_BUTTON_PRESS_MASK | |
- GDK_POINTER_MOTION_MASK); |
- gtk_window_set_decorated(window_, false); |
- |
- // 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 minimum height for the window. |
- GdkGeometry hints; |
- hints.min_height = panel::kMinimizedPanelHeight; |
- hints.min_width = kMinWindowWidth; |
- gtk_window_set_geometry_hints( |
- window_, GTK_WIDGET(window_), &hints, GDK_HINT_MIN_SIZE); |
- |
- // Connect signal handlers to the window. |
- 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); |
- |
- // This vbox contains the titlebar and the render area, but not |
- // the custom frame border. |
- window_vbox_ = gtk_vbox_new(FALSE, 0); |
- gtk_widget_show(window_vbox_); |
- |
- // TODO(jennb): add GlobalMenuBar after refactoring out Browser. |
- |
- // The window container draws the custom window 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); |
- gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 0, |
- kFrameBorderThickness, kFrameBorderThickness, kFrameBorderThickness); |
- g_signal_connect(window_container_, "expose-event", |
- G_CALLBACK(OnCustomFrameExposeThunk), this); |
- gtk_container_add(GTK_CONTAINER(window_container_), window_vbox_); |
- |
- // Build the titlebar. |
- titlebar_.reset(new PanelTitlebarGtk(this)); |
- titlebar_->Init(); |
- gtk_box_pack_start(GTK_BOX(window_vbox_), titlebar_->widget(), FALSE, FALSE, |
- 0); |
- g_signal_connect(titlebar_->widget(), "button-press-event", |
- G_CALLBACK(OnTitlebarButtonPressEventThunk), this); |
- g_signal_connect(titlebar_->widget(), "button-release-event", |
- G_CALLBACK(OnTitlebarButtonReleaseEventThunk), this); |
- |
- contents_expanded_ = gtk_expanded_container_new(); |
- gtk_widget_show(contents_expanded_); |
- |
- 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_), |
- contents_expanded_); |
- gtk_widget_show(render_area_event_box_); |
- gtk_box_pack_end(GTK_BOX(window_vbox_), render_area_event_box_, |
- TRUE, TRUE, 0); |
- |
- gtk_container_add(GTK_CONTAINER(window_), window_container_); |
- gtk_widget_show(window_container_); |
- |
- ConnectAccelerators(); |
- SetPanelAlwaysOnTop(always_on_top_); |
-} |
- |
-void PanelGtk::SetWindowCornerStyle(panel::CornerStyle corner_style) { |
- corner_style_ = corner_style; |
- UpdateWindowShape(); |
-} |
- |
-void PanelGtk::MinimizePanelBySystem() { |
- gtk_window_iconify(window_); |
-} |
- |
-bool PanelGtk::IsPanelMinimizedBySystem() const { |
- return is_minimized_; |
-} |
- |
-bool PanelGtk::IsPanelShownOnActiveDesktop() const { |
- // IsWindowVisible checks _NET_WM_DESKTOP. |
- if (!ui::IsWindowVisible(ui::GetX11WindowFromGtkWidget(GTK_WIDGET(window_)))) |
- return false; |
- |
- // Certain window manager, like Unity, does not update _NET_WM_DESKTOP when a |
- // window is moved to other workspace. However, it treats all workspaces as |
- // concatenated together in one big coordinate space. When the user switches |
- // to another workspace, the window manager will update the origins of all |
- // windows in previous active workspace to move by the size of display |
- // area. |
- gfx::Rect display_area = PanelManager::GetInstance()-> |
- display_settings_provider()->GetDisplayAreaMatching(bounds_); |
- int win_x = 0, win_y = 0; |
- gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(window_)), |
- &win_x, &win_y); |
- return abs(win_x - bounds_.x()) < display_area.width() && |
- abs(win_y - bounds_.y()) < display_area.height(); |
-} |
- |
-void PanelGtk::ShowShadow(bool show) { |
- // Shadow is not supported for GTK panel. |
-} |
- |
-void PanelGtk::UpdateWindowShape() { |
- int width = configure_size_.width(); |
- int height = configure_size_.height(); |
- if (!width || !height) |
- return; |
- |
- GdkRegion* mask; |
- if (corner_style_ & panel::TOP_ROUNDED) { |
- GdkRectangle top_top_rect = { 3, 0, width - 6, 1 }; |
- GdkRectangle top_mid_rect = { 1, 1, width - 2, 2 }; |
- mask = gdk_region_rectangle(&top_top_rect); |
- gdk_region_union_with_rect(mask, &top_mid_rect); |
- } else { |
- GdkRectangle top_rect = { 0, 0, width, 3 }; |
- mask = gdk_region_rectangle(&top_rect); |
- } |
- |
- if (corner_style_ & panel::BOTTOM_ROUNDED) { |
- GdkRectangle mid_rect = { 0, 3, width, height - 6 }; |
- GdkRectangle bottom_mid_rect = { 1, height - 3, width - 2, 2 }; |
- GdkRectangle bottom_bottom_rect = { 3, height - 1, width - 6, 1 }; |
- gdk_region_union_with_rect(mask, &mid_rect); |
- gdk_region_union_with_rect(mask, &bottom_mid_rect); |
- gdk_region_union_with_rect(mask, &bottom_bottom_rect); |
- } else { |
- GdkRectangle mid_rect = { 0, 3, width, height - 3 }; |
- gdk_region_union_with_rect(mask, &mid_rect); |
- } |
- |
- gdk_window_shape_combine_region( |
- gtk_widget_get_window(GTK_WIDGET(window_)), mask, 0, 0); |
- if (mask) |
- gdk_region_destroy(mask); |
-} |
- |
-gboolean PanelGtk::OnConfigure(GtkWidget* widget, |
- GdkEventConfigure* event) { |
- // 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 |
- gfx::Size new_size(event->width, event->height); |
- if (new_size == configure_size_) |
- return FALSE; |
- configure_size_ = new_size; |
- |
- UpdateWindowShape(); |
- |
- if (!GetFrameSize().IsEmpty()) |
- return FALSE; |
- |
- // Save the frame size allocated by the system as the |
- // frame size will be affected when we shrink the panel smaller |
- // than the frame (e.g. when the panel is minimized). |
- SetFrameSize(GetNonClientFrameSize()); |
- panel_->OnWindowSizeAvailable(); |
- |
- content::NotificationService::current()->Notify( |
- chrome::NOTIFICATION_PANEL_WINDOW_SIZE_KNOWN, |
- content::Source<Panel>(panel_.get()), |
- content::NotificationService::NoDetails()); |
- |
- return FALSE; |
-} |
- |
-gboolean PanelGtk::OnWindowState(GtkWidget* widget, |
- GdkEventWindowState* event) { |
- is_minimized_ = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED; |
- return FALSE; |
-} |
- |
-void PanelGtk::ConnectAccelerators() { |
- accel_group_ = gtk_accel_group_new(); |
- gtk_window_add_accel_group(window_, accel_group_); |
- |
- const AcceleratorMap& accelerator_table = GetAcceleratorTable(); |
- for (AcceleratorMap::const_iterator iter = accelerator_table.begin(); |
- iter != accelerator_table.end(); ++iter) { |
- gtk_accel_group_connect( |
- accel_group_, |
- ui::GetGdkKeyCodeForAccelerator(iter->first), |
- ui::GetGdkModifierForAccelerator(iter->first), |
- GtkAccelFlags(0), |
- g_cclosure_new(G_CALLBACK(OnGtkAccelerator), |
- GINT_TO_POINTER(iter->second), NULL)); |
- } |
-} |
- |
-void PanelGtk::DisconnectAccelerators() { |
- // Disconnecting the keys we connected to our accelerator group frees the |
- // closures allocated in ConnectAccelerators. |
- const AcceleratorMap& accelerator_table = GetAcceleratorTable(); |
- for (AcceleratorMap::const_iterator iter = accelerator_table.begin(); |
- iter != accelerator_table.end(); ++iter) { |
- gtk_accel_group_disconnect_key( |
- accel_group_, |
- ui::GetGdkKeyCodeForAccelerator(iter->first), |
- ui::GetGdkModifierForAccelerator(iter->first)); |
- } |
- gtk_window_remove_accel_group(window_, accel_group_); |
- g_object_unref(accel_group_); |
- accel_group_ = NULL; |
-} |
- |
-// static |
-gboolean PanelGtk::OnGtkAccelerator(GtkAccelGroup* accel_group, |
- GObject* acceleratable, |
- guint keyval, |
- GdkModifierType modifier, |
- void* user_data) { |
- DCHECK(acceleratable); |
- int command_id = GPOINTER_TO_INT(user_data); |
- PanelGtk* panel_gtk = static_cast<PanelGtk*>( |
- g_object_get_qdata(acceleratable, GetPanelWindowQuarkKey())); |
- return panel_gtk->panel()->ExecuteCommandIfEnabled(command_id); |
-} |
- |
-gboolean PanelGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) { |
- // No way to deactivate a window in GTK, so ignore input if window |
- // is supposed to be 'inactive'. See comments in DeactivatePanel(). |
- if (!is_active_) |
- 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); |
- } |
- } |
- return TRUE; |
-} |
- |
-bool PanelGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) const { |
- // Only detect the window edge when panels can be resized by the user. |
- // This method is used by the base class to detect when the cursor has |
- // hit the window edge in order to change the cursor to a resize cursor |
- // and to detect when to initiate a resize drag. |
- panel::Resizability resizability = panel_->CanResizeByMouse(); |
- if (panel::NOT_RESIZABLE == resizability) |
- return false; |
- |
- int width = bounds_.width(); |
- int height = bounds_.height(); |
- if (x < kFrameBorderThickness) { |
- if (y < kResizeAreaCornerSize - kTopResizeAdjust && |
- (resizability & panel::RESIZABLE_TOP_LEFT)) { |
- *edge = GDK_WINDOW_EDGE_NORTH_WEST; |
- return true; |
- } else if (y >= height - kResizeAreaCornerSize && |
- (resizability & panel::RESIZABLE_BOTTOM_LEFT)) { |
- *edge = GDK_WINDOW_EDGE_SOUTH_WEST; |
- return true; |
- } |
- } else if (x >= width - kFrameBorderThickness) { |
- if (y < kResizeAreaCornerSize - kTopResizeAdjust && |
- (resizability & panel::RESIZABLE_TOP_RIGHT)) { |
- *edge = GDK_WINDOW_EDGE_NORTH_EAST; |
- return true; |
- } else if (y >= height - kResizeAreaCornerSize && |
- (resizability & panel::RESIZABLE_BOTTOM_RIGHT)) { |
- *edge = GDK_WINDOW_EDGE_SOUTH_EAST; |
- return true; |
- } |
- } |
- |
- if (x < kFrameBorderThickness && (resizability & panel::RESIZABLE_LEFT)) { |
- *edge = GDK_WINDOW_EDGE_WEST; |
- return true; |
- } else if (x >= width - kFrameBorderThickness && |
- (resizability & panel::RESIZABLE_RIGHT)) { |
- *edge = GDK_WINDOW_EDGE_EAST; |
- return true; |
- } |
- |
- if (y < kFrameBorderThickness && (resizability & panel::RESIZABLE_TOP)) { |
- *edge = GDK_WINDOW_EDGE_NORTH; |
- return true; |
- } else if (y >= height - kFrameBorderThickness && |
- (resizability & panel::RESIZABLE_BOTTOM)) { |
- *edge = GDK_WINDOW_EDGE_SOUTH; |
- return true; |
- } |
- |
- return false; |
-} |
- |
-gfx::Image PanelGtk::GetFrameBackground() const { |
- switch (paint_state_) { |
- case PAINT_AS_INACTIVE: |
- return GetInactiveBackgroundDefaultImage(); |
- case PAINT_AS_ACTIVE: |
- return GetActiveBackgroundDefaultImage(); |
- case PAINT_AS_MINIMIZED: |
- return GetMinimizeBackgroundDefaultImage(); |
- case PAINT_FOR_ATTENTION: |
- return GetAttentionBackgroundDefaultImage(); |
- default: |
- NOTREACHED(); |
- return GetInactiveBackgroundDefaultImage(); |
- } |
-} |
- |
-gboolean PanelGtk::OnCustomFrameExpose(GtkWidget* widget, |
- GdkEventExpose* event) { |
- TRACE_EVENT0("ui::gtk", "PanelGtk::OnCustomFrameExpose"); |
- cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget)); |
- gdk_cairo_rectangle(cr, &event->area); |
- cairo_clip(cr); |
- |
- // Update the painting state. |
- int window_height = gdk_window_get_height(gtk_widget_get_window(widget)); |
- if (is_drawing_attention_) |
- paint_state_ = PAINT_FOR_ATTENTION; |
- else if (window_height <= panel::kMinimizedPanelHeight) |
- paint_state_ = PAINT_AS_MINIMIZED; |
- else if (is_active_) |
- paint_state_ = PAINT_AS_ACTIVE; |
- else |
- paint_state_ = PAINT_AS_INACTIVE; |
- |
- // Draw the background. |
- gfx::CairoCachedSurface* surface = GetFrameBackground().ToCairo(); |
- surface->SetSource(cr, widget, 0, 0); |
- cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT); |
- cairo_rectangle(cr, event->area.x, event->area.y, |
- event->area.width, event->area.height); |
- cairo_fill(cr); |
- |
- // Draw the border for the minimized panel only. |
- if (paint_state_ == PAINT_AS_MINIMIZED) { |
- cairo_move_to(cr, 0, 3); |
- cairo_line_to(cr, 1, 2); |
- cairo_line_to(cr, 1, 1); |
- cairo_line_to(cr, 2, 1); |
- cairo_line_to(cr, 3, 0); |
- cairo_line_to(cr, event->area.width - 3, 0); |
- cairo_line_to(cr, event->area.width - 2, 1); |
- cairo_line_to(cr, event->area.width - 1, 1); |
- cairo_line_to(cr, event->area.width - 1, 2); |
- cairo_line_to(cr, event->area.width - 1, 3); |
- cairo_line_to(cr, event->area.width - 1, event->area.height - 1); |
- cairo_line_to(cr, 0, event->area.height - 1); |
- cairo_close_path(cr); |
- cairo_set_source_rgb(cr, |
- SkColorGetR(kMinimizeBorderDefaultColor) / 255.0, |
- SkColorGetG(kMinimizeBorderDefaultColor) / 255.0, |
- SkColorGetB(kMinimizeBorderDefaultColor) / 255.0); |
- cairo_set_line_width(cr, 1.0); |
- cairo_stroke(cr); |
- } |
- |
- cairo_destroy(cr); |
- |
- return FALSE; // Allow subwidgets to paint. |
-} |
- |
-void PanelGtk::EnsureDragHelperCreated() { |
- if (drag_helper_.get()) |
- return; |
- |
- drag_helper_.reset(new PanelDragGtk(panel_.get())); |
- gtk_box_pack_end(GTK_BOX(window_vbox_), drag_helper_->widget(), |
- FALSE, FALSE, 0); |
-} |
- |
-gboolean PanelGtk::OnTitlebarButtonPressEvent( |
- GtkWidget* widget, GdkEventButton* event) { |
- if (event->button != 1) |
- return TRUE; |
- if (event->type != GDK_BUTTON_PRESS) |
- return TRUE; |
- |
- // If the panel is in a stack, bring all other panels in the stack to the |
- // top. |
- StackedPanelCollection* stack = panel_->stack(); |
- if (stack) { |
- for (StackedPanelCollection::Panels::const_iterator iter = |
- stack->panels().begin(); |
- iter != stack->panels().end(); ++iter) { |
- Panel* panel = *iter; |
- GtkWindow* gtk_window = panel->GetNativeWindow(); |
- // If a panel is collapsed, we make it not to take focus. For such window, |
- // it cannot be brought to the top by calling gdk_window_raise. To work |
- // around this issue, we make it always-on-top first and then put it back |
- // to normal. Note that this trick has been done for all panels in the |
- // stack, regardless of whether it is collapsed or not. |
- // There is one side-effect to this approach: if the panel being pressed |
- // on is collapsed, clicking on the client area of the last active |
- // window will not raise it above these panels. |
- gtk_window_set_keep_above(gtk_window, true); |
- gtk_window_set_keep_above(gtk_window, false); |
- } |
- } else { |
- gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(window_))); |
- } |
- |
- EnsureDragHelperCreated(); |
- drag_helper_->InitialTitlebarMousePress(event, titlebar_->widget()); |
- return TRUE; |
-} |
- |
-gboolean PanelGtk::OnTitlebarButtonReleaseEvent( |
- GtkWidget* widget, GdkEventButton* event) { |
- if (event->button != 1) |
- return TRUE; |
- |
- panel_->OnTitlebarClicked((event->state & GDK_CONTROL_MASK) ? |
- panel::APPLY_TO_ALL : panel::NO_MODIFIER); |
- return TRUE; |
-} |
- |
-gboolean PanelGtk::OnMouseMoveEvent(GtkWidget* widget, |
- GdkEventMotion* event) { |
- // This method is used to update the mouse cursor when over the edge of the |
- // custom frame. If we're over some other widget, do nothing. |
- if (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 = has_hit_edge ? |
- gtk_window_util::GdkWindowEdgeToGdkCursorType(edge) : GDK_LAST_CURSOR; |
- GdkCursorType last_cursor = |
- frame_cursor_ ? frame_cursor_->type : GDK_LAST_CURSOR; |
- |
- if (last_cursor != new_cursor) { |
- frame_cursor_ = has_hit_edge ? gfx::GetCursor(new_cursor) : NULL; |
- gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(window_)), |
- frame_cursor_); |
- } |
- return FALSE; |
-} |
- |
-gboolean PanelGtk::OnButtonPressEvent(GtkWidget* widget, |
- GdkEventButton* event) { |
- if (event->button != 1 || event->type != GDK_BUTTON_PRESS) |
- return FALSE; |
- |
- // No way to deactivate a window in GTK, so we pretended it is deactivated. |
- // See comments in DeactivatePanel(). |
- // Mouse click anywhere in window should re-activate window so do it now. |
- if (!is_active_) |
- panel_->Activate(); |
- |
- // Make the button press coordinate relative to the panel 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); |
- if (has_hit_edge) { |
- gdk_window_raise(gdk_window); |
- EnsureDragHelperCreated(); |
- // Resize cursor was set by PanelGtk when mouse moved over window edge. |
- GdkCursor* cursor = |
- gdk_window_get_cursor(gtk_widget_get_window(GTK_WIDGET(window_))); |
- drag_helper_->InitialWindowEdgeMousePress(event, cursor, edge); |
- return TRUE; |
- } |
- |
- return FALSE; // Continue to propagate the event. |
-} |
- |
-void PanelGtk::ActiveWindowChanged(GdkWindow* active_window) { |
- // Do nothing if we're in the process of closing the panel window. |
- if (!window_) |
- return; |
- |
- bool is_active = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window; |
- if (is_active == is_active_) |
- return; // State did not change. |
- |
- if (is_active) { |
- // 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; |
- titlebar_->UpdateTextColor(); |
- InvalidateWindow(); |
- panel_->OnActiveStateChanged(is_active_); |
-} |
- |
-// Callback for the delete event. This event is fired when the user tries to |
-// close the window. |
-gboolean PanelGtk::OnMainWindowDeleteEvent(GtkWidget* widget, |
- GdkEvent* event) { |
- ClosePanel(); |
- |
- // Return true to prevent the gtk window from being destroyed. Close will |
- // destroy it for us. |
- return TRUE; |
-} |
- |
-void PanelGtk::OnMainWindowDestroy(GtkWidget* widget) { |
- // BUG 8712. When we gtk_widget_destroy() in ClosePanel(), this will emit the |
- // signal right away, and we will be here (while ClosePanel() is still in the |
- // call stack). Let stack unwind before deleting the panel. |
- // |
- // 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<PanelGtk>, this)); |
-} |
- |
-void PanelGtk::ShowPanel() { |
- gtk_window_present(window_); |
- RevealPanel(); |
-} |
- |
-void PanelGtk::ShowPanelInactive() { |
- gtk_window_set_focus_on_map(window_, false); |
- gtk_widget_show(GTK_WIDGET(window_)); |
- RevealPanel(); |
-} |
- |
-void PanelGtk::RevealPanel() { |
- DCHECK(!is_shown_); |
- is_shown_ = true; |
- SetBoundsInternal(bounds_); |
-} |
- |
-gfx::Rect PanelGtk::GetPanelBounds() const { |
- return bounds_; |
-} |
- |
-void PanelGtk::SetPanelBounds(const gfx::Rect& bounds) { |
- SetBoundsInternal(bounds); |
-} |
- |
-void PanelGtk::SetPanelBoundsInstantly(const gfx::Rect& bounds) { |
- SetBoundsInternal(bounds); |
-} |
- |
-void PanelGtk::SetBoundsInternal(const gfx::Rect& bounds) { |
- if (is_shown_) { |
- gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(window_)), |
- bounds.x(), bounds.y(), |
- bounds.width(), bounds.height()); |
- } |
- |
- bounds_ = bounds; |
- |
- titlebar_->SendEnterNotifyToCloseButtonIfUnderMouse(); |
- panel_->manager()->OnPanelAnimationEnded(panel_.get()); |
-} |
- |
-void PanelGtk::ClosePanel() { |
- // We're already closing. Do nothing. |
- if (!window_) |
- return; |
- |
- if (!panel_->ShouldCloseWindow()) |
- return; |
- |
- if (drag_helper_.get()) |
- drag_helper_.reset(); |
- |
- if (accel_group_) |
- DisconnectAccelerators(); |
- |
- // Cancel any pending callback from the loading animation timer. |
- loading_animation_timer_.Stop(); |
- |
- if (panel_->GetWebContents()) { |
- // Hide the window (so it appears to have closed immediately). |
- // When web contents are destroyed, we will be called back again. |
- gtk_widget_hide(GTK_WIDGET(window_)); |
- panel_->OnWindowClosing(); |
- return; |
- } |
- |
- 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; |
- |
- panel_->OnNativePanelClosed(); |
- |
- // We don't want GlobalMenuBar handling any notifications or commands after |
- // the window is destroyed. |
- // TODO(jennb): global_menu_bar_->Disable(); |
- gtk_widget_destroy(window); |
-} |
- |
-void PanelGtk::ActivatePanel() { |
- gtk_window_present(window_); |
- |
- // When the user clicks to expand the minimized panel, the panel has already |
- // become an active window before gtk_window_present is called. Thus the |
- // active window change event, fired by ActiveWindowWatcherXObserver, is not |
- // triggered. We need to call ActiveWindowChanged manually to update panel's |
- // active status. It is OK to call ActiveWindowChanged with the same active |
- // window twice since the 2nd call is just a no-op. |
- ActiveWindowChanged(gtk_widget_get_window(GTK_WIDGET(window_))); |
-} |
- |
-void PanelGtk::DeactivatePanel() { |
- // When a panel is deactivated, it should not be lowered to the bottom of the |
- // z-order. We could put it behind other panel window. |
- Panel* other_panel = NULL; |
- // First, try to pick the sibling panel in the same stack. |
- StackedPanelCollection* stack = panel_->stack(); |
- if (stack && stack->num_panels()) { |
- other_panel = panel_ != stack->top_panel() ? stack->top_panel() |
- : stack->bottom_panel(); |
- } |
- // Then, try to pick other detached or stacked panel. |
- if (!other_panel) { |
- std::vector<Panel*> panels = |
- panel_->manager()->GetDetachedAndStackedPanels(); |
- if (!panels.empty()) |
- other_panel = panel_ != panels.front() ? panels.front() : panels.back(); |
- } |
- |
- gdk_window_restack( |
- gtk_widget_get_window(GTK_WIDGET(window_)), |
- other_panel ? gtk_widget_get_window( |
- GTK_WIDGET(other_panel->GetNativeWindow())) : NULL, |
- false); |
- |
- // Per ICCCM: http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7 |
- // A convention is also required for clients that want to give up the |
- // input focus. There is no safe value set for them to set the input |
- // focus to; therefore, they should ignore input material. |
- // |
- // No way to deactive a GTK window. Pretend panel is deactivated |
- // and ignore input. |
- ActiveWindowChanged(NULL); |
-} |
- |
-bool PanelGtk::IsPanelActive() const { |
- return is_active_; |
-} |
- |
-void PanelGtk::PreventActivationByOS(bool prevent_activation) { |
- gtk_window_set_accept_focus(window_, !prevent_activation); |
-} |
- |
-gfx::NativeWindow PanelGtk::GetNativePanelWindow() { |
- return window_; |
-} |
- |
-void PanelGtk::UpdatePanelTitleBar() { |
- TRACE_EVENT0("ui::gtk", "PanelGtk::UpdatePanelTitleBar"); |
- base::string16 title = panel_->GetWindowTitle(); |
- gtk_window_set_title(window_, base::UTF16ToUTF8(title).c_str()); |
- titlebar_->UpdateTitleAndIcon(); |
- |
- gfx::Image app_icon = panel_->app_icon(); |
- if (!app_icon.IsEmpty()) |
- gtk_util::SetWindowIcon(window_, panel_->profile(), app_icon.ToGdkPixbuf()); |
-} |
- |
-void PanelGtk::UpdatePanelLoadingAnimations(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, |
- &PanelGtk::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 PanelGtk::LoadingAnimationCallback() { |
- titlebar_->UpdateThrobber(panel_->GetWebContents()); |
-} |
- |
-void PanelGtk::PanelWebContentsFocused(content::WebContents* contents) { |
- // Nothing to do. |
-} |
- |
-void PanelGtk::PanelCut() { |
- gtk_window_util::DoCut(window_, panel_->GetWebContents()); |
-} |
- |
-void PanelGtk::PanelCopy() { |
- gtk_window_util::DoCopy(window_, panel_->GetWebContents()); |
-} |
- |
-void PanelGtk::PanelPaste() { |
- gtk_window_util::DoPaste(window_, panel_->GetWebContents()); |
-} |
- |
-void PanelGtk::DrawAttention(bool draw_attention) { |
- DCHECK((panel_->attention_mode() & Panel::USE_PANEL_ATTENTION) != 0); |
- |
- if (is_drawing_attention_ == draw_attention) |
- return; |
- |
- is_drawing_attention_ = draw_attention; |
- |
- titlebar_->UpdateTextColor(); |
- InvalidateWindow(); |
- |
- if ((panel_->attention_mode() & Panel::USE_SYSTEM_ATTENTION) != 0) { |
- // May not be respected by all window managers. |
- gtk_window_set_urgency_hint(window_, draw_attention); |
- } |
-} |
- |
-bool PanelGtk::IsDrawingAttention() const { |
- return is_drawing_attention_; |
-} |
- |
-void PanelGtk::HandlePanelKeyboardEvent( |
- const NativeWebKeyboardEvent& event) { |
- GdkEventKey* os_event = &event.os_event->key; |
- if (os_event && event.type == blink::WebInputEvent::RawKeyDown) |
- gtk_window_activate_key(window_, os_event); |
-} |
- |
-void PanelGtk::FullScreenModeChanged(bool is_full_screen) { |
- // No need to hide panels when entering the full-screen mode because the |
- // full-screen window will automatically be placed above all other windows. |
- if (is_full_screen) |
- return; |
- |
- // Show the panel if not yet when leaving the full-screen mode. This is |
- // because the panel is not shown when it is being created under full-screen |
- // mode. |
- GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_)); |
- if (!GDK_IS_WINDOW(gdk_window) || !gdk_window_is_visible(gdk_window)) |
- ShowPanelInactive(); |
-} |
- |
-void PanelGtk::PanelExpansionStateChanging( |
- Panel::ExpansionState old_state, Panel::ExpansionState new_state) { |
-} |
- |
-void PanelGtk::AttachWebContents(content::WebContents* contents) { |
- if (!contents) |
- return; |
- gfx::NativeView widget = contents->GetView()->GetNativeView(); |
- if (widget) { |
- gtk_container_add(GTK_CONTAINER(contents_expanded_), widget); |
- gtk_widget_show(widget); |
- contents->WasShown(); |
- } |
-} |
- |
-void PanelGtk::DetachWebContents(content::WebContents* contents) { |
- gfx::NativeView widget = contents->GetView()->GetNativeView(); |
- if (widget) { |
- GtkWidget* parent = gtk_widget_get_parent(widget); |
- if (parent) { |
- DCHECK_EQ(parent, contents_expanded_); |
- gtk_container_remove(GTK_CONTAINER(contents_expanded_), widget); |
- } |
- } |
-} |
- |
-gfx::Size PanelGtk::WindowSizeFromContentSize( |
- const gfx::Size& content_size) const { |
- gfx::Size& frame_size = GetFrameSize(); |
- return gfx::Size(content_size.width() + frame_size.width(), |
- content_size.height() + frame_size.height()); |
-} |
- |
-gfx::Size PanelGtk::ContentSizeFromWindowSize( |
- const gfx::Size& window_size) const { |
- gfx::Size& frame_size = GetFrameSize(); |
- return gfx::Size(window_size.width() - frame_size.width(), |
- window_size.height() - frame_size.height()); |
-} |
- |
-int PanelGtk::TitleOnlyHeight() const { |
- gfx::Size& frame_size = GetFrameSize(); |
- if (!frame_size.IsEmpty()) |
- return panel::kTitlebarHeight; |
- |
- NOTREACHED() << "Checking title height before window allocated"; |
- return 0; |
-} |
- |
-bool PanelGtk::IsPanelAlwaysOnTop() const { |
- return always_on_top_; |
-} |
- |
-void PanelGtk::SetPanelAlwaysOnTop(bool on_top) { |
- always_on_top_ = on_top; |
- |
- gtk_window_set_keep_above(window_, on_top); |
- |
- // Do not show an icon in the task bar for always-on-top windows. |
- // Window operations such as close, minimize etc. can only be done |
- // from the panel UI. |
- gtk_window_set_skip_taskbar_hint(window_, on_top); |
- |
- // Show always-on-top windows on all the virtual desktops. |
- if (on_top) |
- gtk_window_stick(window_); |
- else |
- gtk_window_unstick(window_); |
-} |
- |
-void PanelGtk::UpdatePanelMinimizeRestoreButtonVisibility() { |
- titlebar_->UpdateMinimizeRestoreButtonVisibility(); |
-} |
- |
-gfx::Size PanelGtk::GetNonClientFrameSize() const { |
- GtkAllocation window_allocation; |
- gtk_widget_get_allocation(window_container_, &window_allocation); |
- GtkAllocation contents_allocation; |
- gtk_widget_get_allocation(contents_expanded_, &contents_allocation); |
- return gfx::Size(window_allocation.width - contents_allocation.width, |
- window_allocation.height - contents_allocation.height); |
-} |
- |
-void PanelGtk::InvalidateWindow() { |
- GtkAllocation allocation; |
- gtk_widget_get_allocation(GTK_WIDGET(window_), &allocation); |
- gdk_window_invalidate_rect(gtk_widget_get_window(GTK_WIDGET(window_)), |
- &allocation, TRUE); |
-} |
- |
-// NativePanelTesting implementation. |
-class GtkNativePanelTesting : public NativePanelTesting { |
- public: |
- explicit GtkNativePanelTesting(PanelGtk* panel_gtk); |
- |
- private: |
- virtual void PressLeftMouseButtonTitlebar( |
- const gfx::Point& mouse_location, panel::ClickModifier modifier) OVERRIDE; |
- virtual void ReleaseMouseButtonTitlebar( |
- panel::ClickModifier modifier) OVERRIDE; |
- virtual void DragTitlebar(const gfx::Point& mouse_location) OVERRIDE; |
- virtual void CancelDragTitlebar() OVERRIDE; |
- virtual void FinishDragTitlebar() OVERRIDE; |
- virtual bool VerifyDrawingAttention() const OVERRIDE; |
- virtual bool VerifyActiveState(bool is_active) OVERRIDE; |
- virtual bool VerifyAppIcon() const OVERRIDE; |
- virtual bool VerifySystemMinimizeState() const OVERRIDE; |
- virtual bool IsWindowVisible() const OVERRIDE; |
- virtual bool IsWindowSizeKnown() const OVERRIDE; |
- virtual bool IsAnimatingBounds() const OVERRIDE; |
- virtual bool IsButtonVisible( |
- panel::TitlebarButtonType button_type) const OVERRIDE; |
- virtual panel::CornerStyle GetWindowCornerStyle() const OVERRIDE; |
- virtual bool EnsureApplicationRunOnForeground() OVERRIDE; |
- |
- PanelGtk* panel_gtk_; |
-}; |
- |
-NativePanelTesting* PanelGtk::CreateNativePanelTesting() { |
- return new GtkNativePanelTesting(this); |
-} |
- |
-GtkNativePanelTesting::GtkNativePanelTesting(PanelGtk* panel_gtk) |
- : panel_gtk_(panel_gtk) { |
-} |
- |
-void GtkNativePanelTesting::PressLeftMouseButtonTitlebar( |
- const gfx::Point& mouse_location, panel::ClickModifier modifier) { |
- |
- GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); |
- event->button.button = 1; |
- event->button.x_root = mouse_location.x(); |
- event->button.y_root = mouse_location.y(); |
- if (modifier == panel::APPLY_TO_ALL) |
- event->button.state |= GDK_CONTROL_MASK; |
- panel_gtk_->OnTitlebarButtonPressEvent( |
- NULL, reinterpret_cast<GdkEventButton*>(event)); |
- gdk_event_free(event); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
-} |
- |
-void GtkNativePanelTesting::ReleaseMouseButtonTitlebar( |
- panel::ClickModifier modifier) { |
- GdkEvent* event = gdk_event_new(GDK_BUTTON_RELEASE); |
- event->button.button = 1; |
- if (modifier == panel::APPLY_TO_ALL) |
- event->button.state |= GDK_CONTROL_MASK; |
- if (panel_gtk_->drag_helper_.get()) { |
- panel_gtk_->drag_helper_->OnButtonReleaseEvent( |
- NULL, reinterpret_cast<GdkEventButton*>(event)); |
- } else { |
- panel_gtk_->OnTitlebarButtonReleaseEvent( |
- NULL, reinterpret_cast<GdkEventButton*>(event)); |
- } |
- gdk_event_free(event); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
-} |
- |
-void GtkNativePanelTesting::DragTitlebar(const gfx::Point& mouse_location) { |
- if (!panel_gtk_->drag_helper_.get()) |
- return; |
- GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY); |
- event->motion.x_root = mouse_location.x(); |
- event->motion.y_root = mouse_location.y(); |
- panel_gtk_->drag_helper_->OnMouseMoveEvent( |
- NULL, reinterpret_cast<GdkEventMotion*>(event)); |
- gdk_event_free(event); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
-} |
- |
-void GtkNativePanelTesting::CancelDragTitlebar() { |
- if (!panel_gtk_->drag_helper_.get()) |
- return; |
- panel_gtk_->drag_helper_->OnGrabBrokenEvent(NULL, NULL); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
-} |
- |
-void GtkNativePanelTesting::FinishDragTitlebar() { |
- if (!panel_gtk_->drag_helper_.get()) |
- return; |
- ReleaseMouseButtonTitlebar(panel::NO_MODIFIER); |
-} |
- |
-bool GtkNativePanelTesting::VerifyDrawingAttention() const { |
- return panel_gtk_->IsDrawingAttention(); |
-} |
- |
-bool GtkNativePanelTesting::VerifyActiveState(bool is_active) { |
- return gtk_window_is_active(panel_gtk_->GetNativePanelWindow()) == is_active; |
-} |
- |
-bool GtkNativePanelTesting::VerifyAppIcon() const { |
- GdkPixbuf* icon = gtk_window_get_icon(panel_gtk_->GetNativePanelWindow()); |
- return icon && |
- gdk_pixbuf_get_width(icon) == panel::kPanelAppIconSize && |
- gdk_pixbuf_get_height(icon) == panel::kPanelAppIconSize; |
-} |
- |
-bool GtkNativePanelTesting::VerifySystemMinimizeState() const { |
- // TODO(jianli): to be implemented. |
- return true; |
-} |
- |
-bool GtkNativePanelTesting::IsWindowVisible() const { |
- GdkWindow* gdk_window = |
- gtk_widget_get_window(GTK_WIDGET(panel_gtk_->GetNativePanelWindow())); |
- return GDK_IS_WINDOW(gdk_window) && gdk_window_is_visible(gdk_window); |
-} |
- |
-bool GtkNativePanelTesting::IsWindowSizeKnown() const { |
- return !GetFrameSize().IsEmpty(); |
-} |
- |
-bool GtkNativePanelTesting::IsAnimatingBounds() const { |
- return false; |
-} |
- |
-bool GtkNativePanelTesting::IsButtonVisible( |
- panel::TitlebarButtonType button_type) const { |
- PanelTitlebarGtk* titlebar = panel_gtk_->titlebar(); |
- CustomDrawButton* button; |
- switch (button_type) { |
- case panel::CLOSE_BUTTON: |
- button = titlebar->close_button(); |
- break; |
- case panel::MINIMIZE_BUTTON: |
- button = titlebar->minimize_button(); |
- break; |
- case panel::RESTORE_BUTTON: |
- button = titlebar->restore_button(); |
- break; |
- default: |
- NOTREACHED(); |
- return false; |
- } |
- return gtk_widget_get_visible(button->widget()); |
-} |
- |
-panel::CornerStyle GtkNativePanelTesting::GetWindowCornerStyle() const { |
- return panel_gtk_->corner_style_; |
-} |
- |
-bool GtkNativePanelTesting::EnsureApplicationRunOnForeground() { |
- // Not needed on GTK. |
- return true; |
-} |