// 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/extensions/shell_window_gtk.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/extension.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/rect.h" ShellWindowGtk::ShellWindowGtk(Profile* profile, const Extension* extension, const GURL& url) : ShellWindow(profile, extension, url), state_(GDK_WINDOW_STATE_WITHDRAWN), is_active_(!ui::ActiveWindowWatcherX::WMSupportsActivation()) { 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); gtk_window_set_default_size(window_, kDefaultWidth, kDefaultHeight); // TODO(mihaip): Mirror contents of tag in window title gtk_window_set_title(window_, extension->name().c_str()); 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); ui::ActiveWindowWatcherX::AddObserver(this); gtk_window_present(window_); } ShellWindowGtk::~ShellWindowGtk() { ui::ActiveWindowWatcherX::RemoveObserver(this); } bool ShellWindowGtk::IsActive() const { return is_active_; } bool ShellWindowGtk::IsMaximized() const { return (state_ & GDK_WINDOW_STATE_MAXIMIZED); } bool ShellWindowGtk::IsMinimized() const { return (state_ & GDK_WINDOW_STATE_ICONIFIED); } bool ShellWindowGtk::IsFullscreen() const { return false; } gfx::Rect ShellWindowGtk::GetRestoredBounds() const { return restored_bounds_; } gfx::Rect ShellWindowGtk::GetBounds() const { return bounds_; } void ShellWindowGtk::Show() { gtk_window_present(window_); } void ShellWindowGtk::ShowInactive() { gtk_window_set_focus_on_map(window_, false); gtk_widget_show(GTK_WIDGET(window_)); } void ShellWindowGtk::Close() { 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; gtk_widget_destroy(window); delete this; } void ShellWindowGtk::Activate() { gtk_window_present(window_); } void ShellWindowGtk::Deactivate() { gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_))); } void ShellWindowGtk::Maximize() { gtk_window_maximize(window_); } void ShellWindowGtk::Minimize() { gtk_window_iconify(window_); } void ShellWindowGtk::Restore() { if (IsMaximized()) gtk_window_unmaximize(window_); else if (IsMinimized()) gtk_window_deiconify(window_); } void ShellWindowGtk::SetBounds(const gfx::Rect& bounds) { gtk_window_move(window_, bounds.x(), bounds.y()); // TODO(mihaip): Do we need the same workaround as BrowserWindowGtk:: // SetWindowSize in order to avoid triggering fullscreen mode? gtk_window_resize(window_, bounds.width(), bounds.height()); } void ShellWindowGtk::SetDraggableRegion(SkRegion* region) { // TODO: implement } void ShellWindowGtk::FlashFrame(bool flash) { gtk_window_set_urgency_hint(window_, flash); } bool ShellWindowGtk::IsAlwaysOnTop() const { return false; } void ShellWindowGtk::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; } // 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 ShellWindowGtk::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 ShellWindowGtk::OnConfigure(GtkWidget* widget, GdkEventConfigure* event) { // TODO(mihaip): Do we need an explicit gtk_window_get_position call like in // in BrowserWindowGtk::OnConfigure? bounds_.SetRect(event->x, event->y, event->width, event->height); if (!IsMaximized()) restored_bounds_ = bounds_; return FALSE; } gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender, GdkEventWindowState* event) { state_ = event->new_window_state; return FALSE; } // static ShellWindow* ShellWindow::CreateImpl(Profile* profile, const Extension* extension, const GURL& url) { return new ShellWindowGtk(profile, extension, url); }