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 #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" |
(...skipping 29 matching lines...) Expand all Loading... |
40 | 40 |
41 const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff); | 41 const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff); |
42 const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63); | 42 const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63); |
43 | 43 |
44 } // namespace | 44 } // namespace |
45 | 45 |
46 // static | 46 // static |
47 InfoBubbleGtk* InfoBubbleGtk::Show(GtkWindow* toplevel_window, | 47 InfoBubbleGtk* InfoBubbleGtk::Show(GtkWindow* toplevel_window, |
48 const gfx::Rect& rect, | 48 const gfx::Rect& rect, |
49 GtkWidget* content, | 49 GtkWidget* content, |
| 50 ArrowLocationGtk arrow_location, |
50 GtkThemeProvider* provider, | 51 GtkThemeProvider* provider, |
51 InfoBubbleGtkDelegate* delegate) { | 52 InfoBubbleGtkDelegate* delegate) { |
52 InfoBubbleGtk* bubble = new InfoBubbleGtk(provider); | 53 InfoBubbleGtk* bubble = new InfoBubbleGtk(provider); |
53 bubble->Init(toplevel_window, rect, content); | 54 bubble->Init(toplevel_window, rect, content, arrow_location); |
54 bubble->set_delegate(delegate); | 55 bubble->set_delegate(delegate); |
55 return bubble; | 56 return bubble; |
56 } | 57 } |
57 | 58 |
58 InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider) | 59 InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider) |
59 : delegate_(NULL), | 60 : delegate_(NULL), |
60 window_(NULL), | 61 window_(NULL), |
61 theme_provider_(provider), | 62 theme_provider_(provider), |
62 accel_group_(gtk_accel_group_new()), | 63 accel_group_(gtk_accel_group_new()), |
63 toplevel_window_(NULL), | 64 toplevel_window_(NULL), |
64 mask_region_(NULL), | 65 mask_region_(NULL), |
65 arrow_location_(ARROW_LOCATION_TOP_LEFT) { | 66 preferred_arrow_location_(ARROW_LOCATION_TOP_LEFT), |
| 67 current_arrow_location_(ARROW_LOCATION_TOP_LEFT) { |
66 } | 68 } |
67 | 69 |
68 InfoBubbleGtk::~InfoBubbleGtk() { | 70 InfoBubbleGtk::~InfoBubbleGtk() { |
69 g_object_unref(accel_group_); | 71 g_object_unref(accel_group_); |
70 if (mask_region_) { | 72 if (mask_region_) { |
71 gdk_region_destroy(mask_region_); | 73 gdk_region_destroy(mask_region_); |
72 mask_region_ = NULL; | 74 mask_region_ = NULL; |
73 } | 75 } |
74 | 76 |
75 g_signal_handlers_disconnect_by_func( | 77 g_signal_handlers_disconnect_by_func( |
76 toplevel_window_, | 78 toplevel_window_, |
77 reinterpret_cast<gpointer>(HandleToplevelConfigureThunk), | 79 reinterpret_cast<gpointer>(HandleToplevelConfigureThunk), |
78 this); | 80 this); |
79 g_signal_handlers_disconnect_by_func( | 81 g_signal_handlers_disconnect_by_func( |
80 toplevel_window_, | 82 toplevel_window_, |
81 reinterpret_cast<gpointer>(HandleToplevelUnmapThunk), | 83 reinterpret_cast<gpointer>(HandleToplevelUnmapThunk), |
82 this); | 84 this); |
83 toplevel_window_ = NULL; | 85 toplevel_window_ = NULL; |
84 } | 86 } |
85 | 87 |
86 void InfoBubbleGtk::Init(GtkWindow* toplevel_window, | 88 void InfoBubbleGtk::Init(GtkWindow* toplevel_window, |
87 const gfx::Rect& rect, | 89 const gfx::Rect& rect, |
88 GtkWidget* content) { | 90 GtkWidget* content, |
| 91 ArrowLocationGtk arrow_location) { |
89 DCHECK(!window_); | 92 DCHECK(!window_); |
90 toplevel_window_ = toplevel_window; | 93 toplevel_window_ = toplevel_window; |
91 rect_ = rect; | 94 rect_ = rect; |
| 95 preferred_arrow_location_ = arrow_location; |
92 | 96 |
93 window_ = gtk_window_new(GTK_WINDOW_POPUP); | 97 window_ = gtk_window_new(GTK_WINDOW_POPUP); |
94 gtk_widget_set_app_paintable(window_, TRUE); | 98 gtk_widget_set_app_paintable(window_, TRUE); |
95 | 99 |
96 // Attach our accelerator group to the window with an escape accelerator. | 100 // Attach our accelerator group to the window with an escape accelerator. |
97 gtk_accel_group_connect(accel_group_, GDK_Escape, | 101 gtk_accel_group_connect(accel_group_, GDK_Escape, |
98 static_cast<GdkModifierType>(0), static_cast<GtkAccelFlags>(0), | 102 static_cast<GdkModifierType>(0), static_cast<GtkAccelFlags>(0), |
99 g_cclosure_new(G_CALLBACK(&HandleEscapeThunk), this, NULL)); | 103 g_cclosure_new(G_CALLBACK(&HandleEscapeThunk), this, NULL)); |
100 gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_); | 104 gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_); |
101 | 105 |
102 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); | 106 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); |
103 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), | 107 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), |
104 kTopMargin, kBottomMargin, | 108 kTopMargin, kBottomMargin, |
105 kLeftMargin, kRightMargin); | 109 kLeftMargin, kRightMargin); |
106 | 110 |
107 gtk_container_add(GTK_CONTAINER(alignment), content); | 111 gtk_container_add(GTK_CONTAINER(alignment), content); |
108 gtk_container_add(GTK_CONTAINER(window_), alignment); | 112 gtk_container_add(GTK_CONTAINER(window_), alignment); |
109 | 113 |
110 // GtkWidget only exposes the bitmap mask interface. Use GDK to more | 114 // GtkWidget only exposes the bitmap mask interface. Use GDK to more |
111 // efficently mask a GdkRegion. Make sure the window is realized during | 115 // efficently mask a GdkRegion. Make sure the window is realized during |
112 // HandleSizeAllocate, so the mask can be applied to the GdkWindow. | 116 // HandleSizeAllocate, so the mask can be applied to the GdkWindow. |
113 gtk_widget_realize(window_); | 117 gtk_widget_realize(window_); |
114 | 118 |
115 // For RTL, we will have to move the window again when it is allocated, but | 119 UpdateArrowLocation(true); // Force move and reshape. |
116 // this should be somewhat close to its final position. | |
117 MoveWindow(); | |
118 GtkRequisition req; | |
119 gtk_widget_size_request(window_, &req); | |
120 | |
121 StackWindow(); | 120 StackWindow(); |
122 | 121 |
123 gtk_widget_add_events(window_, GDK_BUTTON_PRESS_MASK | | 122 gtk_widget_add_events(window_, GDK_BUTTON_PRESS_MASK | |
124 GDK_BUTTON_RELEASE_MASK); | 123 GDK_BUTTON_RELEASE_MASK); |
125 | 124 |
126 g_signal_connect(window_, "expose-event", | 125 g_signal_connect(window_, "expose-event", |
127 G_CALLBACK(HandleExposeThunk), this); | 126 G_CALLBACK(HandleExposeThunk), this); |
128 g_signal_connect(window_, "size-allocate", | 127 g_signal_connect(window_, "size-allocate", |
129 G_CALLBACK(HandleSizeAllocateThunk), this); | 128 G_CALLBACK(HandleSizeAllocateThunk), this); |
130 g_signal_connect(window_, "button-press-event", | 129 g_signal_connect(window_, "button-press-event", |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 // corners. This is a lot more work, but they get anti-aliasing. | 168 // corners. This is a lot more work, but they get anti-aliasing. |
170 // static | 169 // static |
171 std::vector<GdkPoint> InfoBubbleGtk::MakeFramePolygonPoints( | 170 std::vector<GdkPoint> InfoBubbleGtk::MakeFramePolygonPoints( |
172 ArrowLocationGtk arrow_location, | 171 ArrowLocationGtk arrow_location, |
173 int width, | 172 int width, |
174 int height, | 173 int height, |
175 FrameType type) { | 174 FrameType type) { |
176 using gtk_util::MakeBidiGdkPoint; | 175 using gtk_util::MakeBidiGdkPoint; |
177 std::vector<GdkPoint> points; | 176 std::vector<GdkPoint> points; |
178 | 177 |
179 // This name isn't completely accurate; the arrow location can differ from its | 178 bool on_left = (arrow_location == ARROW_LOCATION_TOP_LEFT); |
180 // expected location for LTR/RTL if needed for the bubble to fit onscreen. | |
181 bool ltr = (arrow_location == ARROW_LOCATION_TOP_LEFT); | |
182 | 179 |
183 // If we have a stroke, we have to offset some of our points by 1 pixel. | 180 // If we're stroking the frame, we need to offset some of our points by 1 |
184 // We have to inset by 1 pixel when we draw horizontal lines that are on the | 181 // pixel. We do this when we draw horizontal lines that are on the bottom or |
185 // bottom or when we draw vertical lines that are closer to the end (end is | 182 // when we draw vertical lines that are closer to the end (where "end" is the |
186 // right for ltr). | 183 // right side for ARROW_LOCATION_TOP_LEFT). |
187 int y_off = (type == FRAME_MASK) ? 0 : -1; | 184 int y_off = (type == FRAME_MASK) ? 0 : -1; |
188 // We use this one for LTR. | 185 // We use this one for arrows located on the left. |
189 int x_off_l = ltr ? y_off : 0; | 186 int x_off_l = on_left ? y_off : 0; |
190 // We use this one for RTL. | 187 // We use this one for RTL. |
191 int x_off_r = !ltr ? -y_off : 0; | 188 int x_off_r = !on_left ? -y_off : 0; |
192 | 189 |
193 // Top left corner. | 190 // Top left corner. |
194 points.push_back(MakeBidiGdkPoint( | 191 points.push_back(MakeBidiGdkPoint( |
195 x_off_r, kArrowSize + kCornerSize - 1, width, ltr)); | 192 x_off_r, kArrowSize + kCornerSize - 1, width, on_left)); |
196 points.push_back(MakeBidiGdkPoint( | 193 points.push_back(MakeBidiGdkPoint( |
197 kCornerSize + x_off_r - 1, kArrowSize, width, ltr)); | 194 kCornerSize + x_off_r - 1, kArrowSize, width, on_left)); |
198 | 195 |
199 // The arrow. | 196 // The arrow. |
200 points.push_back(MakeBidiGdkPoint( | 197 points.push_back(MakeBidiGdkPoint( |
201 kArrowX - kArrowSize + x_off_r, kArrowSize, width, ltr)); | 198 kArrowX - kArrowSize + x_off_r, kArrowSize, width, on_left)); |
202 points.push_back(MakeBidiGdkPoint( | 199 points.push_back(MakeBidiGdkPoint( |
203 kArrowX + x_off_r, 0, width, ltr)); | 200 kArrowX + x_off_r, 0, width, on_left)); |
204 points.push_back(MakeBidiGdkPoint( | 201 points.push_back(MakeBidiGdkPoint( |
205 kArrowX + 1 + x_off_l, 0, width, ltr)); | 202 kArrowX + 1 + x_off_l, 0, width, on_left)); |
206 points.push_back(MakeBidiGdkPoint( | 203 points.push_back(MakeBidiGdkPoint( |
207 kArrowX + kArrowSize + 1 + x_off_l, kArrowSize, width, ltr)); | 204 kArrowX + kArrowSize + 1 + x_off_l, kArrowSize, width, on_left)); |
208 | 205 |
209 // Top right corner. | 206 // Top right corner. |
210 points.push_back(MakeBidiGdkPoint( | 207 points.push_back(MakeBidiGdkPoint( |
211 width - kCornerSize + 1 + x_off_l, kArrowSize, width, ltr)); | 208 width - kCornerSize + 1 + x_off_l, kArrowSize, width, on_left)); |
212 points.push_back(MakeBidiGdkPoint( | 209 points.push_back(MakeBidiGdkPoint( |
213 width + x_off_l, kArrowSize + kCornerSize - 1, width, ltr)); | 210 width + x_off_l, kArrowSize + kCornerSize - 1, width, on_left)); |
214 | 211 |
215 // Bottom right corner. | 212 // Bottom right corner. |
216 points.push_back(MakeBidiGdkPoint( | 213 points.push_back(MakeBidiGdkPoint( |
217 width + x_off_l, height - kCornerSize, width, ltr)); | 214 width + x_off_l, height - kCornerSize, width, on_left)); |
218 points.push_back(MakeBidiGdkPoint( | 215 points.push_back(MakeBidiGdkPoint( |
219 width - kCornerSize + x_off_r, height + y_off, width, ltr)); | 216 width - kCornerSize + x_off_r, height + y_off, width, on_left)); |
220 | 217 |
221 // Bottom left corner. | 218 // Bottom left corner. |
222 points.push_back(MakeBidiGdkPoint( | 219 points.push_back(MakeBidiGdkPoint( |
223 kCornerSize + x_off_l, height + y_off, width, ltr)); | 220 kCornerSize + x_off_l, height + y_off, width, on_left)); |
224 points.push_back(MakeBidiGdkPoint( | 221 points.push_back(MakeBidiGdkPoint( |
225 x_off_r, height - kCornerSize, width, ltr)); | 222 x_off_r, height - kCornerSize, width, on_left)); |
226 | 223 |
227 return points; | 224 return points; |
228 } | 225 } |
229 | 226 |
230 InfoBubbleGtk::ArrowLocationGtk InfoBubbleGtk::GetArrowLocation( | 227 InfoBubbleGtk::ArrowLocationGtk InfoBubbleGtk::GetArrowLocation( |
231 int arrow_x, int width) { | 228 ArrowLocationGtk preferred_location, int arrow_x, int width) { |
232 bool ltr = (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT); | 229 bool wants_left = (preferred_location == ARROW_LOCATION_TOP_LEFT); |
233 int screen_width = gdk_screen_get_width(gdk_screen_get_default()); | 230 int screen_width = gdk_screen_get_width(gdk_screen_get_default()); |
234 | 231 |
235 bool left_is_onscreen = (arrow_x - kArrowX + width < screen_width); | 232 bool left_is_onscreen = (arrow_x - kArrowX + width < screen_width); |
236 bool right_is_onscreen = (arrow_x + kArrowX - width >= 0); | 233 bool right_is_onscreen = (arrow_x + kArrowX - width >= 0); |
237 | 234 |
238 // Use the expected location for our LTR/RTL-ness if it fits onscreen, use | 235 // Use the requested location if it fits onscreen, use whatever fits |
239 // whatever fits otherwise, and use the expected location if neither fits. | 236 // otherwise, and use the requested location if neither fits. |
240 if (left_is_onscreen && (ltr || !right_is_onscreen)) | 237 if (left_is_onscreen && (wants_left || !right_is_onscreen)) |
241 return ARROW_LOCATION_TOP_LEFT; | 238 return ARROW_LOCATION_TOP_LEFT; |
242 if (right_is_onscreen && (!ltr || !left_is_onscreen)) | 239 if (right_is_onscreen && (!wants_left || !left_is_onscreen)) |
243 return ARROW_LOCATION_TOP_RIGHT; | 240 return ARROW_LOCATION_TOP_RIGHT; |
244 return (ltr ? ARROW_LOCATION_TOP_LEFT : ARROW_LOCATION_TOP_RIGHT); | 241 return (wants_left ? ARROW_LOCATION_TOP_LEFT : ARROW_LOCATION_TOP_RIGHT); |
245 } | 242 } |
246 | 243 |
247 bool InfoBubbleGtk::UpdateArrowLocation() { | 244 bool InfoBubbleGtk::UpdateArrowLocation(bool force_move_and_reshape) { |
248 gint toplevel_x = 0, toplevel_y = 0; | 245 gint toplevel_x = 0, toplevel_y = 0; |
249 gdk_window_get_position( | 246 gdk_window_get_position( |
250 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y); | 247 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y); |
251 | 248 |
252 ArrowLocationGtk old_location = arrow_location_; | 249 ArrowLocationGtk old_location = current_arrow_location_; |
253 arrow_location_ = GetArrowLocation( | 250 current_arrow_location_ = GetArrowLocation( |
| 251 preferred_arrow_location_, |
254 toplevel_x + rect_.x() + (rect_.width() / 2), // arrow_x | 252 toplevel_x + rect_.x() + (rect_.width() / 2), // arrow_x |
255 window_->allocation.width); | 253 window_->allocation.width); |
256 | 254 |
257 if (arrow_location_ != old_location) { | 255 if (force_move_and_reshape || current_arrow_location_ != old_location) { |
258 UpdateWindowShape(); | 256 UpdateWindowShape(); |
259 MoveWindow(); | 257 MoveWindow(); |
260 // We need to redraw the entire window to repaint its border. | 258 // We need to redraw the entire window to repaint its border. |
261 gtk_widget_queue_draw(window_); | 259 gtk_widget_queue_draw(window_); |
262 return true; | 260 return true; |
263 } | 261 } |
264 return false; | 262 return false; |
265 } | 263 } |
266 | 264 |
267 void InfoBubbleGtk::UpdateWindowShape() { | 265 void InfoBubbleGtk::UpdateWindowShape() { |
268 if (mask_region_) { | 266 if (mask_region_) { |
269 gdk_region_destroy(mask_region_); | 267 gdk_region_destroy(mask_region_); |
270 mask_region_ = NULL; | 268 mask_region_ = NULL; |
271 } | 269 } |
272 std::vector<GdkPoint> points = MakeFramePolygonPoints( | 270 std::vector<GdkPoint> points = MakeFramePolygonPoints( |
273 arrow_location_, window_->allocation.width, window_->allocation.height, | 271 current_arrow_location_, |
| 272 window_->allocation.width, window_->allocation.height, |
274 FRAME_MASK); | 273 FRAME_MASK); |
275 mask_region_ = gdk_region_polygon(&points[0], | 274 mask_region_ = gdk_region_polygon(&points[0], |
276 points.size(), | 275 points.size(), |
277 GDK_EVEN_ODD_RULE); | 276 GDK_EVEN_ODD_RULE); |
278 gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0); | 277 gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0); |
279 } | 278 } |
280 | 279 |
281 void InfoBubbleGtk::MoveWindow() { | 280 void InfoBubbleGtk::MoveWindow() { |
282 gint toplevel_x = 0, toplevel_y = 0; | 281 gint toplevel_x = 0, toplevel_y = 0; |
283 gdk_window_get_position( | 282 gdk_window_get_position( |
284 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y); | 283 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y); |
285 | 284 |
286 gint screen_x = 0; | 285 gint screen_x = 0; |
287 if (arrow_location_ == ARROW_LOCATION_TOP_LEFT) { | 286 if (current_arrow_location_ == ARROW_LOCATION_TOP_LEFT) { |
288 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) - kArrowX; | 287 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) - kArrowX; |
289 } else if (arrow_location_ == ARROW_LOCATION_TOP_RIGHT) { | 288 } else if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT) { |
290 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) - | 289 screen_x = toplevel_x + rect_.x() + (rect_.width() / 2) - |
291 window_->allocation.width + kArrowX; | 290 window_->allocation.width + kArrowX; |
292 } else { | 291 } else { |
293 NOTREACHED(); | 292 NOTREACHED(); |
294 } | 293 } |
295 | 294 |
296 gint screen_y = toplevel_y + rect_.y() + rect_.height() + | 295 gint screen_y = toplevel_y + rect_.y() + rect_.height() + |
297 kArrowToContentPadding; | 296 kArrowToContentPadding; |
298 | 297 |
299 gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y); | 298 gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 return TRUE; | 364 return TRUE; |
366 } | 365 } |
367 | 366 |
368 gboolean InfoBubbleGtk::HandleExpose() { | 367 gboolean InfoBubbleGtk::HandleExpose() { |
369 GdkDrawable* drawable = GDK_DRAWABLE(window_->window); | 368 GdkDrawable* drawable = GDK_DRAWABLE(window_->window); |
370 GdkGC* gc = gdk_gc_new(drawable); | 369 GdkGC* gc = gdk_gc_new(drawable); |
371 gdk_gc_set_rgb_fg_color(gc, &kFrameColor); | 370 gdk_gc_set_rgb_fg_color(gc, &kFrameColor); |
372 | 371 |
373 // Stroke the frame border. | 372 // Stroke the frame border. |
374 std::vector<GdkPoint> points = MakeFramePolygonPoints( | 373 std::vector<GdkPoint> points = MakeFramePolygonPoints( |
375 arrow_location_, window_->allocation.width, window_->allocation.height, | 374 current_arrow_location_, |
| 375 window_->allocation.width, window_->allocation.height, |
376 FRAME_STROKE); | 376 FRAME_STROKE); |
377 gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size()); | 377 gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size()); |
378 | 378 |
379 g_object_unref(gc); | 379 g_object_unref(gc); |
380 return FALSE; // Propagate so our children paint, etc. | 380 return FALSE; // Propagate so our children paint, etc. |
381 } | 381 } |
382 | 382 |
383 // 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 |
384 // and apply our shape mask region. | 384 // and apply our shape mask region. |
385 void InfoBubbleGtk::HandleSizeAllocate() { | 385 void InfoBubbleGtk::HandleSizeAllocate() { |
386 if (!UpdateArrowLocation()) { | 386 if (!UpdateArrowLocation(false)) { |
387 UpdateWindowShape(); | 387 UpdateWindowShape(); |
388 if (arrow_location_ == ARROW_LOCATION_TOP_RIGHT) | 388 if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT) |
389 MoveWindow(); | 389 MoveWindow(); |
390 } | 390 } |
391 } | 391 } |
392 | 392 |
393 gboolean InfoBubbleGtk::HandleButtonPress(GdkEventButton* event) { | 393 gboolean InfoBubbleGtk::HandleButtonPress(GdkEventButton* event) { |
394 // 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 |
395 // 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 |
396 // 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 |
397 // respect to our window). | 397 // respect to our window). |
398 if (event->window == window_->window && | 398 if (event->window == window_->window && |
(...skipping 14 matching lines...) Expand all Loading... |
413 | 413 |
414 gboolean InfoBubbleGtk::HandleDestroy() { | 414 gboolean InfoBubbleGtk::HandleDestroy() { |
415 // 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 |
416 // 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 |
417 // delete the InfoBubbleGtk object. | 417 // delete the InfoBubbleGtk object. |
418 delete this; | 418 delete this; |
419 return FALSE; // Propagate. | 419 return FALSE; // Propagate. |
420 } | 420 } |
421 | 421 |
422 gboolean InfoBubbleGtk::HandleToplevelConfigure(GdkEventConfigure* event) { | 422 gboolean InfoBubbleGtk::HandleToplevelConfigure(GdkEventConfigure* event) { |
423 if (!UpdateArrowLocation()) | 423 if (!UpdateArrowLocation(false)) |
424 MoveWindow(); | 424 MoveWindow(); |
425 StackWindow(); | 425 StackWindow(); |
426 return FALSE; | 426 return FALSE; |
427 } | 427 } |
428 | 428 |
429 gboolean InfoBubbleGtk::HandleToplevelUnmap() { | 429 gboolean InfoBubbleGtk::HandleToplevelUnmap() { |
430 Close(); | 430 Close(); |
431 return FALSE; | 431 return FALSE; |
432 } | 432 } |
OLD | NEW |