| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/ui/gtk/bubble/bubble_gtk.h" | 5 #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h" |
| 6 | 6 |
| 7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "chrome/browser/ui/gtk/bubble/bubble_accelerators_gtk.h" | 10 #include "chrome/browser/ui/gtk/bubble/bubble_accelerators_gtk.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 GtkWidget* content, | 93 GtkWidget* content, |
| 94 ArrowLocationGtk arrow_location, | 94 ArrowLocationGtk arrow_location, |
| 95 bool grab_input) { | 95 bool grab_input) { |
| 96 // If there is a current grab widget (menu, other bubble, etc.), hide it. | 96 // If there is a current grab widget (menu, other bubble, etc.), hide it. |
| 97 GtkWidget* current_grab_widget = gtk_grab_get_current(); | 97 GtkWidget* current_grab_widget = gtk_grab_get_current(); |
| 98 if (current_grab_widget) | 98 if (current_grab_widget) |
| 99 gtk_widget_hide(current_grab_widget); | 99 gtk_widget_hide(current_grab_widget); |
| 100 | 100 |
| 101 DCHECK(!window_); | 101 DCHECK(!window_); |
| 102 anchor_widget_ = anchor_widget; | 102 anchor_widget_ = anchor_widget; |
| 103 toplevel_window_ = GTK_WINDOW(gtk_widget_get_toplevel(anchor_widget_)); | 103 toplevel_window_ = gtk_widget_get_toplevel(anchor_widget_); |
| 104 DCHECK(gtk_widget_is_toplevel(GTK_WIDGET(toplevel_window_))); | 104 DCHECK(gtk_widget_is_toplevel(toplevel_window_)); |
| 105 rect_ = rect ? *rect : gtk_util::WidgetBounds(anchor_widget); | 105 rect_ = rect ? *rect : gtk_util::WidgetBounds(anchor_widget); |
| 106 preferred_arrow_location_ = arrow_location; | 106 preferred_arrow_location_ = arrow_location; |
| 107 | 107 |
| 108 grab_input_ = grab_input; | 108 grab_input_ = grab_input; |
| 109 // Using a TOPLEVEL window may cause placement issues with certain WMs but it | 109 // Using a TOPLEVEL window may cause placement issues with certain WMs but it |
| 110 // is necessary to be able to focus the window. | 110 // is necessary to be able to focus the window. |
| 111 window_ = gtk_window_new(grab_input ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL); | 111 window_ = gtk_window_new(grab_input ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL); |
| 112 | 112 |
| 113 gtk_widget_set_app_paintable(window_, TRUE); | 113 gtk_widget_set_app_paintable(window_, TRUE); |
| 114 // Resizing is handled by the program, not user. | 114 // Resizing is handled by the program, not user. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 signals_.Connect(window_, "expose-event", G_CALLBACK(OnExposeThunk), this); | 149 signals_.Connect(window_, "expose-event", G_CALLBACK(OnExposeThunk), this); |
| 150 signals_.Connect(window_, "size-allocate", G_CALLBACK(OnSizeAllocateThunk), | 150 signals_.Connect(window_, "size-allocate", G_CALLBACK(OnSizeAllocateThunk), |
| 151 this); | 151 this); |
| 152 signals_.Connect(window_, "button-press-event", | 152 signals_.Connect(window_, "button-press-event", |
| 153 G_CALLBACK(OnButtonPressThunk), this); | 153 G_CALLBACK(OnButtonPressThunk), this); |
| 154 signals_.Connect(window_, "destroy", G_CALLBACK(OnDestroyThunk), this); | 154 signals_.Connect(window_, "destroy", G_CALLBACK(OnDestroyThunk), this); |
| 155 signals_.Connect(window_, "hide", G_CALLBACK(OnHideThunk), this); | 155 signals_.Connect(window_, "hide", G_CALLBACK(OnHideThunk), this); |
| 156 | 156 |
| 157 // If the toplevel window is being used as the anchor, then the signals below | 157 // If the toplevel window is being used as the anchor, then the signals below |
| 158 // are enough to keep us positioned correctly. | 158 // are enough to keep us positioned correctly. |
| 159 if (anchor_widget_ != GTK_WIDGET(toplevel_window_)) { | 159 if (anchor_widget_ != toplevel_window_) { |
| 160 signals_.Connect(anchor_widget_, "size-allocate", | 160 signals_.Connect(anchor_widget_, "size-allocate", |
| 161 G_CALLBACK(OnAnchorAllocateThunk), this); | 161 G_CALLBACK(OnAnchorAllocateThunk), this); |
| 162 signals_.Connect(anchor_widget_, "destroy", | 162 signals_.Connect(anchor_widget_, "destroy", |
| 163 G_CALLBACK(gtk_widget_destroyed), &anchor_widget_); | 163 G_CALLBACK(gtk_widget_destroyed), &anchor_widget_); |
| 164 } | 164 } |
| 165 | 165 |
| 166 signals_.Connect(toplevel_window_, "configure-event", | 166 signals_.Connect(toplevel_window_, "configure-event", |
| 167 G_CALLBACK(OnToplevelConfigureThunk), this); | 167 G_CALLBACK(OnToplevelConfigureThunk), this); |
| 168 signals_.Connect(toplevel_window_, "unmap-event", | 168 signals_.Connect(toplevel_window_, "unmap-event", |
| 169 G_CALLBACK(OnToplevelUnmapThunk), this); | 169 G_CALLBACK(OnToplevelUnmapThunk), this); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 if (right_is_onscreen && (!wants_left || !left_is_onscreen)) | 263 if (right_is_onscreen && (!wants_left || !left_is_onscreen)) |
| 264 return ARROW_LOCATION_TOP_RIGHT; | 264 return ARROW_LOCATION_TOP_RIGHT; |
| 265 return (wants_left ? ARROW_LOCATION_TOP_LEFT : ARROW_LOCATION_TOP_RIGHT); | 265 return (wants_left ? ARROW_LOCATION_TOP_LEFT : ARROW_LOCATION_TOP_RIGHT); |
| 266 } | 266 } |
| 267 | 267 |
| 268 bool BubbleGtk::UpdateArrowLocation(bool force_move_and_reshape) { | 268 bool BubbleGtk::UpdateArrowLocation(bool force_move_and_reshape) { |
| 269 if (!toplevel_window_ || !anchor_widget_) | 269 if (!toplevel_window_ || !anchor_widget_) |
| 270 return false; | 270 return false; |
| 271 | 271 |
| 272 gint toplevel_x = 0, toplevel_y = 0; | 272 gint toplevel_x = 0, toplevel_y = 0; |
| 273 gdk_window_get_position( | 273 gdk_window_get_position(gtk_widget_get_window(toplevel_window_), |
| 274 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y); | 274 &toplevel_x, &toplevel_y); |
| 275 int offset_x, offset_y; | 275 int offset_x, offset_y; |
| 276 gtk_widget_translate_coordinates(anchor_widget_, GTK_WIDGET(toplevel_window_), | 276 gtk_widget_translate_coordinates(anchor_widget_, toplevel_window_, |
| 277 rect_.x(), rect_.y(), &offset_x, &offset_y); | 277 rect_.x(), rect_.y(), &offset_x, &offset_y); |
| 278 | 278 |
| 279 ArrowLocationGtk old_location = current_arrow_location_; | 279 ArrowLocationGtk old_location = current_arrow_location_; |
| 280 GtkAllocation allocation; | 280 GtkAllocation allocation; |
| 281 gtk_widget_get_allocation(window_, &allocation); | 281 gtk_widget_get_allocation(window_, &allocation); |
| 282 current_arrow_location_ = GetArrowLocation( | 282 current_arrow_location_ = GetArrowLocation( |
| 283 preferred_arrow_location_, | 283 preferred_arrow_location_, |
| 284 toplevel_x + offset_x + (rect_.width() / 2), // arrow_x | 284 toplevel_x + offset_x + (rect_.width() / 2), // arrow_x |
| 285 allocation.width); | 285 allocation.width); |
| 286 | 286 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 309 GDK_EVEN_ODD_RULE); | 309 GDK_EVEN_ODD_RULE); |
| 310 gdk_window_shape_combine_region(window_->window, NULL, 0, 0); | 310 gdk_window_shape_combine_region(window_->window, NULL, 0, 0); |
| 311 gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0); | 311 gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0); |
| 312 } | 312 } |
| 313 | 313 |
| 314 void BubbleGtk::MoveWindow() { | 314 void BubbleGtk::MoveWindow() { |
| 315 if (!toplevel_window_ || !anchor_widget_) | 315 if (!toplevel_window_ || !anchor_widget_) |
| 316 return; | 316 return; |
| 317 | 317 |
| 318 gint toplevel_x = 0, toplevel_y = 0; | 318 gint toplevel_x = 0, toplevel_y = 0; |
| 319 gdk_window_get_position( | 319 gdk_window_get_position(gtk_widget_get_window(toplevel_window_), |
| 320 GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y); | 320 &toplevel_x, &toplevel_y); |
| 321 | 321 |
| 322 int offset_x, offset_y; | 322 int offset_x, offset_y; |
| 323 gtk_widget_translate_coordinates(anchor_widget_, GTK_WIDGET(toplevel_window_), | 323 gtk_widget_translate_coordinates(anchor_widget_, toplevel_window_, |
| 324 rect_.x(), rect_.y(), &offset_x, &offset_y); | 324 rect_.x(), rect_.y(), &offset_x, &offset_y); |
| 325 | 325 |
| 326 gint screen_x = 0; | 326 gint screen_x = 0; |
| 327 if (current_arrow_location_ == ARROW_LOCATION_TOP_LEFT) { | 327 if (current_arrow_location_ == ARROW_LOCATION_TOP_LEFT) { |
| 328 screen_x = toplevel_x + offset_x + (rect_.width() / 2) - kArrowX; | 328 screen_x = toplevel_x + offset_x + (rect_.width() / 2) - kArrowX; |
| 329 } else if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT) { | 329 } else if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT) { |
| 330 GtkAllocation allocation; | 330 GtkAllocation allocation; |
| 331 gtk_widget_get_allocation(window_, &allocation); | 331 gtk_widget_get_allocation(window_, &allocation); |
| 332 screen_x = toplevel_x + offset_x + (rect_.width() / 2) - | 332 screen_x = toplevel_x + offset_x + (rect_.width() / 2) - |
| 333 allocation.width + kArrowX; | 333 allocation.width + kArrowX; |
| 334 } else { | 334 } else { |
| 335 NOTREACHED(); | 335 NOTREACHED(); |
| 336 } | 336 } |
| 337 | 337 |
| 338 gint screen_y = toplevel_y + offset_y + rect_.height() + | 338 gint screen_y = toplevel_y + offset_y + rect_.height() + |
| 339 kArrowToContentPadding; | 339 kArrowToContentPadding; |
| 340 | 340 |
| 341 gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y); | 341 gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y); |
| 342 } | 342 } |
| 343 | 343 |
| 344 void BubbleGtk::StackWindow() { | 344 void BubbleGtk::StackWindow() { |
| 345 // Stack our window directly above the toplevel window. | 345 // Stack our window directly above the toplevel window. |
| 346 if (toplevel_window_) | 346 if (toplevel_window_) |
| 347 ui::StackPopupWindow(window_, GTK_WIDGET(toplevel_window_)); | 347 ui::StackPopupWindow(window_, toplevel_window_); |
| 348 } | 348 } |
| 349 | 349 |
| 350 void BubbleGtk::Observe(int type, | 350 void BubbleGtk::Observe(int type, |
| 351 const content::NotificationSource& source, | 351 const content::NotificationSource& source, |
| 352 const content::NotificationDetails& details) { | 352 const content::NotificationDetails& details) { |
| 353 DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED); | 353 DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED); |
| 354 if (theme_service_->UsingNativeTheme() && match_system_theme_) { | 354 if (theme_service_->UsingNativeTheme() && match_system_theme_) { |
| 355 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL); | 355 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL); |
| 356 } else { | 356 } else { |
| 357 // Set the background color, so we don't need to paint it manually. | 357 // Set the background color, so we don't need to paint it manually. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 // Close on C-w and forward the accelerator | 416 // Close on C-w and forward the accelerator |
| 417 if (modifier & GDK_CONTROL_MASK) { | 417 if (modifier & GDK_CONTROL_MASK) { |
| 418 gdk_keymap_get_entries_for_keyval(NULL, | 418 gdk_keymap_get_entries_for_keyval(NULL, |
| 419 keyval, | 419 keyval, |
| 420 &keys, | 420 &keys, |
| 421 &n_keys); | 421 &n_keys); |
| 422 if (n_keys) { | 422 if (n_keys) { |
| 423 // Forward the accelerator to root window the bubble is anchored | 423 // Forward the accelerator to root window the bubble is anchored |
| 424 // to for further processing | 424 // to for further processing |
| 425 msg.type = GDK_KEY_PRESS; | 425 msg.type = GDK_KEY_PRESS; |
| 426 msg.window = GTK_WIDGET(toplevel_window_)->window; | 426 msg.window = gtk_widget_get_window(toplevel_window_); |
| 427 msg.send_event = TRUE; | 427 msg.send_event = TRUE; |
| 428 msg.time = GDK_CURRENT_TIME; | 428 msg.time = GDK_CURRENT_TIME; |
| 429 msg.state = modifier | GDK_MOD2_MASK; | 429 msg.state = modifier | GDK_MOD2_MASK; |
| 430 msg.keyval = keyval; | 430 msg.keyval = keyval; |
| 431 // length and string are deprecated and thus zeroed out | 431 // length and string are deprecated and thus zeroed out |
| 432 msg.length = 0; | 432 msg.length = 0; |
| 433 msg.string = NULL; | 433 msg.string = NULL; |
| 434 msg.hardware_keycode = keys[0].keycode; | 434 msg.hardware_keycode = keys[0].keycode; |
| 435 msg.group = keys[0].group; | 435 msg.group = keys[0].group; |
| 436 msg.is_modifier = 0; | 436 msg.is_modifier = 0; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 gboolean BubbleGtk::OnToplevelUnmap(GtkWidget* widget, GdkEvent* event) { | 532 gboolean BubbleGtk::OnToplevelUnmap(GtkWidget* widget, GdkEvent* event) { |
| 533 Close(); | 533 Close(); |
| 534 return FALSE; | 534 return FALSE; |
| 535 } | 535 } |
| 536 | 536 |
| 537 void BubbleGtk::OnAnchorAllocate(GtkWidget* widget, | 537 void BubbleGtk::OnAnchorAllocate(GtkWidget* widget, |
| 538 GtkAllocation* allocation) { | 538 GtkAllocation* allocation) { |
| 539 if (!UpdateArrowLocation(false)) | 539 if (!UpdateArrowLocation(false)) |
| 540 MoveWindow(); | 540 MoveWindow(); |
| 541 } | 541 } |
| OLD | NEW |