| 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 |