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 |