1// Copyright (c) 2012 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_PANELS_PANEL_GTK_H_
6#define CHROME_BROWSER_UI_GTK_PANELS_PANEL_GTK_H_
7
8#include <gtk/gtk.h>
9#include <map>
10
11#include "base/basictypes.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/timer/timer.h"
14#include "chrome/browser/ui/panels/native_panel.h"
15#include "chrome/browser/ui/panels/panel_constants.h"
16#include "ui/base/gtk/gtk_signal.h"
17#include "ui/base/x/active_window_watcher_x_observer.h"
18#include "ui/gfx/rect.h"
19
20class Panel;
21class PanelTitlebarGtk;
22class PanelDragGtk;
23class GtkNativePanelTesting;
24
25namespace gfx {
26class Image;
27}
28
29// An implementation of the native panel in GTK.
30class PanelGtk : public NativePanel,
31                 public ui::ActiveWindowWatcherXObserver {
32 public:
33  enum PaintState {
34    PAINT_AS_ACTIVE,
35    PAINT_AS_INACTIVE,
36    PAINT_AS_MINIMIZED,
37    PAINT_FOR_ATTENTION
38  };
39
40  PanelGtk(Panel* panel, const gfx::Rect& bounds, bool always_on_top);
41  virtual ~PanelGtk();
42
43  void Init();
44
45  // Overridden from NativePanel.
46  virtual void ShowPanel() OVERRIDE;
47  virtual void ShowPanelInactive() OVERRIDE;
48  virtual gfx::Rect GetPanelBounds() const OVERRIDE;
49  virtual void SetPanelBounds(const gfx::Rect& bounds) OVERRIDE;
50  virtual void SetPanelBoundsInstantly(const gfx::Rect& bounds) OVERRIDE;
51  virtual void ClosePanel() OVERRIDE;
52  virtual void ActivatePanel() OVERRIDE;
53  virtual void DeactivatePanel() OVERRIDE;
54  virtual bool IsPanelActive() const OVERRIDE;
55  virtual void PreventActivationByOS(bool prevent_activation) OVERRIDE;
56  virtual gfx::NativeWindow GetNativePanelWindow() OVERRIDE;
57  virtual void UpdatePanelTitleBar() OVERRIDE;
58  virtual void UpdatePanelLoadingAnimations(bool should_animate) OVERRIDE;
59  virtual void PanelWebContentsFocused(content::WebContents* contents) OVERRIDE;
60  virtual void PanelCut() OVERRIDE;
61  virtual void PanelCopy() OVERRIDE;
62  virtual void PanelPaste() OVERRIDE;
63  virtual void DrawAttention(bool draw_attention) OVERRIDE;
64  virtual bool IsDrawingAttention() const OVERRIDE;
65  virtual void HandlePanelKeyboardEvent(
66      const content::NativeWebKeyboardEvent& event) OVERRIDE;
67  virtual void FullScreenModeChanged(bool is_full_screen) OVERRIDE;
68  virtual void PanelExpansionStateChanging(
69      Panel::ExpansionState old_state,
70      Panel::ExpansionState new_state) OVERRIDE;
71  virtual void AttachWebContents(content::WebContents* contents) OVERRIDE;
72  virtual void DetachWebContents(content::WebContents* contents) OVERRIDE;
73  // These sizes are in screen coordinates.
74  virtual gfx::Size WindowSizeFromContentSize(
75      const gfx::Size& content_size) const OVERRIDE;
76  virtual gfx::Size ContentSizeFromWindowSize(
77      const gfx::Size& window_size) const OVERRIDE;
78  virtual int TitleOnlyHeight() const OVERRIDE;
79  virtual bool IsPanelAlwaysOnTop() const OVERRIDE;
80  virtual void SetPanelAlwaysOnTop(bool on_top) OVERRIDE;
81  virtual void EnableResizeByMouse(bool enable) OVERRIDE;
82  virtual void UpdatePanelMinimizeRestoreButtonVisibility() OVERRIDE;
83  virtual void SetWindowCornerStyle(panel::CornerStyle corner_style) OVERRIDE;
84  virtual void MinimizePanelBySystem() OVERRIDE;
85  virtual bool IsPanelMinimizedBySystem() const OVERRIDE;
86  virtual bool IsPanelShownOnActiveDesktop() const OVERRIDE;
87  virtual void ShowShadow(bool show) OVERRIDE;
88
89  virtual NativePanelTesting* CreateNativePanelTesting() OVERRIDE;
90
91  // Overridden from ActiveWindowWatcherXObserver.
92  virtual void ActiveWindowChanged(GdkWindow* active_window) OVERRIDE;
93
94  Panel* panel() const { return panel_.get(); }
95  PaintState paint_state() const { return paint_state_; }
96  PanelTitlebarGtk* titlebar() const { return titlebar_.get(); }
97
98 private:
99  friend class GtkNativePanelTesting;
100
101  // Applies our custom window shape with rounded or non-rounded corners.
102  void UpdateWindowShape();
103
104  // Checks to see if the mouse pointer at |x|, |y| is over the border of the
105  // custom frame (a spot that should trigger a window resize). Returns true if
106  // it should and sets |edge|.
107  bool GetWindowEdge(int x, int y, GdkWindowEdge* edge) const;
108
109  // Connect/disconnect accelerators for keyboard shortcut support.
110  void ConnectAccelerators();
111  void DisconnectAccelerators();
112
113  // Returns the image to paint the frame.
114  gfx::Image GetFrameBackground() const;
115
116  // Animation when panel is first shown.
117  void RevealPanel();
118
119  // Creates helper for handling drags if not already created.
120  void EnsureDragHelperCreated();
121
122  void SetBoundsInternal(const gfx::Rect& bounds);
123
124  void LoadingAnimationCallback();
125
126  // Returns the size of the window frame around the client content area.
127  gfx::Size GetNonClientFrameSize() const;
128
129  // Invalidate window to force repaint.
130  void InvalidateWindow();
131
132  // Callback for accelerator activation. |user_data| stores the command id
133  // of the matched accelerator.
134  static gboolean OnGtkAccelerator(GtkAccelGroup* accel_group,
135                                   GObject* acceleratable,
136                                   guint keyval,
137                                   GdkModifierType modifier,
138                                   void* user_data);
139
140  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean, OnMainWindowDeleteEvent,
141                       GdkEvent*);
142  CHROMEGTK_CALLBACK_0(PanelGtk, void, OnMainWindowDestroy);
143  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean, OnConfigure, GdkEventConfigure*);
144  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean, OnWindowState, GdkEventWindowState*);
145  // Callback for when the custom frame alignment needs to be redrawn.
146  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean, OnCustomFrameExpose,
147                       GdkEventExpose*);
148  // Key press event callback.
149  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean, OnKeyPress, GdkEventKey*);
150  // Mouse move and button press callbacks. If mouse hits titlebar,
151  // the titlebar gets the event, else the window gets the button press.
152  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean, OnMouseMoveEvent,
153                       GdkEventMotion*);
154  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean, OnButtonPressEvent,
155                       GdkEventButton*);
156  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean,
157                       OnTitlebarButtonPressEvent, GdkEventButton*);
158  CHROMEGTK_CALLBACK_1(PanelGtk, gboolean,
159                       OnTitlebarButtonReleaseEvent, GdkEventButton*);
160
161  scoped_ptr<Panel> panel_;
162  gfx::Rect bounds_;
163
164  // True if the panel should always stay on top of other windows.
165  bool always_on_top_;
166
167  // True after panel has been shown.
168  bool is_shown_;
169
170  scoped_ptr<PanelDragGtk> drag_helper_;
171
172  // The configure size of the current window, used to figure out whether to
173  // ignore later configure events. See OnConfigure() for more information.
174  gfx::Size configure_size_;
175
176  // Indicates different painting state, active, drawing attention or else.
177  PaintState paint_state_;
178
179  // Indicates that the panel is currently drawing attention.
180  bool is_drawing_attention_;
181
182  // The timer used to update frames for the Loading Animation.
183  base::RepeatingTimer<PanelGtk> loading_animation_timer_;
184
185  // The current window cursor.  We set it to a resize cursor when over the
186  // custom frame border.  We set it to NULL if we want the default cursor.
187  GdkCursor* frame_cursor_;
188
189  // True if the window manager thinks the window is active.  Not all window
190  // managers keep track of this state (_NET_ACTIVE_WINDOW), in which case
191  // this will always be true.
192  bool is_active_;
193
194  // True if the window manager thinks the window is minimized (iconified).
195  // Not all window managers support this, in which case this will always be
196  // false.
197  bool is_minimized_;
198
199  // Top level window.
200  GtkWindow* window_;
201  // GtkAlignment that holds the interior components of the chromium window.
202  // This is used to draw the custom frame border and content shadow.
203  GtkWidget* window_container_;
204  // VBox that holds everything (titlebar, web contents).
205  GtkWidget* window_vbox_;
206  // EventBox that holds web contents.
207  GtkWidget* render_area_event_box_;
208  // We insert and remove WebContents GtkWidgets into this expanded.
209  GtkWidget* contents_expanded_;
210
211  // The accelerator group used to handle accelerators, owned by this object.
212  GtkAccelGroup* accel_group_;
213
214  // The container for the titlebar.
215  scoped_ptr<PanelTitlebarGtk> titlebar_;
216
217  // Indicates how the window corner should be rendered, rounded or not.
218  panel::CornerStyle corner_style_;
219
220  DISALLOW_COPY_AND_ASSIGN(PanelGtk);
221};
222
223#endif  // CHROME_BROWSER_UI_GTK_PANELS_PANEL_GTK_H_
224