Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: chrome/browser/gtk/info_bubble_gtk.cc

Issue 316006: GTK: Try to position info bubbles onscreen. (Closed)
Patch Set: merge Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/gtk/info_bubble_gtk.h ('k') | chrome/browser/gtk/location_bar_view_gtk.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "chrome/browser/gtk/info_bubble_gtk.h" 5 #include "chrome/browser/gtk/info_bubble_gtk.h"
6 6
7 #include <gdk/gdkkeysyms.h> 7 #include <gdk/gdkkeysyms.h>
8 #include <gtk/gtk.h> 8 #include <gtk/gtk.h>
9 9
10 #include "app/gfx/gtk_util.h" 10 #include "app/gfx/gtk_util.h"
11 #include "app/gfx/path.h" 11 #include "app/gfx/path.h"
12 #include "app/l10n_util.h" 12 #include "app/l10n_util.h"
13 #include "base/basictypes.h" 13 #include "base/basictypes.h"
14 #include "base/gfx/rect.h" 14 #include "base/gfx/rect.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "chrome/browser/gtk/gtk_theme_provider.h" 16 #include "chrome/browser/gtk/gtk_theme_provider.h"
17 #include "chrome/common/gtk_util.h" 17 #include "chrome/common/gtk_util.h"
18 #include "chrome/common/notification_service.h" 18 #include "chrome/common/notification_service.h"
19 19
20 namespace { 20 namespace {
21 21
22 // The height of the arrow, and the width will be about twice the height. 22 // The height of the arrow, and the width will be about twice the height.
23 const int kArrowSize = 5; 23 const int kArrowSize = 5;
24
24 // Number of pixels to the start of the arrow from the edge of the window. 25 // Number of pixels to the start of the arrow from the edge of the window.
25 const int kArrowX = 13; 26 const int kArrowX = 13;
27
26 // Number of pixels between the tip of the arrow and the region we're 28 // Number of pixels between the tip of the arrow and the region we're
27 // pointing to. 29 // pointing to.
28 const int kArrowToContentPadding = -6; 30 const int kArrowToContentPadding = -6;
31
29 // We draw flat diagonal corners, each corner is an NxN square. 32 // We draw flat diagonal corners, each corner is an NxN square.
30 const int kCornerSize = 3; 33 const int kCornerSize = 3;
34
31 // Margins around the content. 35 // Margins around the content.
32 const int kTopMargin = kArrowSize + kCornerSize + 6; 36 const int kTopMargin = kArrowSize + kCornerSize + 6;
33 const int kBottomMargin = kCornerSize + 6; 37 const int kBottomMargin = kCornerSize + 6;
34 const int kLeftMargin = kCornerSize + 6; 38 const int kLeftMargin = kCornerSize + 6;
35 const int kRightMargin = kCornerSize + 6; 39 const int kRightMargin = kCornerSize + 6;
36 40
37 const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff); 41 const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff);
38 const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63); 42 const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63);
39 43
40 enum FrameType {
41 FRAME_MASK,
42 FRAME_STROKE,
43 };
44
45 // Make the points for our polygon frame, either for fill (the mask), or for
46 // when we stroke the border. NOTE: This seems a bit overcomplicated, but it
47 // requires a bunch of careful fudging to get the pixels rasterized exactly
48 // where we want them, the arrow to have a 1 pixel point, etc.
49 // TODO(deanm): Windows draws with Skia and uses some PNG images for the
50 // corners. This is a lot more work, but they get anti-aliasing.
51 std::vector<GdkPoint> MakeFramePolygonPoints(int width,
52 int height,
53 FrameType type) {
54 using gtk_util::MakeBidiGdkPoint;
55 std::vector<GdkPoint> points;
56
57 bool ltr = l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT;
58 // If we have a stroke, we have to offset some of our points by 1 pixel.
59 // We have to inset by 1 pixel when we draw horizontal lines that are on the
60 // bottom or when we draw vertical lines that are closer to the end (end is
61 // right for ltr).
62 int y_off = (type == FRAME_MASK) ? 0 : -1;
63 // We use this one for LTR.
64 int x_off_l = ltr ? y_off : 0;
65 // We use this one for RTL.
66 int x_off_r = !ltr ? -y_off : 0;
67
68 // Top left corner.
69 points.push_back(MakeBidiGdkPoint(
70 x_off_r, kArrowSize + kCornerSize - 1, width, ltr));
71 points.push_back(MakeBidiGdkPoint(
72 kCornerSize + x_off_r - 1, kArrowSize, width, ltr));
73
74 // The arrow.
75 points.push_back(MakeBidiGdkPoint(
76 kArrowX - kArrowSize + x_off_r, kArrowSize, width, ltr));
77 points.push_back(MakeBidiGdkPoint(
78 kArrowX + x_off_r, 0, width, ltr));
79 points.push_back(MakeBidiGdkPoint(
80 kArrowX + 1 + x_off_l, 0, width, ltr));
81 points.push_back(MakeBidiGdkPoint(
82 kArrowX + kArrowSize + 1 + x_off_l, kArrowSize, width, ltr));
83
84 // Top right corner.
85 points.push_back(MakeBidiGdkPoint(
86 width - kCornerSize + 1 + x_off_l, kArrowSize, width, ltr));
87 points.push_back(MakeBidiGdkPoint(
88 width + x_off_l, kArrowSize + kCornerSize - 1, width, ltr));
89
90 // Bottom right corner.
91 points.push_back(MakeBidiGdkPoint(
92 width + x_off_l, height - kCornerSize, width, ltr));
93 points.push_back(MakeBidiGdkPoint(
94 width - kCornerSize + x_off_r, height + y_off, width, ltr));
95
96 // Bottom left corner.
97 points.push_back(MakeBidiGdkPoint(
98 kCornerSize + x_off_l, height + y_off, width, ltr));
99 points.push_back(MakeBidiGdkPoint(
100 x_off_r, height - kCornerSize, width, ltr));
101
102 return points;
103 }
104
105 gboolean HandleExpose(GtkWidget* widget,
106 GdkEventExpose* event,
107 gpointer unused) {
108 GdkDrawable* drawable = GDK_DRAWABLE(event->window);
109 GdkGC* gc = gdk_gc_new(drawable);
110 gdk_gc_set_rgb_fg_color(gc, &kFrameColor);
111
112 // Stroke the frame border.
113 std::vector<GdkPoint> points = MakeFramePolygonPoints(
114 widget->allocation.width, widget->allocation.height, FRAME_STROKE);
115 gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
116
117 g_object_unref(gc);
118 return FALSE; // Propagate so our children paint, etc.
119 }
120
121 } // namespace 44 } // namespace
122 45
123 // static 46 // static
124 InfoBubbleGtk* InfoBubbleGtk::Show(GtkWindow* toplevel_window, 47 InfoBubbleGtk* InfoBubbleGtk::Show(GtkWindow* toplevel_window,
125 const gfx::Rect& rect, 48 const gfx::Rect& rect,
126 GtkWidget* content, 49 GtkWidget* content,
127 GtkThemeProvider* provider, 50 GtkThemeProvider* provider,
128 InfoBubbleGtkDelegate* delegate) { 51 InfoBubbleGtkDelegate* delegate) {
129 InfoBubbleGtk* bubble = new InfoBubbleGtk(provider); 52 InfoBubbleGtk* bubble = new InfoBubbleGtk(provider);
130 bubble->Init(toplevel_window, rect, content); 53 bubble->Init(toplevel_window, rect, content);
131 bubble->set_delegate(delegate); 54 bubble->set_delegate(delegate);
132 return bubble; 55 return bubble;
133 } 56 }
134 57
135 InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider) 58 InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider)
136 : delegate_(NULL), 59 : delegate_(NULL),
137 window_(NULL), 60 window_(NULL),
138 theme_provider_(provider), 61 theme_provider_(provider),
139 accel_group_(gtk_accel_group_new()), 62 accel_group_(gtk_accel_group_new()),
140 toplevel_window_(NULL), 63 toplevel_window_(NULL),
141 mask_region_(NULL) { 64 mask_region_(NULL),
65 arrow_location_(ARROW_LOCATION_TOP_LEFT) {
142 } 66 }
143 67
144 InfoBubbleGtk::~InfoBubbleGtk() { 68 InfoBubbleGtk::~InfoBubbleGtk() {
145 g_object_unref(accel_group_); 69 g_object_unref(accel_group_);
146 if (mask_region_) { 70 if (mask_region_) {
147 gdk_region_destroy(mask_region_); 71 gdk_region_destroy(mask_region_);
148 mask_region_ = NULL; 72 mask_region_ = NULL;
149 } 73 }
150 74
151 g_signal_handlers_disconnect_by_func( 75 g_signal_handlers_disconnect_by_func(
152 toplevel_window_, 76 toplevel_window_,
153 reinterpret_cast<gpointer>(HandleToplevelConfigureThunk), 77 reinterpret_cast<gpointer>(HandleToplevelConfigureThunk),
154 this); 78 this);
155 g_signal_handlers_disconnect_by_func( 79 g_signal_handlers_disconnect_by_func(
156 toplevel_window_, 80 toplevel_window_,
157 reinterpret_cast<gpointer>(HandleToplevelUnmapThunk), 81 reinterpret_cast<gpointer>(HandleToplevelUnmapThunk),
158 this); 82 this);
159 toplevel_window_ = NULL; 83 toplevel_window_ = NULL;
160 } 84 }
161 85
162 void InfoBubbleGtk::Init(GtkWindow* toplevel_window, 86 void InfoBubbleGtk::Init(GtkWindow* toplevel_window,
163 const gfx::Rect& rect, 87 const gfx::Rect& rect,
164 GtkWidget* content) { 88 GtkWidget* content) {
165 DCHECK(!window_); 89 DCHECK(!window_);
166 toplevel_window_ = toplevel_window; 90 toplevel_window_ = toplevel_window;
167 rect_ = rect; 91 rect_ = rect;
168 92
169 window_ = gtk_window_new(GTK_WINDOW_POPUP); 93 window_ = gtk_window_new(GTK_WINDOW_POPUP);
170 gtk_widget_set_app_paintable(window_, TRUE); 94 gtk_widget_set_app_paintable(window_, TRUE);
171 // Have GTK double buffer around the expose signal.
172 gtk_widget_set_double_buffered(window_, TRUE);
173 95
174 // Attach our accelerator group to the window with an escape accelerator. 96 // Attach our accelerator group to the window with an escape accelerator.
175 gtk_accel_group_connect(accel_group_, GDK_Escape, 97 gtk_accel_group_connect(accel_group_, GDK_Escape,
176 static_cast<GdkModifierType>(0), static_cast<GtkAccelFlags>(0), 98 static_cast<GdkModifierType>(0), static_cast<GtkAccelFlags>(0),
177 g_cclosure_new(G_CALLBACK(&HandleEscapeThunk), this, NULL)); 99 g_cclosure_new(G_CALLBACK(&HandleEscapeThunk), this, NULL));
178 gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_); 100 gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_);
179 101
180 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); 102 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
181 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 103 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
182 kTopMargin, kBottomMargin, 104 kTopMargin, kBottomMargin,
(...skipping 12 matching lines...) Expand all
195 MoveWindow(); 117 MoveWindow();
196 GtkRequisition req; 118 GtkRequisition req;
197 gtk_widget_size_request(window_, &req); 119 gtk_widget_size_request(window_, &req);
198 120
199 StackWindow(); 121 StackWindow();
200 122
201 gtk_widget_add_events(window_, GDK_BUTTON_PRESS_MASK | 123 gtk_widget_add_events(window_, GDK_BUTTON_PRESS_MASK |
202 GDK_BUTTON_RELEASE_MASK); 124 GDK_BUTTON_RELEASE_MASK);
203 125
204 g_signal_connect(window_, "expose-event", 126 g_signal_connect(window_, "expose-event",
205 G_CALLBACK(HandleExpose), NULL); 127 G_CALLBACK(HandleExposeThunk), this);
206 g_signal_connect(window_, "size-allocate", 128 g_signal_connect(window_, "size-allocate",
207 G_CALLBACK(HandleSizeAllocateThunk), this); 129 G_CALLBACK(HandleSizeAllocateThunk), this);
208 g_signal_connect(window_, "button-press-event", 130 g_signal_connect(window_, "button-press-event",
209 G_CALLBACK(&HandleButtonPressThunk), this); 131 G_CALLBACK(&HandleButtonPressThunk), this);
210 g_signal_connect(window_, "destroy", 132 g_signal_connect(window_, "destroy",
211 G_CALLBACK(&HandleDestroyThunk), this); 133 G_CALLBACK(&HandleDestroyThunk), this);
212 134
213 g_signal_connect(toplevel_window, "configure-event", 135 g_signal_connect(toplevel_window, "configure-event",
214 G_CALLBACK(&HandleToplevelConfigureThunk), this); 136 G_CALLBACK(&HandleToplevelConfigureThunk), this);
215 g_signal_connect(toplevel_window, "unmap-event", 137 g_signal_connect(toplevel_window, "unmap-event",
(...skipping 17 matching lines...) Expand all
233 GTK_WINDOW(window_)); 155 GTK_WINDOW(window_));
234 gtk_grab_add(window_); 156 gtk_grab_add(window_);
235 157
236 GrabPointerAndKeyboard(); 158 GrabPointerAndKeyboard();
237 159
238 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, 160 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
239 NotificationService::AllSources()); 161 NotificationService::AllSources());
240 theme_provider_->InitThemesFor(this); 162 theme_provider_->InitThemesFor(this);
241 } 163 }
242 164
165 // NOTE: This seems a bit overcomplicated, but it requires a bunch of careful
166 // fudging to get the pixels rasterized exactly where we want them, the arrow to
167 // have a 1 pixel point, etc.
168 // TODO(deanm): Windows draws with Skia and uses some PNG images for the
169 // corners. This is a lot more work, but they get anti-aliasing.
170 // static
171 std::vector<GdkPoint> InfoBubbleGtk::MakeFramePolygonPoints(
172 ArrowLocationGtk arrow_location,
173 int width,
174 int height,
175 FrameType type) {
176 using gtk_util::MakeBidiGdkPoint;
177 std::vector<GdkPoint> points;
178
179 // This name isn't completely accurate; the arrow location can differ from its
180 // expected location for LTR/RTL if needed for the bubble to fit onscreen.
181 bool ltr = (arrow_location == ARROW_LOCATION_TOP_LEFT);
182
183 // If we have a stroke, we have to offset some of our points by 1 pixel.
184 // We have to inset by 1 pixel when we draw horizontal lines that are on the
185 // bottom or when we draw vertical lines that are closer to the end (end is
186 // right for ltr).
187 int y_off = (type == FRAME_MASK) ? 0 : -1;
188 // We use this one for LTR.
189 int x_off_l = ltr ? y_off : 0;
190 // We use this one for RTL.
191 int x_off_r = !ltr ? -y_off : 0;
192
193 // Top left corner.
194 points.push_back(MakeBidiGdkPoint(
195 x_off_r, kArrowSize + kCornerSize - 1, width, ltr));
196 points.push_back(MakeBidiGdkPoint(
197 kCornerSize + x_off_r - 1, kArrowSize, width, ltr));
198
199 // The arrow.
200 points.push_back(MakeBidiGdkPoint(
201 kArrowX - kArrowSize + x_off_r, kArrowSize, width, ltr));
202 points.push_back(MakeBidiGdkPoint(
203 kArrowX + x_off_r, 0, width, ltr));
204 points.push_back(MakeBidiGdkPoint(
205 kArrowX + 1 + x_off_l, 0, width, ltr));
206 points.push_back(MakeBidiGdkPoint(
207 kArrowX + kArrowSize + 1 + x_off_l, kArrowSize, width, ltr));
208
209 // Top right corner.
210 points.push_back(MakeBidiGdkPoint(
211 width - kCornerSize + 1 + x_off_l, kArrowSize, width, ltr));
212 points.push_back(MakeBidiGdkPoint(
213 width + x_off_l, kArrowSize + kCornerSize - 1, width, ltr));
214
215 // Bottom right corner.
216 points.push_back(MakeBidiGdkPoint(
217 width + x_off_l, height - kCornerSize, width, ltr));
218 points.push_back(MakeBidiGdkPoint(
219 width - kCornerSize + x_off_r, height + y_off, width, ltr));
220
221 // Bottom left corner.
222 points.push_back(MakeBidiGdkPoint(
223 kCornerSize + x_off_l, height + y_off, width, ltr));
224 points.push_back(MakeBidiGdkPoint(
225 x_off_r, height - kCornerSize, width, ltr));
226
227 return points;
228 }
229
230 InfoBubbleGtk::ArrowLocationGtk InfoBubbleGtk::GetArrowLocation(
231 int arrow_x, int width) {
232 bool ltr = (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT);
233 int screen_width = gdk_screen_get_width(gdk_screen_get_default());
234
235 bool left_is_onscreen = (arrow_x - kArrowX + width < screen_width);
236 bool right_is_onscreen = (arrow_x + kArrowX - width >= 0);
237
238 // Use the expected location for our LTR/RTL-ness if it fits onscreen, use
239 // whatever fits otherwise, and use the expected location if neither fits.
240 if (left_is_onscreen && (ltr || !right_is_onscreen))
241 return ARROW_LOCATION_TOP_LEFT;
242 if (right_is_onscreen && (!ltr || !left_is_onscreen))
243 return ARROW_LOCATION_TOP_RIGHT;
244 return (ltr ? ARROW_LOCATION_TOP_LEFT : ARROW_LOCATION_TOP_RIGHT);
245 }
246
247 bool InfoBubbleGtk::UpdateArrowLocation() {
248 gint toplevel_x = 0, toplevel_y = 0;
249 gdk_window_get_position(
250 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y);
251
252 ArrowLocationGtk old_location = arrow_location_;
253 arrow_location_ = GetArrowLocation(
254 toplevel_x + rect_.x() + (rect_.width() / 2), // arrow_x
255 window_->allocation.width);
256
257 if (arrow_location_ != old_location) {
258 UpdateWindowShape();
259 MoveWindow();
260 // We need to redraw the entire window to repaint its border.
261 gtk_widget_queue_draw(window_);
262 return true;
263 }
264 return false;
265 }
266
267 void InfoBubbleGtk::UpdateWindowShape() {
268 if (mask_region_) {
269 gdk_region_destroy(mask_region_);
270 mask_region_ = NULL;
271 }
272 std::vector<GdkPoint> points = MakeFramePolygonPoints(
273 arrow_location_, window_->allocation.width, window_->allocation.height,
274 FRAME_MASK);
275 mask_region_ = gdk_region_polygon(&points[0],
276 points.size(),
277 GDK_EVEN_ODD_RULE);
278 gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0);
279 }
280
243 void InfoBubbleGtk::MoveWindow() { 281 void InfoBubbleGtk::MoveWindow() {
244 gint toplevel_x = 0, toplevel_y = 0; 282 gint toplevel_x = 0, toplevel_y = 0;
245 gdk_window_get_position( 283 gdk_window_get_position(
246 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y); 284 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y);
247 285
248 gint screen_x = 0; 286 gint screen_x = 0;
249 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) { 287 if (arrow_location_ == ARROW_LOCATION_TOP_LEFT) {
288 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) - kArrowX;
289 } else if (arrow_location_ == ARROW_LOCATION_TOP_RIGHT) {
250 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) - 290 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) -
251 window_->allocation.width + kArrowX; 291 window_->allocation.width + kArrowX;
252 } else { 292 } else {
253 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) - kArrowX; 293 NOTREACHED();
254 } 294 }
255 295
256 gint screen_y = toplevel_y + rect_.y() + rect_.height() + 296 gint screen_y = toplevel_y + rect_.y() + rect_.height() +
257 kArrowToContentPadding; 297 kArrowToContentPadding;
258 298
259 gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y); 299 gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y);
260 } 300 }
261 301
262 void InfoBubbleGtk::StackWindow() { 302 void InfoBubbleGtk::StackWindow() {
263 // Stack our window directly above the toplevel window. 303 // Stack our window directly above the toplevel window.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 DLOG(ERROR) << "Unable to grab keyboard (status=" 358 DLOG(ERROR) << "Unable to grab keyboard (status="
319 << keyboard_grab_status << ")"; 359 << keyboard_grab_status << ")";
320 } 360 }
321 } 361 }
322 362
323 gboolean InfoBubbleGtk::HandleEscape() { 363 gboolean InfoBubbleGtk::HandleEscape() {
324 CloseInternal(true); // Close by escape. 364 CloseInternal(true); // Close by escape.
325 return TRUE; 365 return TRUE;
326 } 366 }
327 367
368 gboolean InfoBubbleGtk::HandleExpose() {
369 GdkDrawable* drawable = GDK_DRAWABLE(window_->window);
370 GdkGC* gc = gdk_gc_new(drawable);
371 gdk_gc_set_rgb_fg_color(gc, &kFrameColor);
372
373 // Stroke the frame border.
374 std::vector<GdkPoint> points = MakeFramePolygonPoints(
375 arrow_location_, window_->allocation.width, window_->allocation.height,
376 FRAME_STROKE);
377 gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
378
379 g_object_unref(gc);
380 return FALSE; // Propagate so our children paint, etc.
381 }
382
328 // When our size is initially allocated or changed, we need to recompute 383 // When our size is initially allocated or changed, we need to recompute
329 // and apply our shape mask region. 384 // and apply our shape mask region.
330 void InfoBubbleGtk::HandleSizeAllocate() { 385 void InfoBubbleGtk::HandleSizeAllocate() {
331 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) 386 if (!UpdateArrowLocation()) {
332 MoveWindow(); 387 UpdateWindowShape();
333 388 if (arrow_location_ == ARROW_LOCATION_TOP_RIGHT)
334 DCHECK(window_->allocation.x == 0 && window_->allocation.y == 0); 389 MoveWindow();
335 if (mask_region_) {
336 gdk_region_destroy(mask_region_);
337 mask_region_ = NULL;
338 } 390 }
339 std::vector<GdkPoint> points = MakeFramePolygonPoints(
340 window_->allocation.width, window_->allocation.height, FRAME_MASK);
341 mask_region_ = gdk_region_polygon(&points[0],
342 points.size(),
343 GDK_EVEN_ODD_RULE);
344 gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0);
345 } 391 }
346 392
347 gboolean InfoBubbleGtk::HandleButtonPress(GdkEventButton* event) { 393 gboolean InfoBubbleGtk::HandleButtonPress(GdkEventButton* event) {
348 // If we got a click in our own window, that's okay (we need to additionally 394 // If we got a click in our own window, that's okay (we need to additionally
349 // check that it falls within our bounds, since we've grabbed the pointer and 395 // check that it falls within our bounds, since we've grabbed the pointer and
350 // some events that actually occurred in other windows will be reported with 396 // some events that actually occurred in other windows will be reported with
351 // respect to our window). 397 // respect to our window).
352 if (event->window == window_->window && 398 if (event->window == window_->window &&
353 (mask_region_ && gdk_region_point_in(mask_region_, event->x, event->y))) { 399 (mask_region_ && gdk_region_point_in(mask_region_, event->x, event->y))) {
354 return FALSE; // Propagate. 400 return FALSE; // Propagate.
(...skipping 12 matching lines...) Expand all
367 413
368 gboolean InfoBubbleGtk::HandleDestroy() { 414 gboolean InfoBubbleGtk::HandleDestroy() {
369 // We are self deleting, we have a destroy signal setup to catch when we 415 // We are self deleting, we have a destroy signal setup to catch when we
370 // destroy the widget manually, or the window was closed via X. This will 416 // destroy the widget manually, or the window was closed via X. This will
371 // delete the InfoBubbleGtk object. 417 // delete the InfoBubbleGtk object.
372 delete this; 418 delete this;
373 return FALSE; // Propagate. 419 return FALSE; // Propagate.
374 } 420 }
375 421
376 gboolean InfoBubbleGtk::HandleToplevelConfigure(GdkEventConfigure* event) { 422 gboolean InfoBubbleGtk::HandleToplevelConfigure(GdkEventConfigure* event) {
377 MoveWindow(); 423 if (!UpdateArrowLocation())
424 MoveWindow();
378 StackWindow(); 425 StackWindow();
379 return FALSE; 426 return FALSE;
380 } 427 }
381 428
382 gboolean InfoBubbleGtk::HandleToplevelUnmap() { 429 gboolean InfoBubbleGtk::HandleToplevelUnmap() {
383 Close(); 430 Close();
384 return FALSE; 431 return FALSE;
385 } 432 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/info_bubble_gtk.h ('k') | chrome/browser/gtk/location_bar_view_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698