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

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: More fixes for sky 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/controls/menu/menu_message_loop_aura.h ('k') | ui/views/controls/menu/menu_message_loop_mac.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..f49920b937d7a8e4cc8bf68d10771125613fab7e
--- /dev/null
+++ b/ui/views/controls/menu/menu_message_loop_aura.cc
@@ -0,0 +1,195 @@
+// Copyright 2014 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 "ui/views/controls/menu/menu_message_loop_aura.h"
+
+#if defined(OS_WIN)
+#include <windowsx.h>
+#endif
+
+#include "base/run_loop.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.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_controller.h"
+#include "ui/views/widget/widget.h"
+#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
+
+using aura::client::ScreenPositionClient;
+
+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
+
+// static
+MenuMessageLoop* MenuMessageLoop::Create() {
+ return new MenuMessageLoopAura;
+}
+
+MenuMessageLoopAura::MenuMessageLoopAura() : owner_(NULL) {
+}
+
+MenuMessageLoopAura::~MenuMessageLoopAura() {
+}
+
+void MenuMessageLoopAura::RepostEventToWindow(const ui::LocatedEvent& event,
+ gfx::NativeWindow window,
+ const gfx::Point& screen_loc) {
+ 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);
+}
+
+void MenuMessageLoopAura::Run(MenuController* controller,
+ Widget* owner,
+ bool nested_menu) {
+ // |owner_| may be NULL.
+ owner_ = owner;
+ aura::Window* root = GetOwnerRootWindow(owner_);
+
+#if defined(OS_WIN)
+ internal::MenuMessagePumpDispatcher nested_dispatcher(controller);
+ 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
+ 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);
+ }
+ 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 MenuMessageLoopAura::ShouldQuitNow() const {
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ return !aura::client::GetDragDropClient(root) ||
+ !aura::client::GetDragDropClient(root)->IsDragDropInProgress();
+}
+
+void MenuMessageLoopAura::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();
+}
+
+void MenuMessageLoopAura::ClearOwner() {
+ owner_ = NULL;
+}
+
+} // namespace views
« no previous file with comments | « ui/views/controls/menu/menu_message_loop_aura.h ('k') | ui/views/controls/menu/menu_message_loop_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698