OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This is the GTK implementation of InfoBubbles. InfoBubbles are like | 5 // This is the GTK implementation of InfoBubbles. InfoBubbles are like |
6 // dialogs, but they point to a given element on the screen. You should call | 6 // dialogs, but they point to a given element on the screen. You should call |
7 // InfoBubbleGtk::Show, which will create and display a bubble. The object is | 7 // InfoBubbleGtk::Show, which will create and display a bubble. The object is |
8 // self deleting, when the bubble is closed, you will be notified via | 8 // self deleting, when the bubble is closed, you will be notified via |
9 // InfoBubbleGtkDelegate::InfoBubbleClosing(). Then the widgets and the | 9 // InfoBubbleGtkDelegate::InfoBubbleClosing(). Then the widgets and the |
10 // underlying object will be destroyed. You can also close and destroy the | 10 // underlying object will be destroyed. You can also close and destroy the |
(...skipping 21 matching lines...) Expand all Loading... |
32 // |closed_by_escape| is true if the close is the result of pressing escape. | 32 // |closed_by_escape| is true if the close is the result of pressing escape. |
33 virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble, | 33 virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble, |
34 bool closed_by_escape) = 0; | 34 bool closed_by_escape) = 0; |
35 | 35 |
36 // NOTE: The Views interface has CloseOnEscape, except I can't find a place | 36 // NOTE: The Views interface has CloseOnEscape, except I can't find a place |
37 // where it ever returns false, so we always allow you to close via escape. | 37 // where it ever returns false, so we always allow you to close via escape. |
38 }; | 38 }; |
39 | 39 |
40 class InfoBubbleGtk : public NotificationObserver { | 40 class InfoBubbleGtk : public NotificationObserver { |
41 public: | 41 public: |
| 42 // Where should the arrow be placed relative to the bubble? |
| 43 enum ArrowLocationGtk { |
| 44 // TODO(derat): Support placing arrows on the bottoms of the bubbles. |
| 45 ARROW_LOCATION_TOP_LEFT, |
| 46 ARROW_LOCATION_TOP_RIGHT, |
| 47 }; |
| 48 |
42 // Show an InfoBubble, pointing at the area |rect| (in coordinates relative to | 49 // Show an InfoBubble, pointing at the area |rect| (in coordinates relative to |
43 // |toplevel_window|'s origin). An info bubble will try to fit on the screen, | 50 // |toplevel_window|'s origin). An info bubble will try to fit on the screen, |
44 // so it can point to any edge of |rect|. The bubble will host the |content| | 51 // so it can point to any edge of |rect|. The bubble will host the |content| |
45 // widget. The |delegate| will be notified when the bubble is closed. The | 52 // widget. Its arrow will be drawn at |arrow_location| if possible. The |
46 // bubble will perform an X grab of the pointer and keyboard, and will close | 53 // |delegate| will be notified when the bubble is closed. The bubble will |
47 // itself if a click is received outside of the bubble. | 54 // perform an X grab of the pointer and keyboard, and will close itself if a |
48 // TODO(derat): This implementation doesn't try to position itself onscreen. | 55 // click is received outside of the bubble. |
49 static InfoBubbleGtk* Show(GtkWindow* toplevel_window, | 56 static InfoBubbleGtk* Show(GtkWindow* toplevel_window, |
50 const gfx::Rect& rect, | 57 const gfx::Rect& rect, |
51 GtkWidget* content, | 58 GtkWidget* content, |
| 59 ArrowLocationGtk arrow_location, |
52 GtkThemeProvider* provider, | 60 GtkThemeProvider* provider, |
53 InfoBubbleGtkDelegate* delegate); | 61 InfoBubbleGtkDelegate* delegate); |
54 | 62 |
55 // Close the bubble if it's open. This will delete the widgets and object, | 63 // Close the bubble if it's open. This will delete the widgets and object, |
56 // so you shouldn't hold a InfoBubbleGtk pointer after calling Close(). | 64 // so you shouldn't hold a InfoBubbleGtk pointer after calling Close(). |
57 void Close() { CloseInternal(false); } | 65 void Close() { CloseInternal(false); } |
58 | 66 |
59 // NotificationObserver implementation. | 67 // NotificationObserver implementation. |
60 virtual void Observe(NotificationType type, | 68 virtual void Observe(NotificationType type, |
61 const NotificationSource& source, | 69 const NotificationSource& source, |
62 const NotificationDetails& details); | 70 const NotificationDetails& details); |
63 | 71 |
64 // If the content contains widgets that can steal our pointer and keyboard | 72 // If the content contains widgets that can steal our pointer and keyboard |
65 // grabs (e.g. GtkComboBox), this method should be called after a widget | 73 // grabs (e.g. GtkComboBox), this method should be called after a widget |
66 // releases the grabs so we can reacquire them. Note that this causes a race | 74 // releases the grabs so we can reacquire them. Note that this causes a race |
67 // condition; another client could grab them before we do (ideally, GDK would | 75 // condition; another client could grab them before we do (ideally, GDK would |
68 // transfer the grabs back to us when the widget releases them). The window | 76 // transfer the grabs back to us when the widget releases them). The window |
69 // is small, though, and the worst-case scenario for this seems to just be | 77 // is small, though, and the worst-case scenario for this seems to just be |
70 // that the content's widgets will appear inactive even after the user clicks | 78 // that the content's widgets will appear inactive even after the user clicks |
71 // in them. | 79 // in them. |
72 void HandlePointerAndKeyboardUngrabbedByContent(); | 80 void HandlePointerAndKeyboardUngrabbedByContent(); |
73 | 81 |
74 private: | 82 private: |
75 // Where should the arrow be placed relative to the bubble? | |
76 enum ArrowLocationGtk { | |
77 // TODO(derat): Support placing arrows on the bottoms of the bubbles. | |
78 ARROW_LOCATION_TOP_LEFT, | |
79 ARROW_LOCATION_TOP_RIGHT, | |
80 }; | |
81 | |
82 enum FrameType { | 83 enum FrameType { |
83 FRAME_MASK, | 84 FRAME_MASK, |
84 FRAME_STROKE, | 85 FRAME_STROKE, |
85 }; | 86 }; |
86 | 87 |
87 explicit InfoBubbleGtk(GtkThemeProvider* provider); | 88 explicit InfoBubbleGtk(GtkThemeProvider* provider); |
88 virtual ~InfoBubbleGtk(); | 89 virtual ~InfoBubbleGtk(); |
89 | 90 |
90 // Creates the InfoBubble. | 91 // Creates the InfoBubble. |
91 void Init(GtkWindow* toplevel_window, | 92 void Init(GtkWindow* toplevel_window, |
92 const gfx::Rect& rect, | 93 const gfx::Rect& rect, |
93 GtkWidget* content); | 94 GtkWidget* content, |
| 95 ArrowLocationGtk arrow_location); |
94 | 96 |
95 // Make the points for our polygon frame, either for fill (the mask), or for | 97 // Make the points for our polygon frame, either for fill (the mask), or for |
96 // when we stroke the border. | 98 // when we stroke the border. |
97 static std::vector<GdkPoint> MakeFramePolygonPoints( | 99 static std::vector<GdkPoint> MakeFramePolygonPoints( |
98 ArrowLocationGtk arrow_location, | 100 ArrowLocationGtk arrow_location, |
99 int width, | 101 int width, |
100 int height, | 102 int height, |
101 FrameType type); | 103 FrameType type); |
102 | 104 |
103 // Get the location where the arrow should be placed (which is a function of | 105 // Get the location where the arrow should be placed (which is a function of |
104 // whether the user's language is LTR/RTL and of the direction that the bubble | 106 // the preferred location and of the direction that the bubble should be |
105 // should be facing to fit onscreen). |arrow_x| is the X component in screen | 107 // facing to fit onscreen). |arrow_x| is the X component in screen |
106 // coordinates of the point at which the bubble's arrow should be aimed, and | 108 // coordinates of the point at which the bubble's arrow should be aimed, and |
107 // |width| is the bubble's width. | 109 // |width| is the bubble's width. |
108 static ArrowLocationGtk GetArrowLocation(int arrow_x, int width); | 110 static ArrowLocationGtk GetArrowLocation( |
| 111 ArrowLocationGtk preferred_location, int arrow_x, int width); |
109 | 112 |
110 // Updates |arrow_location_| based on the toplevel window's current position | 113 // Updates |arrow_location_| based on the toplevel window's current position |
111 // and the bubble's size. If the location changes, moves and reshapes the | 114 // and the bubble's size. If the |force_move_and_reshape| is true or the |
112 // window and returns true. | 115 // location changes, moves and reshapes the window and returns true. |
113 bool UpdateArrowLocation(); | 116 bool UpdateArrowLocation(bool force_move_and_reshape); |
114 | 117 |
115 // Reshapes the window and updates |mask_region_|. | 118 // Reshapes the window and updates |mask_region_|. |
116 void UpdateWindowShape(); | 119 void UpdateWindowShape(); |
117 | 120 |
118 // Calculate the current screen position for the bubble's window (per | 121 // Calculate the current screen position for the bubble's window (per |
119 // |toplevel_window_|'s position as of its most-recent ConfigureNotify event | 122 // |toplevel_window_|'s position as of its most-recent ConfigureNotify event |
120 // and |rect_|) and move it there. | 123 // and |rect_|) and move it there. |
121 void MoveWindow(); | 124 void MoveWindow(); |
122 | 125 |
123 // Restack the bubble's window directly above |toplevel_window_|. | 126 // Restack the bubble's window directly above |toplevel_window_|. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 GtkWindow* toplevel_window_; | 214 GtkWindow* toplevel_window_; |
212 | 215 |
213 // Provides an offset from |toplevel_window_|'s origin for MoveWindow() to | 216 // Provides an offset from |toplevel_window_|'s origin for MoveWindow() to |
214 // use. | 217 // use. |
215 gfx::Rect rect_; | 218 gfx::Rect rect_; |
216 | 219 |
217 // The current shape of |window_| (used to test whether clicks fall in it or | 220 // The current shape of |window_| (used to test whether clicks fall in it or |
218 // not). | 221 // not). |
219 GdkRegion* mask_region_; | 222 GdkRegion* mask_region_; |
220 | 223 |
221 // Where should the arrow be drawn relative to the bubble? | 224 // Where would we prefer for the arrow be drawn relative to the bubble, and |
222 ArrowLocationGtk arrow_location_; | 225 // where is it currently drawn? |
| 226 ArrowLocationGtk preferred_arrow_location_; |
| 227 ArrowLocationGtk current_arrow_location_; |
223 | 228 |
224 NotificationRegistrar registrar_; | 229 NotificationRegistrar registrar_; |
225 | 230 |
226 DISALLOW_COPY_AND_ASSIGN(InfoBubbleGtk); | 231 DISALLOW_COPY_AND_ASSIGN(InfoBubbleGtk); |
227 }; | 232 }; |
228 | 233 |
229 #endif // CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_ | 234 #endif // CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_ |
OLD | NEW |