• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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();
ToggleTabStripMode()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.
tabstrip()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 
browser()192   Browser* browser() const { return browser_.get(); }
193 
window()194   GtkWindow* window() const { return window_; }
195 
GetToolbar()196   BrowserToolbarGtk* GetToolbar() { return toolbar_.get(); }
197 
bounds()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