blob: 11033c48daf37de21eaad0f653a61243f526b48e [file] [log] [blame]
[email protected]a87ecb3c2009-08-24 15:46:451// 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
3// found in the LICENSE file.
4
5
6#include "views/controls/menu/menu_host_gtk.h"
7
8#include <gdk/gdk.h>
9
10#include "views/controls/menu/menu_controller.h"
11#include "views/controls/menu/menu_host_root_view.h"
12#include "views/controls/menu/menu_item_view.h"
13#include "views/controls/menu/submenu_view.h"
14
15namespace views {
16
17MenuHost::MenuHost(SubmenuView* submenu)
18 : WidgetGtk(WidgetGtk::TYPE_POPUP),
19 closed_(false),
[email protected]40e59f92009-08-26 20:51:0220 submenu_(submenu),
21 did_pointer_grab_(false) {
[email protected]a87ecb3c2009-08-24 15:46:4522 GdkModifierType current_event_mod;
23 if (gtk_get_current_event_state(&current_event_mod)) {
24 set_mouse_down(
25 (current_event_mod & GDK_BUTTON1_MASK) ||
26 (current_event_mod & GDK_BUTTON2_MASK) ||
27 (current_event_mod & GDK_BUTTON3_MASK) ||
28 (current_event_mod & GDK_BUTTON4_MASK) ||
29 (current_event_mod & GDK_BUTTON5_MASK));
30 }
31}
32
[email protected]d6d6d582009-10-12 19:22:2633void MenuHost::Init(gfx::NativeWindow parent,
[email protected]a87ecb3c2009-08-24 15:46:4534 const gfx::Rect& bounds,
35 View* contents_view,
36 bool do_capture) {
[email protected]d6d6d582009-10-12 19:22:2637 WidgetGtk::Init(GTK_WIDGET(parent), bounds);
[email protected]a87ecb3c2009-08-24 15:46:4538 SetContentsView(contents_view);
39 // TODO(sky): see if there is some way to show without changing focus.
40 Show();
41 if (do_capture) {
[email protected]40e59f92009-08-26 20:51:0242 // Release the current grab.
43 GtkWidget* current_grab_window = gtk_grab_get_current();
44 if (current_grab_window)
45 gtk_grab_remove(current_grab_window);
46
47 // Make sure all app mouse events are targetted at us only.
[email protected]a87ecb3c2009-08-24 15:46:4548 DoGrab();
[email protected]40e59f92009-08-26 20:51:0249
50 // And do a grab.
51 // NOTE: we do this to ensure we get mouse events from other apps, a grab
52 // done with gtk_grab_add doesn't get events from other apps.
53 GdkGrabStatus grab_status =
54 gdk_pointer_grab(window_contents()->window, FALSE,
55 static_cast<GdkEventMask>(
56 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
57 GDK_POINTER_MOTION_MASK),
58 NULL, NULL, GDK_CURRENT_TIME);
59 did_pointer_grab_ = (grab_status == GDK_GRAB_SUCCESS);
60 DCHECK(did_pointer_grab_);
61 // need keyboard grab.
[email protected]a87ecb3c2009-08-24 15:46:4562#ifdef DEBUG_MENU
63 DLOG(INFO) << "Doing capture";
64#endif
65 }
66}
67
[email protected]d6d6d582009-10-12 19:22:2668gfx::NativeWindow MenuHost::GetNativeWindow() {
69 return GTK_WINDOW(GetNativeView());
70}
71
[email protected]a87ecb3c2009-08-24 15:46:4572void MenuHost::Show() {
73 WidgetGtk::Show();
74}
75
76void MenuHost::Hide() {
77 if (closed_) {
78 // We're already closed, nothing to do.
79 // This is invoked twice if the first time just hid us, and the second
80 // time deleted Closed (deleted) us.
81 return;
82 }
83 // The menus are freed separately, and possibly before the window is closed,
84 // remove them so that View doesn't try to access deleted objects.
85 static_cast<MenuHostRootView*>(GetRootView())->suspend_events();
86 GetRootView()->RemoveAllChildViews(false);
[email protected]345dd302009-08-26 20:12:5987 ReleaseGrab();
[email protected]40e59f92009-08-26 20:51:0288 closed_ = true;
[email protected]a87ecb3c2009-08-24 15:46:4589 WidgetGtk::Hide();
90}
91
92void MenuHost::HideWindow() {
93 // Make sure we release capture before hiding.
94 ReleaseGrab();
95 WidgetGtk::Hide();
96}
97
98void MenuHost::ReleaseCapture() {
99 ReleaseGrab();
100}
101
102RootView* MenuHost::CreateRootView() {
103 return new MenuHostRootView(this, submenu_);
104}
105
[email protected]40e59f92009-08-26 20:51:02106gboolean MenuHost::OnGrabBrokeEvent(GtkWidget* widget, GdkEvent* event) {
[email protected]4768c65b2009-08-28 21:42:59107 // Grab breaking only happens when drag and drop starts. So, we don't try
108 // and ungrab or cancel the menu.
109 did_pointer_grab_ = false;
[email protected]40e59f92009-08-26 20:51:02110 return WidgetGtk::OnGrabBrokeEvent(widget, event);
111}
112
[email protected]a87ecb3c2009-08-24 15:46:45113// Overriden to return false, we do NOT want to release capture on mouse
114// release.
115bool MenuHost::ReleaseCaptureOnMouseReleased() {
116 return false;
117}
118
[email protected]40e59f92009-08-26 20:51:02119void MenuHost::ReleaseGrab() {
120 WidgetGtk::ReleaseGrab();
121 if (did_pointer_grab_) {
122 did_pointer_grab_ = false;
123 gdk_pointer_ungrab(GDK_CURRENT_TIME);
124 }
125}
126
[email protected]a87ecb3c2009-08-24 15:46:45127} // namespace views