| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 172 |
| 173 // Connect during the bubbling phase so the border is always on top. | 173 // Connect during the bubbling phase so the border is always on top. |
| 174 signals_.ConnectAfter(window_, "expose-event", | 174 signals_.ConnectAfter(window_, "expose-event", |
| 175 G_CALLBACK(OnExposeThunk), this); | 175 G_CALLBACK(OnExposeThunk), this); |
| 176 signals_.Connect(window_, "size-allocate", G_CALLBACK(OnSizeAllocateThunk), | 176 signals_.Connect(window_, "size-allocate", G_CALLBACK(OnSizeAllocateThunk), |
| 177 this); | 177 this); |
| 178 signals_.Connect(window_, "button-press-event", | 178 signals_.Connect(window_, "button-press-event", |
| 179 G_CALLBACK(OnButtonPressThunk), this); | 179 G_CALLBACK(OnButtonPressThunk), this); |
| 180 signals_.Connect(window_, "destroy", G_CALLBACK(OnDestroyThunk), this); | 180 signals_.Connect(window_, "destroy", G_CALLBACK(OnDestroyThunk), this); |
| 181 signals_.Connect(window_, "hide", G_CALLBACK(OnHideThunk), this); | 181 signals_.Connect(window_, "hide", G_CALLBACK(OnHideThunk), this); |
| 182 if (grab_input_) { |
| 183 signals_.Connect(window_, "grab-broken-event", |
| 184 G_CALLBACK(OnGrabBrokenThunk), this); |
| 185 } |
| 182 | 186 |
| 183 // If the toplevel window is being used as the anchor, then the signals below | 187 // If the toplevel window is being used as the anchor, then the signals below |
| 184 // are enough to keep us positioned correctly. | 188 // are enough to keep us positioned correctly. |
| 185 if (anchor_widget_ != toplevel_window_) { | 189 if (anchor_widget_ != toplevel_window_) { |
| 186 signals_.Connect(anchor_widget_, "size-allocate", | 190 signals_.Connect(anchor_widget_, "size-allocate", |
| 187 G_CALLBACK(OnAnchorAllocateThunk), this); | 191 G_CALLBACK(OnAnchorAllocateThunk), this); |
| 188 signals_.Connect(anchor_widget_, "destroy", | 192 signals_.Connect(anchor_widget_, "destroy", |
| 189 G_CALLBACK(gtk_widget_destroyed), &anchor_widget_); | 193 G_CALLBACK(gtk_widget_destroyed), &anchor_widget_); |
| 190 } | 194 } |
| 191 | 195 |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 const content::NotificationDetails& details) { | 459 const content::NotificationDetails& details) { |
| 456 DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED); | 460 DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED); |
| 457 if (theme_service_->UsingNativeTheme() && match_system_theme_) { | 461 if (theme_service_->UsingNativeTheme() && match_system_theme_) { |
| 458 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL); | 462 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL); |
| 459 } else { | 463 } else { |
| 460 // Set the background color, so we don't need to paint it manually. | 464 // Set the background color, so we don't need to paint it manually. |
| 461 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor); | 465 gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor); |
| 462 } | 466 } |
| 463 } | 467 } |
| 464 | 468 |
| 465 void BubbleGtk::HandlePointerAndKeyboardUngrabbedByContent() { | |
| 466 if (grab_input_) | |
| 467 GrabPointerAndKeyboard(); | |
| 468 } | |
| 469 | |
| 470 void BubbleGtk::StopGrabbingInput() { | 469 void BubbleGtk::StopGrabbingInput() { |
| 471 if (!grab_input_) | 470 if (!grab_input_) |
| 472 return; | 471 return; |
| 473 grab_input_ = false; | 472 grab_input_ = false; |
| 474 gtk_grab_remove(window_); | 473 gtk_grab_remove(window_); |
| 475 } | 474 } |
| 476 | 475 |
| 477 void BubbleGtk::Close() { | 476 void BubbleGtk::Close() { |
| 478 // We don't need to ungrab the pointer or keyboard here; the X server will | 477 // We don't need to ungrab the pointer or keyboard here; the X server will |
| 479 // automatically do that when we destroy our window. | 478 // automatically do that when we destroy our window. |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 // destroy the widget manually, or the window was closed via X. This will | 642 // destroy the widget manually, or the window was closed via X. This will |
| 644 // delete the BubbleGtk object. | 643 // delete the BubbleGtk object. |
| 645 delete this; | 644 delete this; |
| 646 return FALSE; // Propagate. | 645 return FALSE; // Propagate. |
| 647 } | 646 } |
| 648 | 647 |
| 649 void BubbleGtk::OnHide(GtkWidget* widget) { | 648 void BubbleGtk::OnHide(GtkWidget* widget) { |
| 650 gtk_widget_destroy(widget); | 649 gtk_widget_destroy(widget); |
| 651 } | 650 } |
| 652 | 651 |
| 652 gboolean BubbleGtk::OnGrabBroken(GtkWidget* widget, |
| 653 GdkEventGrabBroken* grab_broken) { |
| 654 // |grab_input_| may have been changed to false. |
| 655 if (!grab_input_) |
| 656 return false; |
| 657 |
| 658 gpointer user_data; |
| 659 gdk_window_get_user_data(grab_broken->grab_window, &user_data); |
| 660 |
| 661 if (GTK_IS_WIDGET(user_data)) { |
| 662 signals_.Connect(GTK_WIDGET(user_data), "hide", |
| 663 G_CALLBACK(OnForeshadowWidgetHideThunk), this); |
| 664 } |
| 665 |
| 666 return FALSE; |
| 667 } |
| 668 |
| 669 void BubbleGtk::OnForeshadowWidgetHide(GtkWidget* widget) { |
| 670 if (grab_input_) |
| 671 GrabPointerAndKeyboard(); |
| 672 |
| 673 signals_.DisconnectAll(widget); |
| 674 } |
| 675 |
| 653 gboolean BubbleGtk::OnToplevelConfigure(GtkWidget* widget, | 676 gboolean BubbleGtk::OnToplevelConfigure(GtkWidget* widget, |
| 654 GdkEventConfigure* event) { | 677 GdkEventConfigure* event) { |
| 655 if (!UpdateArrowLocation(false)) | 678 if (!UpdateArrowLocation(false)) |
| 656 MoveWindow(); | 679 MoveWindow(); |
| 657 StackWindow(); | 680 StackWindow(); |
| 658 return FALSE; | 681 return FALSE; |
| 659 } | 682 } |
| 660 | 683 |
| 661 gboolean BubbleGtk::OnToplevelUnmap(GtkWidget* widget, GdkEvent* event) { | 684 gboolean BubbleGtk::OnToplevelUnmap(GtkWidget* widget, GdkEvent* event) { |
| 662 Close(); | 685 Close(); |
| 663 return FALSE; | 686 return FALSE; |
| 664 } | 687 } |
| 665 | 688 |
| 666 void BubbleGtk::OnAnchorAllocate(GtkWidget* widget, | 689 void BubbleGtk::OnAnchorAllocate(GtkWidget* widget, |
| 667 GtkAllocation* allocation) { | 690 GtkAllocation* allocation) { |
| 668 if (!UpdateArrowLocation(false)) | 691 if (!UpdateArrowLocation(false)) |
| 669 MoveWindow(); | 692 MoveWindow(); |
| 670 } | 693 } |
| OLD | NEW |