Home | History | Annotate | Download | only in gtk
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_UI_GTK_BROWSER_WINDOW_GTK_H_
      6 #define CHROME_BROWSER_UI_GTK_BROWSER_WINDOW_GTK_H_
      7 #pragma once
      8 
      9 #include <gtk/gtk.h>
     10 
     11 #include <map>
     12 
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/timer.h"
     15 #include "build/build_config.h"
     16 #include "chrome/browser/prefs/pref_member.h"
     17 #include "chrome/browser/tabs/tab_strip_model_observer.h"
     18 #include "chrome/browser/ui/browser_window.h"
     19 #include "chrome/browser/ui/gtk/infobars/infobar_arrow_model.h"
     20 #include "content/common/notification_registrar.h"
     21 #include "ui/base/gtk/gtk_signal.h"
     22 #include "ui/base/x/active_window_watcher_x.h"
     23 #include "ui/base/x/x11_util.h"
     24 #include "ui/gfx/rect.h"
     25 
     26 class BookmarkBarGtk;
     27 class Browser;
     28 class BrowserTitlebar;
     29 class BrowserToolbarGtk;
     30 class CustomDrawButton;
     31 class DownloadShelfGtk;
     32 class FindBarGtk;
     33 class FullscreenExitBubbleGtk;
     34 class GlobalMenuBar;
     35 class InfoBarContainerGtk;
     36 class LocationBar;
     37 class StatusBubbleGtk;
     38 class TabContentsContainerGtk;
     39 class TabStripGtk;
     40 
     41 // An implementation of BrowserWindow for GTK.
     42 // Cross-platform code will interact with this object when
     43 // it needs to manipulate the window.
     44 
     45 class BrowserWindowGtk : public BrowserWindow,
     46                          public NotificationObserver,
     47                          public TabStripModelObserver,
     48                          public ui::ActiveWindowWatcherX::Observer,
     49                          public InfoBarArrowModel::Observer {
     50  public:
     51   explicit BrowserWindowGtk(Browser* browser);
     52   virtual ~BrowserWindowGtk();
     53 
     54   virtual void Init();
     55 
     56   // Overridden from BrowserWindow
     57   virtual void Show();
     58   virtual void ShowInactive();
     59   virtual void SetBounds(const gfx::Rect& bounds);
     60   virtual void Close();
     61   virtual void Activate();
     62   virtual void Deactivate();
     63   virtual bool IsActive() const;
     64   virtual void FlashFrame();
     65   virtual gfx::NativeWindow GetNativeHandle();
     66   virtual BrowserWindowTesting* GetBrowserWindowTesting();
     67   virtual StatusBubble* GetStatusBubble();
     68   virtual void ToolbarSizeChanged(bool is_animating);
     69   virtual void UpdateTitleBar();
     70   virtual void ShelfVisibilityChanged();
     71   virtual void UpdateDevTools();
     72   virtual void UpdateLoadingAnimations(bool should_animate);
     73   virtual void SetStarredState(bool is_starred);
     74   virtual gfx::Rect GetRestoredBounds() const;
     75   virtual gfx::Rect GetBounds() const;
     76   virtual bool IsMaximized() const;
     77   virtual void SetFullscreen(bool fullscreen);
     78   virtual bool IsFullscreen() const;
     79   virtual bool IsFullscreenBubbleVisible() const;
     80   virtual LocationBar* GetLocationBar() const;
     81   virtual void SetFocusToLocationBar(bool select_all);
     82   virtual void UpdateReloadStopState(bool is_loading, bool force);
     83   virtual void UpdateToolbar(TabContentsWrapper* contents,
     84                              bool should_restore_state);
     85   virtual void FocusToolbar();
     86   virtual void FocusAppMenu();
     87   virtual void FocusBookmarksToolbar();
     88   virtual void FocusChromeOSStatus();
     89   virtual void RotatePaneFocus(bool forwards);
     90   virtual bool IsBookmarkBarVisible() const;
     91   virtual bool IsBookmarkBarAnimating() const;
     92   virtual bool IsTabStripEditable() const;
     93   virtual bool IsToolbarVisible() const;
     94   virtual void ConfirmAddSearchProvider(const TemplateURL* template_url,
     95                                         Profile* profile);
     96   virtual void ToggleBookmarkBar();
     97   virtual void ShowAboutChromeDialog();
     98   virtual void ShowUpdateChromeDialog();
     99   virtual void ShowTaskManager();
    100   virtual void ShowBackgroundPages();
    101   virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked);
    102   virtual bool IsDownloadShelfVisible() const;
    103   virtual DownloadShelf* GetDownloadShelf();
    104   virtual void ShowRepostFormWarningDialog(TabContents* tab_contents);
    105   virtual void ShowCollectedCookiesDialog(TabContents* tab_contents);
    106   virtual void ShowThemeInstallBubble();
    107   virtual void ConfirmBrowserCloseWithPendingDownloads();
    108   virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
    109                               gfx::NativeWindow parent_window);
    110   virtual void UserChangedTheme();
    111   virtual int GetExtraRenderViewHeight() const;
    112   virtual void TabContentsFocused(TabContents* tab_contents);
    113   virtual void ShowPageInfo(Profile* profile,
    114                             const GURL& url,
    115                             const NavigationEntry::SSLStatus& ssl,
    116                             bool show_history);
    117   virtual void ShowAppMenu();
    118   virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
    119                                       bool* is_keyboard_shortcut);
    120   virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
    121   virtual void ShowCreateWebAppShortcutsDialog(
    122       TabContentsWrapper* tab_contents);
    123   virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile,
    124                                                   const Extension* app);
    125   virtual void Cut();
    126   virtual void Copy();
    127   virtual void Paste();
    128   virtual void ToggleTabStripMode() {}
    129   virtual void PrepareForInstant();
    130   virtual void ShowInstant(TabContentsWrapper* preview);
    131   virtual void HideInstant(bool instant_is_active);
    132   virtual gfx::Rect GetInstantBounds();
    133 
    134   // Overridden from NotificationObserver:
    135   virtual void Observe(NotificationType type,
    136                        const NotificationSource& source,
    137                        const NotificationDetails& details);
    138 
    139   // Overridden from TabStripModelObserver:
    140   virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
    141   virtual void TabSelectedAt(TabContentsWrapper* old_contents,
    142                              TabContentsWrapper* new_contents,
    143                              int index,
    144                              bool user_gesture);
    145 
    146   // Overridden from ActiveWindowWatcher::Observer.
    147   virtual void ActiveWindowChanged(GdkWindow* active_window);
    148 
    149   // Overridden from InfoBarArrowModel::Observer.
    150   virtual void PaintStateChanged();
    151 
    152   // Accessor for the tab strip.
    153   TabStripGtk* tabstrip() const { return tabstrip_.get(); }
    154 
    155   void UpdateDevToolsForContents(TabContents* contents);
    156 
    157   void OnDebouncedBoundsChanged();
    158 
    159   // Request the underlying window to unmaximize.  Also tries to work around
    160   // a window manager "feature" that can prevent this in some edge cases.
    161   void UnMaximize();
    162 
    163   // Returns false if we're not ready to close yet.  E.g., a tab may have an
    164   // onbeforeunload handler that prevents us from closing.
    165   bool CanClose() const;
    166 
    167   bool ShouldShowWindowIcon() const;
    168 
    169   // This should only be called from tests where the debounce timeout introduces
    170   // timing issues.
    171   void DisableDebounceTimerForTests(bool is_disabled);
    172 
    173   // Add the find bar widget to the window hierarchy.
    174   void AddFindBar(FindBarGtk* findbar);
    175 
    176   // Reset the mouse cursor to the default cursor if it was set to something
    177   // else for the custom frame.
    178   void ResetCustomFrameCursor();
    179 
    180   // Toggles whether an infobar is showing.
    181   // |animate| controls whether we animate to the new state set by |bar|.
    182   void SetInfoBarShowing(InfoBar* bar, bool animate);
    183 
    184   // Returns the BrowserWindowGtk registered with |window|.
    185   static BrowserWindowGtk* GetBrowserWindowForNativeWindow(
    186       gfx::NativeWindow window);
    187 
    188   // Retrieves the GtkWindow associated with |xid|, which is the X Window
    189   // ID of the top-level X window of this object.
    190   static GtkWindow* GetBrowserWindowForXID(XID xid);
    191 
    192   Browser* browser() const { return browser_.get(); }
    193 
    194   GtkWindow* window() const { return window_; }
    195 
    196   BrowserToolbarGtk* GetToolbar() { return toolbar_.get(); }
    197 
    198   gfx::Rect bounds() const { return bounds_; }
    199 
    200   // Make changes necessary when the floating state of the bookmark bar changes.
    201   // This should only be called by the bookmark bar itself.
    202   void BookmarkBarIsFloating(bool is_floating);
    203 
    204   // Returns the tab contents we're currently displaying in the tab contents
    205   // container.
    206   TabContents* GetDisplayedTabContents();
    207 
    208   static void RegisterUserPrefs(PrefService* prefs);
    209 
    210   // Returns whether to draw the content drop shadow on the sides and bottom
    211   // of the browser window. When false, we still draw a shadow on the top of
    212   // the toolbar (under the tab strip), but do not round the top corners.
    213   bool ShouldDrawContentDropShadow();
    214 
    215   // Tells GTK that the toolbar area is invalidated and needs redrawing. We
    216   // have this method as a hack because GTK doesn't queue the toolbar area for
    217   // redraw when it should.
    218   void QueueToolbarRedraw();
    219 
    220   // Get the position where the infobar arrow should be anchored in
    221   // |relative_to| coordinates. This is the middle of the omnibox location icon.
    222   int GetXPositionOfLocationIcon(GtkWidget* relative_to);
    223 
    224  protected:
    225   virtual void DestroyBrowser();
    226   // Top level window.
    227   GtkWindow* window_;
    228   // GtkAlignment that holds the interior components of the chromium window.
    229   // This is used to draw the custom frame border and content shadow.
    230   GtkWidget* window_container_;
    231   // VBox that holds everything (tabs, toolbar, bookmarks bar, tab contents).
    232   GtkWidget* window_vbox_;
    233   // VBox that holds everything below the toolbar.
    234   GtkWidget* render_area_vbox_;
    235   // Floating container that holds the render area. It is needed to position
    236   // the findbar.
    237   GtkWidget* render_area_floating_container_;
    238   // EventBox that holds render_area_floating_container_.
    239   GtkWidget* render_area_event_box_;
    240   // Border between toolbar and render area.
    241   GtkWidget* toolbar_border_;
    242 
    243   scoped_ptr<Browser> browser_;
    244 
    245   // The download shelf view (view at the bottom of the page).
    246   scoped_ptr<DownloadShelfGtk> download_shelf_;
    247 
    248  private:
    249   // Shows a fade effect over the tab contents. Repeated calls will be ignored
    250   // until the fade is canceled. If |animate| is true the fade should animate.
    251   void FadeForInstant(bool animate);
    252 
    253   // Immediately removes the fade.
    254   void CancelInstantFade();
    255 
    256   // Show or hide the bookmark bar.
    257   void MaybeShowBookmarkBar(bool animate);
    258 
    259   // Sets the default size for the window and the the way the user is allowed to
    260   // resize it.
    261   void SetGeometryHints();
    262 
    263   // Connect to signals on |window_|.
    264   void ConnectHandlersToSignals();
    265 
    266   // Create the various UI components.
    267   void InitWidgets();
    268 
    269   // Set up background color of the window (depends on if we're incognito or
    270   // not).
    271   void SetBackgroundColor();
    272 
    273   // Called when the window size changed.
    274   void OnSizeChanged(int width, int height);
    275 
    276   // Applies the window shape to if we're in custom drawing mode.
    277   void UpdateWindowShape(int width, int height);
    278 
    279   // Connect accelerators that aren't connected to menu items (like ctrl-o,
    280   // ctrl-l, etc.).
    281   void ConnectAccelerators();
    282 
    283   // Change whether we're showing the custom blue frame.
    284   // Must be called once at startup.
    285   // Triggers relayout of the content.
    286   void UpdateCustomFrame();
    287 
    288   // Save the window position in the prefs.
    289   void SaveWindowPosition();
    290 
    291   // Set the bounds of the current window. If |exterior| is true, set the size
    292   // of the window itself, otherwise set the bounds of the web contents.
    293   // If |move| is true, set the position of the window, otherwise leave the
    294   // position to the WM.
    295   void SetBoundsImpl(const gfx::Rect& bounds, bool exterior, bool move);
    296 
    297   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnConfigure,
    298                        GdkEventConfigure*);
    299   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnWindowState,
    300                        GdkEventWindowState*);
    301   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnMainWindowDeleteEvent,
    302                        GdkEvent*);
    303   CHROMEGTK_CALLBACK_0(BrowserWindowGtk, void, OnMainWindowDestroy);
    304   // Callback for when the custom frame alignment needs to be redrawn.
    305   // The content area includes the toolbar and web page but not the tab strip.
    306   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnCustomFrameExpose,
    307                        GdkEventExpose*);
    308 
    309   // A helper method that draws the shadow above the toolbar and in the frame
    310   // border during an expose.
    311   void DrawContentShadow(cairo_t* cr);
    312 
    313   // Draws the tab image as the frame so we can write legible text.
    314   void DrawPopupFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
    315 
    316   // Draws the normal custom frame using theme_frame.
    317   void DrawCustomFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
    318 
    319   // The background frame image needs to be offset by the size of the top of
    320   // the window to the top of the tabs when the full skyline isn't displayed
    321   // for some reason.
    322   int GetVerticalOffset();
    323 
    324   // Returns which frame image we should use based on the window's current
    325   // activation state / incognito state.
    326   int GetThemeFrameResource();
    327 
    328   // Invalidate all the widgets that need to redraw when the infobar draw state
    329   // has changed.
    330   void InvalidateInfoBarBits();
    331 
    332   // Gets the size (width and height) of the infobar arrow. The size depends on
    333   // the state of the bookmark bar.
    334   gfx::Size GetInfobarArrowSize();
    335 
    336   // When the location icon moves, we have to redraw the arrow.
    337   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, void, OnLocationIconSizeAllocate,
    338                        GtkAllocation*);
    339 
    340   // Used to draw the infobar arrow and drop shadow. This is connected to
    341   // multiple widgets' expose events because it overlaps several widgets.
    342   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnExposeDrawInfobarBits,
    343                        GdkEventExpose*);
    344 
    345   // Used to draw the infobar bits for the bookmark bar. When the bookmark
    346   // bar is in floating mode, it has to draw a drop shadow only; otherwise
    347   // it is responsible for its portion of the arrow as well as some shadowing.
    348   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnBookmarkBarExpose,
    349                        GdkEventExpose*);
    350 
    351   // Callback for "size-allocate" signal on bookmark bar; this is relevant
    352   // because when the bookmark bar changes dimensions, the infobar arrow has to
    353   // change its shape, and we need to queue appropriate redraws.
    354   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, void, OnBookmarkBarSizeAllocate,
    355                        GtkAllocation*);
    356 
    357   // Callback for accelerator activation. |user_data| stores the command id
    358   // of the matched accelerator.
    359   static gboolean OnGtkAccelerator(GtkAccelGroup* accel_group,
    360                                    GObject* acceleratable,
    361                                    guint keyval,
    362                                    GdkModifierType modifier,
    363                                    void* user_data);
    364 
    365   // Key press event callback.
    366   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnKeyPress, GdkEventKey*);
    367 
    368   // Mouse move and mouse button press callbacks.
    369   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnMouseMoveEvent,
    370                        GdkEventMotion*);
    371   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnButtonPressEvent,
    372                        GdkEventButton*);
    373 
    374   // Maps and Unmaps the xid of |widget| to |window|.
    375   static void MainWindowMapped(GtkWidget* widget);
    376   static void MainWindowUnMapped(GtkWidget* widget);
    377 
    378   // Tracks focus state of browser.
    379   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnFocusIn,
    380                        GdkEventFocus*);
    381   CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnFocusOut,
    382                        GdkEventFocus*);
    383 
    384   // Callback for the loading animation(s) associated with this window.
    385   void LoadingAnimationCallback();
    386 
    387   // Shows UI elements for supported window features.
    388   void ShowSupportedWindowFeatures();
    389 
    390   // Hides UI elements for unsupported window features.
    391   void HideUnsupportedWindowFeatures();
    392 
    393   // Helper functions that query |browser_| concerning support for UI features
    394   // in this window. (For example, a popup window might not support a tabstrip).
    395   bool IsTabStripSupported() const;
    396   bool IsToolbarSupported() const;
    397   bool IsBookmarkBarSupported() const;
    398 
    399   // Whether we should draw the tab background instead of the theme_frame
    400   // background because this window is a popup.
    401   bool UsingCustomPopupFrame() const;
    402 
    403   // Checks to see if the mouse pointer at |x|, |y| is over the border of the
    404   // custom frame (a spot that should trigger a window resize). Returns true if
    405   // it should and sets |edge|.
    406   bool GetWindowEdge(int x, int y, GdkWindowEdge* edge);
    407 
    408   // Returns |true| if we should use the custom frame.
    409   bool UseCustomFrame();
    410 
    411   // Returns |true| if the window bounds match the monitor size.
    412   bool BoundsMatchMonitorSize();
    413 
    414   // Put the bookmark bar where it belongs.
    415   void PlaceBookmarkBar(bool is_floating);
    416 
    417   // Determine whether we use should default to native decorations or the custom
    418   // frame based on the currently-running window manager.
    419   static bool GetCustomFramePrefDefault();
    420 
    421   NotificationRegistrar registrar_;
    422 
    423   // The position and size of the current window.
    424   gfx::Rect bounds_;
    425 
    426   // The position and size of the non-maximized, non-fullscreen window.
    427   gfx::Rect restored_bounds_;
    428 
    429   GdkWindowState state_;
    430 
    431   // Controls a hidden GtkMenuBar that we keep updated so GNOME can take a look
    432   // inside "our menu bar" and present it in the top panel, akin to Mac OS.
    433   scoped_ptr<GlobalMenuBar> global_menu_bar_;
    434 
    435   // The container for the titlebar + tab strip.
    436   scoped_ptr<BrowserTitlebar> titlebar_;
    437 
    438   // The object that manages all of the widgets in the toolbar.
    439   scoped_ptr<BrowserToolbarGtk> toolbar_;
    440 
    441   // The object that manages the bookmark bar. This will be NULL if the
    442   // bookmark bar is not supported.
    443   scoped_ptr<BookmarkBarGtk> bookmark_bar_;
    444 
    445   // Caches the hover state of the bookmark bar.
    446   bool bookmark_bar_is_floating_;
    447 
    448   // The status bubble manager.  Always non-NULL.
    449   scoped_ptr<StatusBubbleGtk> status_bubble_;
    450 
    451   // A container that manages the GtkWidget*s that are the webpage display
    452   // (along with associated infobars, shelves, and other things that are part
    453   // of the content area).
    454   scoped_ptr<TabContentsContainerGtk> contents_container_;
    455 
    456   // A container that manages the GtkWidget*s of developer tools for the
    457   // selected tab contents.
    458   scoped_ptr<TabContentsContainerGtk> devtools_container_;
    459 
    460   // Split pane containing the contents_container_ and the devtools_container_.
    461   GtkWidget* contents_split_;
    462 
    463   // The tab strip.  Always non-NULL.
    464   scoped_ptr<TabStripGtk> tabstrip_;
    465 
    466   // The container for info bars. Always non-NULL.
    467   scoped_ptr<InfoBarContainerGtk> infobar_container_;
    468 
    469   // The timer used to update frames for the Loading Animation.
    470   base::RepeatingTimer<BrowserWindowGtk> loading_animation_timer_;
    471 
    472   // The timer used to save the window position for session restore.
    473   base::OneShotTimer<BrowserWindowGtk> window_configure_debounce_timer_;
    474 
    475   // Whether the custom chrome frame pref is set.  Normally you want to use
    476   // UseCustomFrame() above to determine whether to use the custom frame or
    477   // not.
    478   BooleanPrefMember use_custom_frame_pref_;
    479 
    480   // A map which translates an X Window ID into its respective GtkWindow.
    481   static std::map<XID, GtkWindow*> xid_map_;
    482 
    483   // The current window cursor.  We set it to a resize cursor when over the
    484   // custom frame border.  We set it to NULL if we want the default cursor.
    485   GdkCursor* frame_cursor_;
    486 
    487   // True if the window manager thinks the window is active.  Not all window
    488   // managers keep track of this state (_NET_ACTIVE_WINDOW), in which case
    489   // this will always be true.
    490   bool is_active_;
    491 
    492   // Keep track of the last click time and the last click position so we can
    493   // filter out extra GDK_BUTTON_PRESS events when a double click happens.
    494   guint32 last_click_time_;
    495   gfx::Point last_click_position_;
    496 
    497   // If true, maximize the window after we call BrowserWindow::Show for the
    498   // first time.  This is to work around a compiz bug.
    499   bool maximize_after_show_;
    500 
    501   // If true, don't call gdk_window_raise() when we get a click in the title
    502   // bar or window border.  This is to work around a compiz bug.
    503   bool suppress_window_raise_;
    504 
    505   // The accelerator group used to handle accelerators, owned by this object.
    506   GtkAccelGroup* accel_group_;
    507 
    508   scoped_ptr<FullscreenExitBubbleGtk> fullscreen_exit_bubble_;
    509 
    510   // If true, the debounce timer won't be used and OnDebounceBoundsChanged won't
    511   // be called. This should only be enabled in tests where the debounce timeout
    512   // introduces timing issues (e.g. in OmniBoxApiTest it dismisses the
    513   // autocomplete popup before the results can be read) and the final window
    514   // position is unimportant.
    515   bool debounce_timer_disabled_;
    516 
    517   // The model that tracks the paint state of the arrow for the infobar
    518   // directly below the toolbar.
    519   InfoBarArrowModel infobar_arrow_model_;
    520 
    521   DISALLOW_COPY_AND_ASSIGN(BrowserWindowGtk);
    522 };
    523 
    524 #endif  // CHROME_BROWSER_UI_GTK_BROWSER_WINDOW_GTK_H_
    525