OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // 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 | 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 "views/controls/menu/menu_host_win.h" | 5 #include "views/controls/menu/menu_host_win.h" |
6 | 6 |
7 #include "base/win_util.h" | 7 #include "base/win_util.h" |
8 #include "views/controls/menu/menu_controller.h" | 8 #include "views/controls/menu/menu_controller.h" |
9 #include "views/controls/menu/menu_host_root_view.h" | 9 #include "views/controls/menu/menu_host_root_view.h" |
10 #include "views/controls/menu/menu_item_view.h" | 10 #include "views/controls/menu/menu_item_view.h" |
11 #include "views/controls/menu/submenu_view.h" | 11 #include "views/controls/menu/submenu_view.h" |
12 | 12 |
13 namespace views { | 13 namespace views { |
14 | 14 |
15 MenuHost::MenuHost(SubmenuView* submenu) | 15 // static |
16 : closed_(false), | 16 MenuHost* MenuHost::Create(SubmenuView* submenu_view) { |
| 17 return new MenuHostWin(submenu_view); |
| 18 } |
| 19 |
| 20 MenuHostWin::MenuHostWin(SubmenuView* submenu) |
| 21 : destroying_(false), |
17 submenu_(submenu), | 22 submenu_(submenu), |
18 owns_capture_(false) { | 23 owns_capture_(false) { |
19 set_window_style(WS_POPUP); | 24 set_window_style(WS_POPUP); |
20 set_initial_class_style( | 25 set_initial_class_style( |
21 (win_util::GetWinVersion() < win_util::WINVERSION_XP) ? | 26 (win_util::GetWinVersion() < win_util::WINVERSION_XP) ? |
22 0 : CS_DROPSHADOW); | 27 0 : CS_DROPSHADOW); |
23 is_mouse_down_ = | 28 is_mouse_down_ = |
24 ((GetKeyState(VK_LBUTTON) & 0x80) || | 29 ((GetKeyState(VK_LBUTTON) & 0x80) || |
25 (GetKeyState(VK_RBUTTON) & 0x80) || | 30 (GetKeyState(VK_RBUTTON) & 0x80) || |
26 (GetKeyState(VK_MBUTTON) & 0x80) || | 31 (GetKeyState(VK_MBUTTON) & 0x80) || |
27 (GetKeyState(VK_XBUTTON1) & 0x80) || | 32 (GetKeyState(VK_XBUTTON1) & 0x80) || |
28 (GetKeyState(VK_XBUTTON2) & 0x80)); | 33 (GetKeyState(VK_XBUTTON2) & 0x80)); |
29 // Mouse clicks shouldn't give us focus. | 34 // Mouse clicks shouldn't give us focus. |
30 set_window_ex_style(WS_EX_TOPMOST | WS_EX_NOACTIVATE); | 35 set_window_ex_style(WS_EX_TOPMOST | WS_EX_NOACTIVATE); |
31 } | 36 } |
32 | 37 |
33 void MenuHost::Init(HWND parent, | 38 MenuHostWin::~MenuHostWin() { |
34 const gfx::Rect& bounds, | 39 } |
35 View* contents_view, | 40 |
36 bool do_capture) { | 41 void MenuHostWin::Init(HWND parent, |
| 42 const gfx::Rect& bounds, |
| 43 View* contents_view, |
| 44 bool do_capture) { |
37 WidgetWin::Init(parent, bounds); | 45 WidgetWin::Init(parent, bounds); |
38 SetContentsView(contents_view); | 46 SetContentsView(contents_view); |
39 Show(); | 47 ShowMenuHost(do_capture); |
| 48 } |
| 49 |
| 50 bool MenuHostWin::IsMenuHostVisible() { |
| 51 return IsVisible(); |
| 52 } |
| 53 |
| 54 void MenuHostWin::ShowMenuHost(bool do_capture) { |
| 55 // We don't want to take focus away from the hosting window. |
| 56 ShowWindow(SW_SHOWNA); |
| 57 |
40 if (do_capture) | 58 if (do_capture) |
41 DoCapture(); | 59 DoCapture(); |
42 } | 60 } |
43 | 61 |
44 void MenuHost::Show() { | 62 void MenuHostWin::HideMenuHost() { |
45 // We don't want to take focus away from the hosting window. | 63 // Make sure we release capture before hiding. |
46 ShowWindow(SW_SHOWNA); | 64 ReleaseMenuHostCapture(); |
47 } | |
48 | 65 |
49 void MenuHost::Hide() { | |
50 if (closed_) { | |
51 // We're already closed, nothing to do. | |
52 // This is invoked twice if the first time just hid us, and the second | |
53 // time deleted Closed (deleted) us. | |
54 return; | |
55 } | |
56 // The menus are freed separately, and possibly before the window is closed, | |
57 // remove them so that View doesn't try to access deleted objects. | |
58 static_cast<MenuHostRootView*>(GetRootView())->suspend_events(); | |
59 GetRootView()->RemoveAllChildViews(false); | |
60 closed_ = true; | |
61 ReleaseCapture(); | |
62 WidgetWin::Hide(); | 66 WidgetWin::Hide(); |
63 } | 67 } |
64 | 68 |
65 void MenuHost::HideWindow() { | 69 void MenuHostWin::DestroyMenuHost() { |
66 // Make sure we release capture before hiding. | 70 HideMenuHost(); |
67 ReleaseCapture(); | 71 destroying_ = true; |
68 WidgetWin::Hide(); | 72 CloseNow(); |
69 } | 73 } |
70 | 74 |
71 void MenuHost::OnCaptureChanged(HWND hwnd) { | 75 void MenuHostWin::SetMenuHostBounds(const gfx::Rect& bounds) { |
| 76 SetBounds(bounds); |
| 77 } |
| 78 |
| 79 void MenuHostWin::ReleaseMenuHostCapture() { |
| 80 if (owns_capture_) { |
| 81 owns_capture_ = false; |
| 82 ::ReleaseCapture(); |
| 83 } |
| 84 } |
| 85 |
| 86 gfx::NativeWindow MenuHostWin::GetMenuHostWindow() { |
| 87 return GetNativeView(); |
| 88 } |
| 89 |
| 90 void MenuHostWin::OnDestroy() { |
| 91 if (!destroying_) { |
| 92 // We weren't explicitly told to destroy ourselves, which means the menu was |
| 93 // deleted out from under us (the window we're parented to was closed). Tell |
| 94 // the SubmenuView to drop references to us. |
| 95 submenu_->MenuHostDestroyed(); |
| 96 } |
| 97 WidgetWin::OnDestroy(); |
| 98 } |
| 99 |
| 100 void MenuHostWin::OnCaptureChanged(HWND hwnd) { |
72 WidgetWin::OnCaptureChanged(hwnd); | 101 WidgetWin::OnCaptureChanged(hwnd); |
73 owns_capture_ = false; | 102 owns_capture_ = false; |
74 #ifdef DEBUG_MENU | 103 #ifdef DEBUG_MENU |
75 DLOG(INFO) << "Capture changed"; | 104 DLOG(INFO) << "Capture changed"; |
76 #endif | 105 #endif |
77 } | 106 } |
78 | 107 |
79 void MenuHost::DoCapture() { | 108 void MenuHostWin::OnCancelMode() { |
| 109 submenu_->GetMenuItem()->GetMenuController()->Cancel( |
| 110 MenuController::EXIT_ALL); |
| 111 } |
| 112 |
| 113 RootView* MenuHostWin::CreateRootView() { |
| 114 return new MenuHostRootView(this, submenu_); |
| 115 } |
| 116 |
| 117 bool MenuHostWin::ReleaseCaptureOnMouseReleased() { |
| 118 return false; |
| 119 } |
| 120 |
| 121 void MenuHostWin::DoCapture() { |
80 owns_capture_ = true; | 122 owns_capture_ = true; |
81 SetCapture(); | 123 SetCapture(); |
82 has_capture_ = true; | 124 has_capture_ = true; |
83 #ifdef DEBUG_MENU | 125 #ifdef DEBUG_MENU |
84 DLOG(INFO) << "Doing capture"; | 126 DLOG(INFO) << "Doing capture"; |
85 #endif | 127 #endif |
86 } | 128 } |
87 | 129 |
88 void MenuHost::ReleaseCapture() { | |
89 if (owns_capture_) { | |
90 #ifdef DEBUG_MENU | |
91 DLOG(INFO) << "released capture"; | |
92 #endif | |
93 owns_capture_ = false; | |
94 ::ReleaseCapture(); | |
95 } | |
96 } | |
97 | |
98 RootView* MenuHost::CreateRootView() { | |
99 return new MenuHostRootView(this, submenu_); | |
100 } | |
101 | |
102 void MenuHost::OnCancelMode() { | |
103 if (!closed_) { | |
104 #ifdef DEBUG_MENU | |
105 DLOG(INFO) << "OnCanceMode, closing menu"; | |
106 #endif | |
107 submenu_->GetMenuItem()->GetMenuController()->Cancel(true); | |
108 } | |
109 } | |
110 | |
111 // Overriden to return false, we do NOT want to release capture on mouse | |
112 // release. | |
113 bool MenuHost::ReleaseCaptureOnMouseReleased() { | |
114 return false; | |
115 } | |
116 | |
117 } // namespace views | 130 } // namespace views |
OLD | NEW |