// 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 "chrome/common/extensions/extension.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 "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::ShellWindow;

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(ShellWindow* shell_window,
                                       const ShellWindow::CreateParams& params)
    : shell_window_(shell_window),
      window_(NULL),
      state_(GDK_WINDOW_STATE_WITHDRAWN),
      is_active_(false),
      content_thinks_its_fullscreen_(false),
      frameless_(params.frame == ShellWindow::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);

  if (params.bounds.x() != INT_MIN && params.bounds.y() != INT_MIN)
    gtk_window_move(window_, params.bounds.x(), params.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 = params.bounds.height();
  if (frameless_ &&
      gtk_window_util::BoundsMatchMonitorSize(window_, params.bounds)) {
    win_height -= 1;
  }
  gtk_window_set_default_size(window_, params.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_),
        params.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_ = params.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 ShellWindow.
  if (frameless_)
    gtk_window_set_decorated(window_, false);

  if (always_on_top_)
    gtk_window_set_keep_above(window_, TRUE);

  int min_width = params.minimum_size.width();
  int min_height = params.minimum_size.height();
  int max_width = params.maximum_size.width();
  int max_height = params.maximum_size.height();
  GdkGeometry hints;
  int hints_mask = 0;
  if (min_width || min_height) {
    hints.min_height = min_height;
    hints.min_width = min_width;
    hints_mask |= GDK_HINT_MIN_SIZE;
  }
  if (max_width || max_height) {
    hints.max_height = max_height ? max_height : G_MAXINT;
    hints.max_width = max_width ? max_width : G_MAXINT;
    hints_mask |= GDK_HINT_MAX_SIZE;
  }
  if (hints_mask) {
    gtk_window_set_geometry_hints(
        window_,
        GTK_WIDGET(window_),
        &hints,
        static_cast<GdkWindowHints>(hints_mask));
  }

  // 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(
      shell_window_->profile(),
      window_,
      extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
      shell_window_));

  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 {
  gfx::Rect window_bounds = bounds_;
  window_bounds.Inset(-GetFrameInsets());
  return window_bounds;
}

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() {
  shell_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).
  shell_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_);
  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;
  content_bounds.Inset(GetFrameInsets());
  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") &&
      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"));
    state_ = (it != atom_list.end()) ? GDK_WINDOW_STATE_ICONIFIED :
        static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);

    shell_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);
    shell_window_->OnNativeWindowChanged();
  }
}

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_, &current_width, &current_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_, &current_width, &current_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_)
    shell_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_);
  shell_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_);
  }
}

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();
  }

  shell_window_->OnNativeWindowChanged();

  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(bool fullscreen) {
  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 = shell_window_->profile();
  gfx::Image app_icon = shell_window_->app_icon();
  if (!app_icon.IsEmpty())
    gtk_util::SetWindowIcon(window_, profile, app_icon.ToGdkPixbuf());
  else
    gtk_util::SetWindowIcon(window_, profile);
}

void NativeAppWindowGtk::UpdateWindowTitle() {
  string16 title = shell_window_->GetTitle();
  gtk_window_set_title(window_, UTF16ToUTF8(title).c_str());
}

void NativeAppWindowGtk::UpdateDraggableRegions(
    const std::vector<extensions::DraggableRegion>& regions) {
  // Draggable region is not supported for non-frameless window.
  if (!frameless_)
    return;

  draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
}

SkRegion* NativeAppWindowGtk::GetDraggableRegion() {
  return draggable_region_.get();
}

void NativeAppWindowGtk::UpdateInputRegion(scoped_ptr<SkRegion> region) {
  NOTIMPLEMENTED();
}

void NativeAppWindowGtk::HandleKeyboardEvent(
    const content::NativeWebKeyboardEvent& event) {
  // No-op.
}

bool NativeAppWindowGtk::IsFrameless() const {
  return frameless_;
}

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_, &current_width, &current_height);
  gint current_x = 0;
  gint current_y = 0;
  gdk_window_get_position(gdk_window, &current_x, &current_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);
}

bool NativeAppWindowGtk::IsVisible() const {
  return gtk_widget_get_visible(GTK_WIDGET(window_));
}

void NativeAppWindowGtk::HideWithApp() {}
void NativeAppWindowGtk::ShowWithApp() {}
