summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/panels/panel_browser_window_gtk.h
blob: 94f37866a4f89a86e133e919377e24cbae2f39a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright (c) 2011 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.

#ifndef CHROME_BROWSER_UI_PANELS_PANEL_BROWSER_WINDOW_GTK_H_
#define CHROME_BROWSER_UI_PANELS_PANEL_BROWSER_WINDOW_GTK_H_

#include "chrome/browser/ui/gtk/browser_window_gtk.h"
#include "chrome/browser/ui/gtk/menu_gtk.h"
#include "chrome/browser/ui/panels/native_panel.h"

class Panel;
class PanelSettingsMenuModel;
class NativePanelTestingGtk;

class PanelBrowserWindowGtk : public BrowserWindowGtk,
                              public NativePanel,
                              public MenuGtk::Delegate,
                              public MessageLoopForUI::Observer {
  friend class NativePanelTestingGtk;
 public:
  PanelBrowserWindowGtk(Browser* browser, Panel* panel,
                        const gfx::Rect& bounds);
  virtual ~PanelBrowserWindowGtk();

  // BrowserWindowGtk overrides
  virtual void Init() OVERRIDE;

  // BrowserWindow overrides
  virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
  virtual void ShowSettingsMenu(GtkWidget* widget,
                                GdkEventButton* event) OVERRIDE;
  virtual TitleDecoration GetWindowTitle(std::string* title) const OVERRIDE;

 protected:
  // BrowserWindowGtk overrides
  virtual bool GetWindowEdge(int x, int y, GdkWindowEdge* edge) OVERRIDE;
  virtual bool HandleTitleBarLeftMousePress(
      GdkEventButton* event,
      guint32 last_click_time,
      gfx::Point last_click_position) OVERRIDE;
  virtual void SaveWindowPosition() OVERRIDE;
  virtual void SetGeometryHints() OVERRIDE;
  virtual bool UseCustomFrame() OVERRIDE;
  virtual void OnSizeChanged(int width, int height) OVERRIDE;
  virtual void DrawCustomFrame(cairo_t* cr, GtkWidget* widget,
                               GdkEventExpose* event) OVERRIDE;

  // Overridden from NativePanel:
  virtual void ShowPanel() OVERRIDE;
  virtual void ShowPanelInactive() OVERRIDE;
  virtual gfx::Rect GetPanelBounds() const OVERRIDE;
  virtual void SetPanelBounds(const gfx::Rect& bounds) OVERRIDE;
  virtual void ClosePanel() OVERRIDE;
  virtual void ActivatePanel() OVERRIDE;
  virtual void DeactivatePanel() OVERRIDE;
  virtual bool IsPanelActive() const OVERRIDE;
  virtual gfx::NativeWindow GetNativePanelHandle() OVERRIDE;
  virtual void UpdatePanelTitleBar() OVERRIDE;
  virtual void UpdatePanelLoadingAnimations(bool should_animate) OVERRIDE;
  virtual void ShowTaskManagerForPanel() OVERRIDE;
  virtual FindBar* CreatePanelFindBar() OVERRIDE;
  virtual void NotifyPanelOnUserChangedTheme() OVERRIDE;
  virtual void PanelTabContentsFocused(TabContents* tab_contents) OVERRIDE;
  virtual void PanelCut() OVERRIDE;
  virtual void PanelCopy() OVERRIDE;
  virtual void PanelPaste() OVERRIDE;
  virtual void DrawAttention() OVERRIDE;
  virtual bool IsDrawingAttention() const OVERRIDE;
  virtual bool PreHandlePanelKeyboardEvent(
      const NativeWebKeyboardEvent& event,
      bool* is_keyboard_shortcut) OVERRIDE;
  virtual void HandlePanelKeyboardEvent(
      const NativeWebKeyboardEvent& event) OVERRIDE;
  virtual Browser* GetPanelBrowser() const OVERRIDE;
  virtual void DestroyPanelBrowser() OVERRIDE;
  virtual gfx::Size WindowSizeFromContentSize(
      const gfx::Size& content_size) const OVERRIDE;
  virtual gfx::Size ContentSizeFromWindowSize(
      const gfx::Size& window_size) const OVERRIDE;
  virtual int TitleOnlyHeight() const OVERRIDE;

 private:
  // Resize the window as specified by the bounds.
  // Panels use window gravity of GDK_GRAVITY_SOUTH_EAST which means the
  // window is anchored to the bottom right corner on resize, making it
  // unnecessary to move the window if the bottom right corner is unchanged.
  // For example, when we minimize to the bottom, moving can actually
  // result in the wrong behavior.
  //   - Say window is 100x100 with x,y=900,900 on a 1000x1000 screen.
  //   - Say you minimize the window to 100x3 and move it to 900,997 to keep it
  //     anchored to the bottom.
  //   - resize is an async operation and the window manager will decide that
  //     the move will take the window off screen and it won't honor the
  //     request.
  //   - When resize finally happens, you'll have a 100x3 window a x,y=900,900.
  // Set |force_move| to true to force a move regardless. Otherwise, the
  // window is only moved if the bottom right corner is being changed.
  void SetBoundsImpl(const gfx::Rect& bounds, bool force_move);

  // MessageLoop::Observer implementation:
  virtual void WillProcessEvent(GdkEvent* event) OVERRIDE;
  virtual void DidProcessEvent(GdkEvent* event) OVERRIDE;

  void CreateDragWidget();
  void DestroyDragWidget();
  void EndDrag(bool canceled);
  void CleanupDragDrop();

  GdkRectangle GetTitlebarRectForDrawAttention() const;

  CHROMEGTK_CALLBACK_1(PanelBrowserWindowGtk, gboolean,
                       OnTitlebarButtonPressEvent, GdkEventButton*);
  CHROMEGTK_CALLBACK_1(PanelBrowserWindowGtk, gboolean,
                       OnTitlebarButtonReleaseEvent, GdkEventButton*);
  CHROMEGTK_CALLBACK_1(PanelBrowserWindowGtk, gboolean, OnFocusIn,
                       GdkEventFocus*);

  // drag-begin is emitted when the drag is started. We connect so that we can
  // set the drag icon to a transparent pixbuf.
  CHROMEGTK_CALLBACK_1(PanelBrowserWindowGtk, void, OnDragBegin,
                       GdkDragContext*);

  // drag-failed is emitted when the drag is finished.  In our case the signal
  // does not imply failure as we don't use the drag-n-drop API to transfer drop
  // data.
  CHROMEGTK_CALLBACK_2(PanelBrowserWindowGtk, gboolean, OnDragFailed,
                       GdkDragContext*, GtkDragResult);

  // When a drag is ending, a fake button release event is passed to the drag
  // widget to fake letting go of the mouse button.  We need a callback for
  // this event because it is the only way to catch drag end events when the
  // user presses space or return.
  CHROMEGTK_CALLBACK_1(PanelBrowserWindowGtk, gboolean, OnDragButtonReleased,
                       GdkEventButton*);

  // A copy of the last button press event, used to initiate a drag.
  GdkEvent* last_mouse_down_;

  // A GtkInivisible used to track the drag event.  GtkInvisibles are of the
  // type GInitiallyUnowned, but the widget initialization code sinks the
  // reference, so we can't use an OwnedWidgetGtk here.
  GtkWidget* drag_widget_;

  // Used to destroy the drag widget after a return to the message loop.
  ScopedRunnableMethodFactory<PanelBrowserWindowGtk>
      destroy_drag_widget_factory_;

  // Due to a bug in GTK+, we need to force the end of a drag when we get a
  // mouse release event on the the dragged widget, otherwise, we don't know
  // when the drag has ended when the user presses space or enter.  We queue
  // a task to end the drag and only run it if GTK+ didn't send us the
  // drag-failed event.
  ScopedRunnableMethodFactory<PanelBrowserWindowGtk> drag_end_factory_;

  scoped_ptr<Panel> panel_;
  gfx::Rect bounds_;

  scoped_ptr<PanelSettingsMenuModel> settings_menu_model_;
  scoped_ptr<MenuGtk> settings_menu_;

  // False until the window has been allocated and sized.
  bool window_size_known_;

  // Indicates that the panel is currently drawing attention.
  bool is_drawing_attention_;

  // Disable ExpansionState changes on mouse click for a short duration.
  // This is needed in case the window gains focus as result of mouseDown while
  // being already expanded and drawing attention - in this case, we don't
  // want to minimize it on subsequent mouseUp.
  // We use time interval because the window may gain focus in various ways
  // (via keyboard for example) which are not distinguishable at this point.
  // Apparently this disable interval is not affecting the user in other cases.
  base::Time disableMinimizeUntilTime_;

  DISALLOW_COPY_AND_ASSIGN(PanelBrowserWindowGtk);
};

#endif  // CHROME_BROWSER_UI_PANELS_PANEL_BROWSER_WINDOW_GTK_H_