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

Unified 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, 8 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 side-by-side diff with in-line comments
Download patch
Index: ui/views/controls/menu/menu_message_loop_aura.cc
diff --git a/ui/views/controls/menu/menu_message_loop_aura.cc b/ui/views/controls/menu/menu_message_loop_aura.cc
new file mode 100644
index 0000000000000000000000000000000000000000..82ec06d6dc0a838aba0691e86f4bb20a245f8a4a
--- /dev/null
+++ b/ui/views/controls/menu/menu_message_loop_aura.cc
@@ -0,0 +1,166 @@
+// 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.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/events/event.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform/scoped_event_dispatcher.h"
+#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.
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/dispatcher_client.h"
+#include "ui/wm/public/drag_drop_client.h"
+
+#if defined(OS_WIN)
+#include "ui/base/win/internal_constants.h"
+#include "ui/views/controls/menu/menu_message_pump_dispatcher_win.h"
+#include "ui/views/win/hwnd_util.h"
+#else
+#include "ui/views/controls/menu/menu_event_dispatcher_linux.h"
+#endif
+
+namespace views {
+
+namespace {
+
+aura::Window* GetOwnerRootWindow(views::Widget* owner) {
+ return owner ? owner->GetNativeWindow()->GetRootWindow() : NULL;
+}
+
+// ActivationChangeObserverImpl is used to observe activation changes and close
+// the menu. Additionally it listens for the root window to be destroyed and
+// cancel the menu as well.
+class ActivationChangeObserverImpl
+ : public aura::client::ActivationChangeObserver,
+ public aura::WindowObserver,
+ public ui::EventHandler {
+ public:
+ ActivationChangeObserverImpl(MenuController* controller, aura::Window* root)
+ : controller_(controller), root_(root) {
+ aura::client::GetActivationClient(root_)->AddObserver(this);
+ root_->AddObserver(this);
+ root_->AddPreTargetHandler(this);
+ }
+
+ virtual ~ActivationChangeObserverImpl() { Cleanup(); }
+
+ // aura::client::ActivationChangeObserver:
+ virtual void OnWindowActivated(aura::Window* gained_active,
+ aura::Window* lost_active) OVERRIDE {
+ if (!controller_->drag_in_progress())
+ controller_->CancelAll();
+ }
+
+ // aura::WindowObserver:
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { Cleanup(); }
+
+ // ui::EventHandler:
+ virtual void OnCancelMode(ui::CancelModeEvent* event) OVERRIDE {
+ controller_->CancelAll();
+ }
+
+ private:
+ void Cleanup() {
+ if (!root_)
+ return;
+ // The ActivationClient may have been destroyed by the time we get here.
+ aura::client::ActivationClient* client =
+ aura::client::GetActivationClient(root_);
+ if (client)
+ client->RemoveObserver(this);
+ root_->RemovePreTargetHandler(this);
+ root_->RemoveObserver(this);
+ root_ = NULL;
+ }
+
+ MenuController* controller_;
+ aura::Window* root_;
+
+ DISALLOW_COPY_AND_ASSIGN(ActivationChangeObserverImpl);
+};
+
+} // namespace
+
+void MenuMessageLoop::RepostEvent(const ui::LocatedEvent& event) {
+ aura::Window* root = window->GetRootWindow();
+ ScreenPositionClient* spc = aura::client::GetScreenPositionClient(root);
+ if (!spc)
+ return;
+
+ gfx::Point root_loc(screen_loc);
+ spc->ConvertPointFromScreen(root, &root_loc);
+
+ ui::MouseEvent clone(static_cast<const ui::MouseEvent&>(event));
+ clone.set_location(root_loc);
+ clone.set_root_location(root_loc);
+ root->GetHost()->dispatcher()->RepostEvent(clone);
+}
+
+#if defined(OS_WIN)
+void MenuMessageLoop::Run(MenuController* controller, bool nested_menu) {
+ internal::MenuMessagePumpDispatcher nested_dispatcher(controller);
+
+ // |owner_| may be NULL.
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ if (root) {
+ scoped_ptr<ActivationChangeObserverImpl> observer;
+ if (!nested_menu)
+ observer.reset(new ActivationChangeObserverImpl(controller, root));
+ aura::client::GetDispatcherClient(root)
+ ->RunWithDispatcher(&nested_dispatcher);
+ } else {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ base::RunLoop run_loop(&nested_dispatcher);
+ run_loop.Run();
+ }
+}
+#else
+void MenuMessageLoop::Run(MenuController* controller, bool nested_menu) {
+ internal::MenuEventDispatcher event_dispatcher(controller);
+ scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher =
+ nested_dispatcher_.Pass();
+ if (ui::PlatformEventSource::GetInstance()) {
+ nested_dispatcher_ =
+ ui::PlatformEventSource::GetInstance()->OverrideDispatcher(
+ &event_dispatcher);
+ }
+ // |owner_| may be NULL.
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ if (root) {
+ scoped_ptr<ActivationChangeObserverImpl> observer;
+ if (!nested_menu)
+ observer.reset(new ActivationChangeObserverImpl(controller, root));
+ aura::client::GetDispatcherClient(root)->RunWithDispatcher(NULL);
+ } else {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ base::RunLoop run_loop;
+ run_loop.Run();
+ }
+ nested_dispatcher_ = old_dispatcher.Pass();
+}
+#endif
+
+bool MenuMessageLoop::ShouldQuitNow() const {
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ return !aura::client::GetDragDropClient(root) ||
+ !aura::client::GetDragDropClient(root)->IsDragDropInProgress();
+}
+
+void MenuMessageLoop::QuitNow() {
+ if (owner_) {
+ // It's safe to invoke QuitNestedMessageLoop() multiple times, it only
+ // effects the current loop.
+ aura::Window* root = owner_->GetNativeWindow()->GetRootWindow();
+ aura::client::GetDispatcherClient(root)->QuitNestedMessageLoop();
+ } else {
+ base::MessageLoop::current()->QuitNow();
+ }
+ // Restore the previous dispatcher.
+ nested_dispatcher_.reset();
+}
+
+} // namespace views

Powered by Google App Engine
This is Rietveld 408576698