Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: ui/views/controls/menu/menu_message_loop_aura.cc

Issue 267593005: Refactor menu controller to isolate aura dependency. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removing ifdefs, work in progress Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
tapted 2014/05/04 23:43:39 nit: no (c)
Andre 2014/05/05 22:41:29 Done.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/run_loop.h"
6 #include "ui/aura/client/screen_position_client.h"
7 #include "ui/events/event.h"
8 #include "ui/events/platform/platform_event_source.h"
9 #include "ui/events/platform/scoped_event_dispatcher.h"
10 #include "ui/views/controls/menu/menu_message_loop.h"
tapted 2014/05/04 23:43:39 nit: should be the first include, followed by a ne
Andre 2014/05/05 22:41:29 Done.
11 #include "ui/wm/public/activation_change_observer.h"
12 #include "ui/wm/public/activation_client.h"
13 #include "ui/wm/public/dispatcher_client.h"
14 #include "ui/wm/public/drag_drop_client.h"
15
16 #if defined(OS_WIN)
17 #include "ui/base/win/internal_constants.h"
18 #include "ui/views/controls/menu/menu_message_pump_dispatcher_win.h"
19 #include "ui/views/win/hwnd_util.h"
20 #else
21 #include "ui/views/controls/menu/menu_event_dispatcher_linux.h"
22 #endif
23
24 namespace views {
25
26 namespace {
27
28 aura::Window* GetOwnerRootWindow(views::Widget* owner) {
29 return owner ? owner->GetNativeWindow()->GetRootWindow() : NULL;
30 }
31
32 // ActivationChangeObserverImpl is used to observe activation changes and close
33 // the menu. Additionally it listens for the root window to be destroyed and
34 // cancel the menu as well.
35 class ActivationChangeObserverImpl
36 : public aura::client::ActivationChangeObserver,
37 public aura::WindowObserver,
38 public ui::EventHandler {
39 public:
40 ActivationChangeObserverImpl(MenuController* controller, aura::Window* root)
41 : controller_(controller), root_(root) {
42 aura::client::GetActivationClient(root_)->AddObserver(this);
43 root_->AddObserver(this);
44 root_->AddPreTargetHandler(this);
45 }
46
47 virtual ~ActivationChangeObserverImpl() { Cleanup(); }
48
49 // aura::client::ActivationChangeObserver:
50 virtual void OnWindowActivated(aura::Window* gained_active,
51 aura::Window* lost_active) OVERRIDE {
52 if (!controller_->drag_in_progress())
53 controller_->CancelAll();
54 }
55
56 // aura::WindowObserver:
57 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { Cleanup(); }
58
59 // ui::EventHandler:
60 virtual void OnCancelMode(ui::CancelModeEvent* event) OVERRIDE {
61 controller_->CancelAll();
62 }
63
64 private:
65 void Cleanup() {
66 if (!root_)
67 return;
68 // The ActivationClient may have been destroyed by the time we get here.
69 aura::client::ActivationClient* client =
70 aura::client::GetActivationClient(root_);
71 if (client)
72 client->RemoveObserver(this);
73 root_->RemovePreTargetHandler(this);
74 root_->RemoveObserver(this);
75 root_ = NULL;
76 }
77
78 MenuController* controller_;
79 aura::Window* root_;
80
81 DISALLOW_COPY_AND_ASSIGN(ActivationChangeObserverImpl);
82 };
83
84 } // namespace
85
86 void MenuMessageLoop::RepostEvent(const ui::LocatedEvent& event) {
87 aura::Window* root = window->GetRootWindow();
88 ScreenPositionClient* spc = aura::client::GetScreenPositionClient(root);
89 if (!spc)
90 return;
91
92 gfx::Point root_loc(screen_loc);
93 spc->ConvertPointFromScreen(root, &root_loc);
94
95 ui::MouseEvent clone(static_cast<const ui::MouseEvent&>(event));
96 clone.set_location(root_loc);
97 clone.set_root_location(root_loc);
98 root->GetHost()->dispatcher()->RepostEvent(clone);
99 }
100
101 #if defined(OS_WIN)
102 void MenuMessageLoop::Run(MenuController* controller, bool nested_menu) {
103 internal::MenuMessagePumpDispatcher nested_dispatcher(controller);
104
105 // |owner_| may be NULL.
106 aura::Window* root = GetOwnerRootWindow(owner_);
107 if (root) {
108 scoped_ptr<ActivationChangeObserverImpl> observer;
109 if (!nested_menu)
110 observer.reset(new ActivationChangeObserverImpl(controller, root));
111 aura::client::GetDispatcherClient(root)
112 ->RunWithDispatcher(&nested_dispatcher);
113 } else {
114 base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
115 base::MessageLoop::ScopedNestableTaskAllower allow(loop);
116 base::RunLoop run_loop(&nested_dispatcher);
117 run_loop.Run();
118 }
119 }
120 #else
121 void MenuMessageLoop::Run(MenuController* controller, bool nested_menu) {
122 internal::MenuEventDispatcher event_dispatcher(controller);
123 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher =
124 nested_dispatcher_.Pass();
125 if (ui::PlatformEventSource::GetInstance()) {
126 nested_dispatcher_ =
127 ui::PlatformEventSource::GetInstance()->OverrideDispatcher(
128 &event_dispatcher);
129 }
130 // |owner_| may be NULL.
131 aura::Window* root = GetOwnerRootWindow(owner_);
132 if (root) {
133 scoped_ptr<ActivationChangeObserverImpl> observer;
134 if (!nested_menu)
135 observer.reset(new ActivationChangeObserverImpl(controller, root));
136 aura::client::GetDispatcherClient(root)->RunWithDispatcher(NULL);
137 } else {
138 base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
139 base::MessageLoop::ScopedNestableTaskAllower allow(loop);
140 base::RunLoop run_loop;
141 run_loop.Run();
142 }
143 nested_dispatcher_ = old_dispatcher.Pass();
144 }
145 #endif
146
147 bool MenuMessageLoop::ShouldQuitNow() const {
148 aura::Window* root = GetOwnerRootWindow(owner_);
149 return !aura::client::GetDragDropClient(root) ||
150 !aura::client::GetDragDropClient(root)->IsDragDropInProgress();
151 }
152
153 void MenuMessageLoop::QuitNow() {
154 if (owner_) {
155 // It's safe to invoke QuitNestedMessageLoop() multiple times, it only
156 // effects the current loop.
157 aura::Window* root = owner_->GetNativeWindow()->GetRootWindow();
158 aura::client::GetDispatcherClient(root)->QuitNestedMessageLoop();
159 } else {
160 base::MessageLoop::current()->QuitNow();
161 }
162 // Restore the previous dispatcher.
163 nested_dispatcher_.reset();
164 }
165
166 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698