| Index: chrome/browser/ui/gtk/apps/native_app_window_gtk.cc
|
| diff --git a/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc b/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc
|
| deleted file mode 100644
|
| index f2d301b7ed17153456dec01cecba9ed5f83bb885..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc
|
| +++ /dev/null
|
| @@ -1,760 +0,0 @@
|
| -// Copyright 2013 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/apps/native_app_window_gtk.h"
|
| -
|
| -#include <gdk/gdkx.h>
|
| -#include <vector>
|
| -
|
| -#include "base/message_loop/message_pump_gtk.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "chrome/browser/profiles/profile.h"
|
| -#include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
|
| -#include "chrome/browser/ui/gtk/gtk_util.h"
|
| -#include "chrome/browser/ui/gtk/gtk_window_util.h"
|
| -#include "chrome/browser/web_applications/web_app.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 "extensions/common/extension.h"
|
| -#include "ui/base/x/active_window_watcher_x.h"
|
| -#include "ui/gfx/gtk_util.h"
|
| -#include "ui/gfx/image/image.h"
|
| -#include "ui/gfx/rect.h"
|
| -
|
| -using apps::AppWindow;
|
| -
|
| -namespace {
|
| -
|
| -// 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;
|
| -
|
| -const char* kAtomsToCache[] = {
|
| - "_NET_WM_STATE",
|
| - "_NET_WM_STATE_HIDDEN",
|
| - NULL
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -NativeAppWindowGtk::NativeAppWindowGtk(AppWindow* app_window,
|
| - const AppWindow::CreateParams& params)
|
| - : app_window_(app_window),
|
| - window_(NULL),
|
| - state_(GDK_WINDOW_STATE_WITHDRAWN),
|
| - is_active_(false),
|
| - content_thinks_its_fullscreen_(false),
|
| - maximize_pending_(false),
|
| - frameless_(params.frame == AppWindow::FRAME_NONE),
|
| - always_on_top_(params.always_on_top),
|
| - frame_cursor_(NULL),
|
| - atom_cache_(base::MessagePumpGtk::GetDefaultXDisplay(), kAtomsToCache),
|
| - is_x_event_listened_(false) {
|
| - Observe(web_contents());
|
| -
|
| - window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
|
| -
|
| - gfx::NativeView native_view =
|
| - web_contents()->GetView()->GetNativeView();
|
| - gtk_container_add(GTK_CONTAINER(window_), native_view);
|
| -
|
| - gfx::Insets frame_insets = GetFrameInsets();
|
| - gfx::Rect initial_bounds = params.GetInitialWindowBounds(frame_insets);
|
| -
|
| - typedef apps::AppWindow::BoundsSpecification BoundsSpecification;
|
| - if (initial_bounds.x() != BoundsSpecification::kUnspecifiedPosition &&
|
| - initial_bounds.y() != BoundsSpecification::kUnspecifiedPosition) {
|
| - gtk_window_move(window_, initial_bounds.x(), initial_bounds.y());
|
| - }
|
| -
|
| - // This is done to avoid a WM "feature" where setting the window size to
|
| - // the monitor size causes the WM to set the EWMH for full screen mode.
|
| - int win_height = initial_bounds.height();
|
| - if (frameless_ &&
|
| - gtk_window_util::BoundsMatchMonitorSize(window_, initial_bounds)) {
|
| - win_height -= 1;
|
| - }
|
| - gtk_window_set_default_size(window_, initial_bounds.width(), win_height);
|
| -
|
| - resizable_ = params.resizable;
|
| - if (!resizable_) {
|
| - // If the window doesn't have a size request when we set resizable to
|
| - // false, GTK will shrink the window to 1x1px.
|
| - gtk_widget_set_size_request(GTK_WIDGET(window_),
|
| - initial_bounds.width(), win_height);
|
| - gtk_window_set_resizable(window_, FALSE);
|
| - }
|
| -
|
| - // make sure bounds_ and restored_bounds_ have correct values until we
|
| - // get our first configure-event
|
| - bounds_ = restored_bounds_ = initial_bounds;
|
| - gint x, y;
|
| - gtk_window_get_position(window_, &x, &y);
|
| - bounds_.set_origin(gfx::Point(x, y));
|
| -
|
| - // Hide titlebar when {frame: 'none'} specified on AppWindow..
|
| - if (frameless_)
|
| - gtk_window_set_decorated(window_, false);
|
| -
|
| - if (always_on_top_)
|
| - gtk_window_set_keep_above(window_, TRUE);
|
| -
|
| - SetContentSizeConstraints(params.GetContentMinimumSize(frame_insets),
|
| - params.GetContentMaximumSize(frame_insets));
|
| -
|
| - // 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;
|
| -
|
| - gtk_window_set_title(window_, extension()->name().c_str());
|
| -
|
| - std::string app_name = web_app::GenerateApplicationNameFromExtensionId(
|
| - extension()->id());
|
| - gtk_window_util::SetWindowCustomClass(window_,
|
| - web_app::GetWMClassFromAppName(app_name));
|
| -
|
| - g_signal_connect(window_, "delete-event",
|
| - G_CALLBACK(OnMainWindowDeleteEventThunk), this);
|
| - g_signal_connect(window_, "configure-event",
|
| - G_CALLBACK(OnConfigureThunk), this);
|
| - g_signal_connect(window_, "window-state-event",
|
| - G_CALLBACK(OnWindowStateThunk), this);
|
| - if (frameless_) {
|
| - g_signal_connect(window_, "button-press-event",
|
| - G_CALLBACK(OnButtonPressThunk), this);
|
| - g_signal_connect(window_, "motion-notify-event",
|
| - G_CALLBACK(OnMouseMoveEventThunk), this);
|
| - }
|
| -
|
| - // If _NET_WM_STATE_HIDDEN is in _NET_SUPPORTED, listen for XEvent to work
|
| - // around GTK+ not reporting minimization state changes. See comment in the
|
| - // |OnXEvent|.
|
| - std::vector< ::Atom> supported_atoms;
|
| - if (ui::GetAtomArrayProperty(ui::GetX11RootWindow(),
|
| - "_NET_SUPPORTED",
|
| - &supported_atoms)) {
|
| - if (std::find(supported_atoms.begin(),
|
| - supported_atoms.end(),
|
| - atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN")) !=
|
| - supported_atoms.end()) {
|
| - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(window_));
|
| - gdk_window_add_filter(window,
|
| - &NativeAppWindowGtk::OnXEventThunk,
|
| - this);
|
| - is_x_event_listened_ = true;
|
| - }
|
| - }
|
| -
|
| - // Add the keybinding registry.
|
| - extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
|
| - Profile::FromBrowserContext(app_window_->browser_context()),
|
| - window_,
|
| - extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
|
| - NULL));
|
| -
|
| - ui::ActiveWindowWatcherX::AddObserver(this);
|
| -}
|
| -
|
| -NativeAppWindowGtk::~NativeAppWindowGtk() {
|
| - ui::ActiveWindowWatcherX::RemoveObserver(this);
|
| - if (is_x_event_listened_) {
|
| - gdk_window_remove_filter(NULL,
|
| - &NativeAppWindowGtk::OnXEventThunk,
|
| - this);
|
| - }
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsActive() const {
|
| - if (ui::ActiveWindowWatcherX::WMSupportsActivation())
|
| - return is_active_;
|
| -
|
| - // This still works even though we don't get the activation notification.
|
| - return gtk_window_is_active(window_);
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsMaximized() const {
|
| - return (state_ & GDK_WINDOW_STATE_MAXIMIZED);
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsMinimized() const {
|
| - return (state_ & GDK_WINDOW_STATE_ICONIFIED);
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsFullscreen() const {
|
| - return (state_ & GDK_WINDOW_STATE_FULLSCREEN);
|
| -}
|
| -
|
| -gfx::NativeWindow NativeAppWindowGtk::GetNativeWindow() {
|
| - return window_;
|
| -}
|
| -
|
| -gfx::Rect NativeAppWindowGtk::GetRestoredBounds() const {
|
| - gfx::Rect window_bounds = restored_bounds_;
|
| - window_bounds.Inset(-GetFrameInsets());
|
| - return window_bounds;
|
| -}
|
| -
|
| -ui::WindowShowState NativeAppWindowGtk::GetRestoredState() const {
|
| - if (IsMaximized())
|
| - return ui::SHOW_STATE_MAXIMIZED;
|
| - if (IsFullscreen())
|
| - return ui::SHOW_STATE_FULLSCREEN;
|
| - return ui::SHOW_STATE_NORMAL;
|
| -}
|
| -
|
| -gfx::Rect NativeAppWindowGtk::GetBounds() const {
|
| - // :GetBounds() is expecting the outer window bounds to be returned (ie.
|
| - // including window decorations). The internal |bounds_| is not including them
|
| - // and trying to add the decoration to |bounds_| would require calling
|
| - // gdk_window_get_frame_extents. The best thing to do is to directly get the
|
| - // frame bounds and only use the internal value if we can't.
|
| - GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
|
| - if (!gdk_window)
|
| - return bounds_;
|
| -
|
| - GdkRectangle window_bounds = {0};
|
| - gdk_window_get_frame_extents(gdk_window, &window_bounds);
|
| - return gfx::Rect(window_bounds.x, window_bounds.y,
|
| - window_bounds.width, window_bounds.height);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Show() {
|
| - gtk_window_present(window_);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::ShowInactive() {
|
| - gtk_window_set_focus_on_map(window_, false);
|
| - gtk_widget_show(GTK_WIDGET(window_));
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Hide() {
|
| - gtk_widget_hide(GTK_WIDGET(window_));
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Close() {
|
| - app_window_->OnNativeWindowChanged();
|
| -
|
| - // Cancel any pending callback from the window configure debounce timer.
|
| - window_configure_debounce_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;
|
| -
|
| - // OnNativeClose does a delete this so no other members should
|
| - // be accessed after. gtk_widget_destroy is safe (and must
|
| - // be last).
|
| - app_window_->OnNativeClose();
|
| - gtk_widget_destroy(window);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Activate() {
|
| - gtk_window_present(window_);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Deactivate() {
|
| - gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Maximize() {
|
| - // Represent the window first in order to keep the maximization behavior
|
| - // consistency with Windows platform. Otherwise the window will be hidden if
|
| - // it has been minimized.
|
| - gtk_window_present(window_);
|
| -
|
| - if (!resizable_) {
|
| - // When the window is not resizable, we still want to make this call succeed
|
| - // but gtk will not allow it if the window is not resizable. The actual
|
| - // maximization will happen with the subsequent OnConfigureDebounced call,
|
| - // that will be triggered when the window manager's resizable property
|
| - // changes.
|
| - maximize_pending_ = true;
|
| - gtk_window_set_resizable(window_, TRUE);
|
| - } else {
|
| - gtk_window_maximize(window_);
|
| - }
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Minimize() {
|
| - gtk_window_iconify(window_);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::Restore() {
|
| - if (IsMaximized())
|
| - gtk_window_unmaximize(window_);
|
| - else if (IsMinimized())
|
| - gtk_window_deiconify(window_);
|
| -
|
| - // Represent the window to keep restoration behavior consistency with Windows
|
| - // platform.
|
| - // TODO(zhchbin): verify whether we need this until http://crbug.com/261013 is
|
| - // fixed.
|
| - gtk_window_present(window_);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
|
| - gfx::Rect content_bounds = bounds;
|
| - gtk_window_move(window_, content_bounds.x(), content_bounds.y());
|
| - if (!resizable_) {
|
| - if (frameless_ &&
|
| - gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) {
|
| - content_bounds.set_height(content_bounds.height() - 1);
|
| - }
|
| - // TODO(jeremya): set_size_request doesn't honor min/max size, so the
|
| - // bounds should be constrained manually.
|
| - gtk_widget_set_size_request(GTK_WIDGET(window_),
|
| - content_bounds.width(), content_bounds.height());
|
| - } else {
|
| - gtk_window_util::SetWindowSize(window_,
|
| - gfx::Size(bounds.width(), bounds.height()));
|
| - }
|
| -}
|
| -
|
| -GdkFilterReturn NativeAppWindowGtk::OnXEvent(GdkXEvent* gdk_x_event,
|
| - GdkEvent* gdk_event) {
|
| - // Work around GTK+ not reporting minimization state changes. Listen
|
| - // for _NET_WM_STATE property changes and use _NET_WM_STATE_HIDDEN's
|
| - // presence to set or clear the iconified bit if _NET_WM_STATE_HIDDEN
|
| - // is supported. http://crbug.com/162794.
|
| - XEvent* x_event = static_cast<XEvent*>(gdk_x_event);
|
| - std::vector< ::Atom> atom_list;
|
| -
|
| - if (x_event->type == PropertyNotify &&
|
| - x_event->xproperty.atom == atom_cache_.GetAtom("_NET_WM_STATE") &&
|
| - GTK_WIDGET(window_)->window &&
|
| - ui::GetAtomArrayProperty(GDK_WINDOW_XWINDOW(GTK_WIDGET(window_)->window),
|
| - "_NET_WM_STATE",
|
| - &atom_list)) {
|
| - std::vector< ::Atom>::iterator it =
|
| - std::find(atom_list.begin(),
|
| - atom_list.end(),
|
| - atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN"));
|
| -
|
| - GdkWindowState previous_state = state_;
|
| - state_ = (it != atom_list.end()) ? GDK_WINDOW_STATE_ICONIFIED :
|
| - static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);
|
| -
|
| - if (previous_state != state_) {
|
| - app_window_->OnNativeWindowChanged();
|
| - }
|
| - }
|
| -
|
| - return GDK_FILTER_CONTINUE;
|
| -}
|
| -
|
| -void NativeAppWindowGtk::FlashFrame(bool flash) {
|
| - gtk_window_set_urgency_hint(window_, flash);
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsAlwaysOnTop() const {
|
| - return always_on_top_;
|
| -}
|
| -
|
| -void NativeAppWindowGtk::RenderViewHostChanged(
|
| - content::RenderViewHost* old_host,
|
| - content::RenderViewHost* new_host) {
|
| - web_contents()->GetView()->Focus();
|
| -}
|
| -
|
| -void NativeAppWindowGtk::SetAlwaysOnTop(bool always_on_top) {
|
| - if (always_on_top_ != always_on_top) {
|
| - // gdk_window_get_state() does not give us the correct value for the
|
| - // GDK_WINDOW_STATE_ABOVE bit. Cache the current state.
|
| - always_on_top_ = always_on_top;
|
| - gtk_window_set_keep_above(window_, always_on_top_ ? TRUE : FALSE);
|
| - }
|
| -}
|
| -
|
| -gfx::NativeView NativeAppWindowGtk::GetHostView() const {
|
| - NOTIMPLEMENTED();
|
| - return NULL;
|
| -}
|
| -
|
| -gfx::Point NativeAppWindowGtk::GetDialogPosition(const gfx::Size& size) {
|
| - gint current_width = 0;
|
| - gint current_height = 0;
|
| - gtk_window_get_size(window_, ¤t_width, ¤t_height);
|
| - return gfx::Point(current_width / 2 - size.width() / 2,
|
| - current_height / 2 - size.height() / 2);
|
| -}
|
| -
|
| -gfx::Size NativeAppWindowGtk::GetMaximumDialogSize() {
|
| - gint current_width = 0;
|
| - gint current_height = 0;
|
| - gtk_window_get_size(window_, ¤t_width, ¤t_height);
|
| - return gfx::Size(current_width, current_height);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::AddObserver(
|
| - web_modal::ModalDialogHostObserver* observer) {
|
| - observer_list_.AddObserver(observer);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::RemoveObserver(
|
| - web_modal::ModalDialogHostObserver* observer) {
|
| - observer_list_.RemoveObserver(observer);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
|
| - // Do nothing if we're in the process of closing the browser window.
|
| - if (!window_)
|
| - return;
|
| -
|
| - is_active_ = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window;
|
| - if (is_active_)
|
| - app_window_->OnNativeWindowActivated();
|
| -}
|
| -
|
| -// 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 NativeAppWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget,
|
| - GdkEvent* event) {
|
| - Close();
|
| -
|
| - // Return true to prevent the GTK window from being destroyed. Close will
|
| - // destroy it for us.
|
| - return TRUE;
|
| -}
|
| -
|
| -gboolean NativeAppWindowGtk::OnConfigure(GtkWidget* widget,
|
| - GdkEventConfigure* event) {
|
| - // 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_.SetRect(event->x, event->y, event->width, event->height);
|
| -
|
| - // 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 OnConfigureDebounced() 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,
|
| - &NativeAppWindowGtk::OnConfigureDebounced);
|
| -
|
| - return FALSE;
|
| -}
|
| -
|
| -void NativeAppWindowGtk::OnConfigureDebounced() {
|
| - gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_);
|
| - app_window_->OnNativeWindowChanged();
|
| -
|
| - FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver,
|
| - observer_list_,
|
| - OnPositionRequiresUpdate());
|
| -
|
| - // Fullscreen of non-resizable windows requires them to be made resizable
|
| - // first. After that takes effect and OnConfigure is called we transition
|
| - // to fullscreen.
|
| - if (!IsFullscreen() && IsFullscreenOrPending()) {
|
| - gtk_window_fullscreen(window_);
|
| - }
|
| -
|
| - // maximize_pending_ is the boolean that lets us know that the window is in
|
| - // the process of being maximized but was set as not resizable.
|
| - // This function will be called twice during the maximization process:
|
| - // 1. gtk_window_maximize() is called to maximize the window;
|
| - // 2. gtk_set_resizable(, FALSE) is called to make the window no longer
|
| - // resizable.
|
| - // gtk_window_maximize() will cause ::OnConfigureDebounced to be called
|
| - // again, at which time we will run into the second step.
|
| - if (maximize_pending_) {
|
| - if (!(state_ & GDK_WINDOW_STATE_MAXIMIZED)) {
|
| - gtk_window_maximize(window_);
|
| - } else {
|
| - maximize_pending_ = false;
|
| - if (!resizable_)
|
| - gtk_window_set_resizable(window_, FALSE);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void NativeAppWindowGtk::UpdateContentMinMaxSize() {
|
| - GdkGeometry hints;
|
| - int hints_mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
| -
|
| - gfx::Size min_size = size_constraints_.GetMinimumSize();
|
| - hints.min_height = min_size.height();
|
| - hints.min_width = min_size.width();
|
| -
|
| - gfx::Size max_size = size_constraints_.GetMaximumSize();
|
| - const int kUnboundedSize = apps::SizeConstraints::kUnboundedSize;
|
| - hints.max_height = max_size.height() == kUnboundedSize ?
|
| - G_MAXINT : max_size.height();
|
| - hints.max_width = max_size.width() == kUnboundedSize ?
|
| - G_MAXINT : max_size.width();
|
| -
|
| - gtk_window_set_geometry_hints(
|
| - window_,
|
| - GTK_WIDGET(window_),
|
| - &hints,
|
| - static_cast<GdkWindowHints>(hints_mask));
|
| -}
|
| -
|
| -gboolean NativeAppWindowGtk::OnWindowState(GtkWidget* sender,
|
| - GdkEventWindowState* event) {
|
| - state_ = event->new_window_state;
|
| -
|
| - if (content_thinks_its_fullscreen_ &&
|
| - !(state_ & GDK_WINDOW_STATE_FULLSCREEN)) {
|
| - content_thinks_its_fullscreen_ = false;
|
| - content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
|
| - if (rvh)
|
| - rvh->ExitFullscreen();
|
| - }
|
| -
|
| - return FALSE;
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) {
|
| - if (!frameless_)
|
| - return false;
|
| -
|
| - if (IsMaximized() || IsFullscreen())
|
| - return false;
|
| -
|
| - return gtk_window_util::GetWindowEdge(bounds_.size(), 0, x, y, edge);
|
| -}
|
| -
|
| -gboolean NativeAppWindowGtk::OnMouseMoveEvent(GtkWidget* widget,
|
| - GdkEventMotion* event) {
|
| - if (!frameless_) {
|
| - // Reset the cursor.
|
| - if (frame_cursor_) {
|
| - frame_cursor_ = NULL;
|
| - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(window_)), NULL);
|
| - }
|
| - return FALSE;
|
| - }
|
| -
|
| - if (!resizable_)
|
| - 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) {
|
| - 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 NativeAppWindowGtk::OnButtonPress(GtkWidget* widget,
|
| - GdkEventButton* event) {
|
| - DCHECK(frameless_);
|
| - // 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 = resizable_ && GetWindowEdge(point.x(), point.y(), &edge);
|
| - bool has_hit_titlebar =
|
| - draggable_region_ && draggable_region_->contains(event->x, event->y);
|
| -
|
| - 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(GTK_WIDGET(widget)->window);
|
| -
|
| - 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 (has_hit_titlebar) {
|
| - return gtk_window_util::HandleTitleBarLeftMousePress(
|
| - window_, bounds_, event);
|
| - }
|
| - } else if (GDK_2BUTTON_PRESS == event->type) {
|
| - if (has_hit_titlebar && resizable_) {
|
| - // Maximize/restore on double click.
|
| - if (IsMaximized()) {
|
| - gtk_window_util::UnMaximize(GTK_WINDOW(widget),
|
| - bounds_, restored_bounds_);
|
| - } 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;
|
| - }
|
| -
|
| - return FALSE;
|
| -}
|
| -
|
| -// NativeAppWindow implementation:
|
| -
|
| -void NativeAppWindowGtk::SetFullscreen(int fullscreen_types) {
|
| - bool fullscreen = (fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE);
|
| - content_thinks_its_fullscreen_ = fullscreen;
|
| - if (fullscreen) {
|
| - if (resizable_) {
|
| - gtk_window_fullscreen(window_);
|
| - } else {
|
| - // We must first make the window resizable. That won't take effect
|
| - // immediately, so OnConfigureDebounced completes the fullscreen call.
|
| - gtk_window_set_resizable(window_, TRUE);
|
| - }
|
| - } else {
|
| - gtk_window_unfullscreen(window_);
|
| - if (!resizable_)
|
| - gtk_window_set_resizable(window_, FALSE);
|
| - }
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsFullscreenOrPending() const {
|
| - // |content_thinks_its_fullscreen_| is used when transitioning, and when
|
| - // the state change will not be made for some time. However, it is possible
|
| - // for a state update to be made before the final fullscreen state comes.
|
| - // In that case, |content_thinks_its_fullscreen_| will be cleared, but we
|
| - // will fall back to |IsFullscreen| which will soon have the correct state.
|
| - return content_thinks_its_fullscreen_ || IsFullscreen();
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsDetached() const {
|
| - return false;
|
| -}
|
| -
|
| -void NativeAppWindowGtk::UpdateWindowIcon() {
|
| - Profile* profile =
|
| - Profile::FromBrowserContext(app_window_->browser_context());
|
| - gfx::Image app_icon = app_window_->app_icon();
|
| - if (!app_icon.IsEmpty())
|
| - gtk_util::SetWindowIcon(window_, profile, app_icon.ToGdkPixbuf());
|
| - else
|
| - gtk_util::SetWindowIcon(window_, profile);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::UpdateWindowTitle() {
|
| - base::string16 title = app_window_->GetTitle();
|
| - gtk_window_set_title(window_, base::UTF16ToUTF8(title).c_str());
|
| -}
|
| -
|
| -void NativeAppWindowGtk::UpdateBadgeIcon() {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void NativeAppWindowGtk::UpdateDraggableRegions(
|
| - const std::vector<extensions::DraggableRegion>& regions) {
|
| - // Draggable region is not supported for non-frameless window.
|
| - if (!frameless_)
|
| - return;
|
| -
|
| - draggable_region_.reset(AppWindow::RawDraggableRegionsToSkRegion(regions));
|
| -}
|
| -
|
| -SkRegion* NativeAppWindowGtk::GetDraggableRegion() {
|
| - return draggable_region_.get();
|
| -}
|
| -
|
| -void NativeAppWindowGtk::UpdateShape(scoped_ptr<SkRegion> region) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void NativeAppWindowGtk::HandleKeyboardEvent(
|
| - const content::NativeWebKeyboardEvent& event) {
|
| - // No-op.
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::IsFrameless() const {
|
| - return frameless_;
|
| -}
|
| -
|
| -bool NativeAppWindowGtk::HasFrameColor() const {
|
| - return false;
|
| -}
|
| -
|
| -SkColor NativeAppWindowGtk::FrameColor() const {
|
| - return SkColor();
|
| -}
|
| -
|
| -gfx::Insets NativeAppWindowGtk::GetFrameInsets() const {
|
| - if (frameless_)
|
| - return gfx::Insets();
|
| - GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
|
| - if (!gdk_window)
|
| - return gfx::Insets();
|
| -
|
| - gint current_width = 0;
|
| - gint current_height = 0;
|
| - gtk_window_get_size(window_, ¤t_width, ¤t_height);
|
| - gint current_x = 0;
|
| - gint current_y = 0;
|
| - gdk_window_get_position(gdk_window, ¤t_x, ¤t_y);
|
| - GdkRectangle rect_with_decorations = {0};
|
| - gdk_window_get_frame_extents(gdk_window,
|
| - &rect_with_decorations);
|
| -
|
| - int left_inset = current_x - rect_with_decorations.x;
|
| - int top_inset = current_y - rect_with_decorations.y;
|
| - return gfx::Insets(
|
| - top_inset,
|
| - left_inset,
|
| - rect_with_decorations.height - current_height - top_inset,
|
| - rect_with_decorations.width - current_width - left_inset);
|
| -}
|
| -
|
| -void NativeAppWindowGtk::HideWithApp() {}
|
| -void NativeAppWindowGtk::ShowWithApp() {}
|
| -
|
| -void NativeAppWindowGtk::UpdateShelfMenu() {
|
| - // TODO(tmdiep): To be implemented for GTK.
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -gfx::Size NativeAppWindowGtk::GetContentMinimumSize() const {
|
| - return size_constraints_.GetMinimumSize();
|
| -}
|
| -
|
| -gfx::Size NativeAppWindowGtk::GetContentMaximumSize() const {
|
| - return size_constraints_.GetMaximumSize();
|
| -}
|
| -
|
| -void NativeAppWindowGtk::SetContentSizeConstraints(
|
| - const gfx::Size& min_size, const gfx::Size& max_size) {
|
| - bool changed = size_constraints_.GetMinimumSize() != min_size ||
|
| - size_constraints_.GetMaximumSize() != max_size;
|
| - if (!changed)
|
| - return;
|
| -
|
| - size_constraints_.set_minimum_size(min_size);
|
| - size_constraints_.set_maximum_size(max_size);
|
| - UpdateContentMinMaxSize();
|
| -}
|
|
|