| Index: views/controls/menu/menu_host_gtk.cc
|
| diff --git a/views/controls/menu/menu_host_gtk.cc b/views/controls/menu/menu_host_gtk.cc
|
| index bdd8ffea5d34f400fcf8f6b02318905b0e4fd1a1..95fea7b0a301f364b3c0e0682bbcd2bb2e276f28 100644
|
| --- a/views/controls/menu/menu_host_gtk.cc
|
| +++ b/views/controls/menu/menu_host_gtk.cc
|
| @@ -1,8 +1,7 @@
|
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -
|
| #include "views/controls/menu/menu_host_gtk.h"
|
|
|
| #include <gdk/gdk.h>
|
| @@ -14,9 +13,14 @@
|
|
|
| namespace views {
|
|
|
| -MenuHost::MenuHost(SubmenuView* submenu)
|
| +// static
|
| +MenuHost* MenuHost::Create(SubmenuView* submenu_view) {
|
| + return new MenuHostGtk(submenu_view);
|
| +}
|
| +
|
| +MenuHostGtk::MenuHostGtk(SubmenuView* submenu)
|
| : WidgetGtk(WidgetGtk::TYPE_POPUP),
|
| - closed_(false),
|
| + destroying_(false),
|
| submenu_(submenu),
|
| did_pointer_grab_(false) {
|
| GdkEvent* event = gtk_get_current_event();
|
| @@ -29,50 +33,92 @@ MenuHost::MenuHost(SubmenuView* submenu)
|
| }
|
| }
|
|
|
| -void MenuHost::Init(gfx::NativeWindow parent,
|
| +MenuHostGtk::~MenuHostGtk() {
|
| +}
|
| +
|
| +void MenuHostGtk::Init(gfx::NativeWindow parent,
|
| const gfx::Rect& bounds,
|
| View* contents_view,
|
| bool do_capture) {
|
| + make_transient_to_parent();
|
| WidgetGtk::Init(GTK_WIDGET(parent), bounds);
|
| + // Make sure we get destroyed when the parent is destroyed.
|
| + gtk_window_set_destroy_with_parent(GTK_WINDOW(GetNativeView()), TRUE);
|
| gtk_window_set_type_hint(GTK_WINDOW(GetNativeView()),
|
| GDK_WINDOW_TYPE_HINT_MENU);
|
| SetContentsView(contents_view);
|
| - Show();
|
| + ShowMenuHost(do_capture);
|
| +}
|
| +
|
| +bool MenuHostGtk::IsMenuHostVisible() {
|
| + return IsVisible();
|
| +}
|
| +
|
| +void MenuHostGtk::ShowMenuHost(bool do_capture) {
|
| + WidgetGtk::Show();
|
| if (do_capture)
|
| DoCapture();
|
| }
|
|
|
| -gfx::NativeWindow MenuHost::GetNativeWindow() {
|
| +void MenuHostGtk::HideMenuHost() {
|
| + // Make sure we release capture before hiding.
|
| + ReleaseMenuHostCapture();
|
| +
|
| + WidgetGtk::Hide();
|
| +}
|
| +
|
| +void MenuHostGtk::DestroyMenuHost() {
|
| + HideMenuHost();
|
| + destroying_ = true;
|
| + CloseNow();
|
| +}
|
| +
|
| +void MenuHostGtk::SetMenuHostBounds(const gfx::Rect& bounds) {
|
| + SetBounds(bounds);
|
| +}
|
| +
|
| +void MenuHostGtk::ReleaseMenuHostCapture() {
|
| + ReleaseGrab();
|
| +}
|
| +
|
| +gfx::NativeWindow MenuHostGtk::GetMenuHostWindow() {
|
| return GTK_WINDOW(GetNativeView());
|
| }
|
|
|
| -void MenuHost::Show() {
|
| - WidgetGtk::Show();
|
| +RootView* MenuHostGtk::CreateRootView() {
|
| + return new MenuHostRootView(this, submenu_);
|
| +}
|
| +
|
| +bool MenuHostGtk::ReleaseCaptureOnMouseReleased() {
|
| + return false;
|
| }
|
|
|
| -void MenuHost::Hide() {
|
| - if (closed_) {
|
| - // We're already closed, nothing to do.
|
| - // This is invoked twice if the first time just hid us, and the second
|
| - // time deleted Closed (deleted) us.
|
| - return;
|
| +void MenuHostGtk::ReleaseGrab() {
|
| + WidgetGtk::ReleaseGrab();
|
| + if (did_pointer_grab_) {
|
| + did_pointer_grab_ = false;
|
| + gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
| }
|
| - // The menus are freed separately, and possibly before the window is closed,
|
| - // remove them so that View doesn't try to access deleted objects.
|
| - static_cast<MenuHostRootView*>(GetRootView())->suspend_events();
|
| - GetRootView()->RemoveAllChildViews(false);
|
| - ReleaseGrab();
|
| - closed_ = true;
|
| - WidgetGtk::Hide();
|
| }
|
|
|
| -void MenuHost::HideWindow() {
|
| - // Make sure we release capture before hiding.
|
| - ReleaseGrab();
|
| - WidgetGtk::Hide();
|
| +void MenuHostGtk::OnDestroy(GtkWidget* object) {
|
| + if (!destroying_) {
|
| + // We weren't explicitly told to destroy ourselves, which means the menu was
|
| + // deleted out from under us (the window we're parented to was closed). Tell
|
| + // the SubmenuView to drop references to us.
|
| + submenu_->MenuHostDestroyed();
|
| + }
|
| + WidgetGtk::OnDestroy(object);
|
| +}
|
| +
|
| +gboolean MenuHostGtk::OnGrabBrokeEvent(GtkWidget* widget, GdkEvent* event) {
|
| + // Grab breaking only happens when drag and drop starts. So, we don't try
|
| + // and ungrab or cancel the menu.
|
| + did_pointer_grab_ = false;
|
| + return WidgetGtk::OnGrabBrokeEvent(widget, event);
|
| }
|
|
|
| -void MenuHost::DoCapture() {
|
| +void MenuHostGtk::DoCapture() {
|
| // Release the current grab.
|
| GtkWidget* current_grab_window = gtk_grab_get_current();
|
| if (current_grab_window)
|
| @@ -93,38 +139,6 @@ void MenuHost::DoCapture() {
|
| did_pointer_grab_ = (grab_status == GDK_GRAB_SUCCESS);
|
| DCHECK(did_pointer_grab_);
|
| // need keyboard grab.
|
| -#ifdef DEBUG_MENU
|
| - DLOG(INFO) << "Doing capture";
|
| -#endif
|
| -}
|
| -
|
| -void MenuHost::ReleaseCapture() {
|
| - ReleaseGrab();
|
| -}
|
| -
|
| -RootView* MenuHost::CreateRootView() {
|
| - return new MenuHostRootView(this, submenu_);
|
| -}
|
| -
|
| -gboolean MenuHost::OnGrabBrokeEvent(GtkWidget* widget, GdkEvent* event) {
|
| - // Grab breaking only happens when drag and drop starts. So, we don't try
|
| - // and ungrab or cancel the menu.
|
| - did_pointer_grab_ = false;
|
| - return WidgetGtk::OnGrabBrokeEvent(widget, event);
|
| -}
|
| -
|
| -// Overriden to return false, we do NOT want to release capture on mouse
|
| -// release.
|
| -bool MenuHost::ReleaseCaptureOnMouseReleased() {
|
| - return false;
|
| -}
|
| -
|
| -void MenuHost::ReleaseGrab() {
|
| - WidgetGtk::ReleaseGrab();
|
| - if (did_pointer_grab_) {
|
| - did_pointer_grab_ = false;
|
| - gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
| - }
|
| }
|
|
|
| } // namespace views
|
|
|