diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-22 23:35:56 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-22 23:35:56 +0000 |
commit | 4b87bc2e3c13bd572a2b1b9a08ea2644120e6d6c (patch) | |
tree | d1dd9f473c130f4e51a9cda7e8b49cb42c8f13bf /ui | |
parent | 4ad932db8c764a861f9c5a578599271f179a9020 (diff) | |
download | chromium_src-4b87bc2e3c13bd572a2b1b9a08ea2644120e6d6c.zip chromium_src-4b87bc2e3c13bd572a2b1b9a08ea2644120e6d6c.tar.gz chromium_src-4b87bc2e3c13bd572a2b1b9a08ea2644120e6d6c.tar.bz2 |
Revert 128328 - Remove stops_event_propagation from Window, since it's broken.
Changes it to be implemented by the Aura client, via a new interface EventClient.
The client can determine whether or not a given window and its subtree can receive events.
I also cleaned up the way screen locking is entered/exited via the delegate, and some stuff in ash/shell.
http://crbug.com/119347
TEST=none
Review URL: https://chromiumcodereview.appspot.com/9788001
TBR=ben@chromium.org
Review URL: https://chromiumcodereview.appspot.com/9808044
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@128338 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/aura/aura.gyp | 2 | ||||
-rw-r--r-- | ui/aura/client/event_client.cc | 27 | ||||
-rw-r--r-- | ui/aura/client/event_client.h | 36 | ||||
-rw-r--r-- | ui/aura/root_window.cc | 7 | ||||
-rw-r--r-- | ui/aura/root_window_unittest.cc | 153 | ||||
-rw-r--r-- | ui/aura/window.cc | 53 | ||||
-rw-r--r-- | ui/aura/window.h | 24 | ||||
-rw-r--r-- | ui/aura/window_unittest.cc | 56 | ||||
-rw-r--r-- | ui/oak/oak_aura_window_display.cc | 4 |
9 files changed, 110 insertions, 252 deletions
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp index e0dafba..89aea94 100644 --- a/ui/aura/aura.gyp +++ b/ui/aura/aura.gyp @@ -38,8 +38,6 @@ 'client/drag_drop_client.h', 'client/drag_drop_delegate.cc', 'client/drag_drop_delegate.h', - 'client/event_client.cc', - 'client/event_client.h', 'client/stacking_client.cc', 'client/stacking_client.h', 'client/tooltip_client.cc', diff --git a/ui/aura/client/event_client.cc b/ui/aura/client/event_client.cc deleted file mode 100644 index dfb3410..0000000 --- a/ui/aura/client/event_client.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2012 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/aura/client/event_client.h" - -#include "ui/aura/root_window.h" -#include "ui/aura/window_property.h" - -DECLARE_WINDOW_PROPERTY_TYPE(aura::client::EventClient*) - -namespace aura { -namespace client { - -DEFINE_WINDOW_PROPERTY_KEY(EventClient*, kRootWindowEventClientKey, NULL); - -void SetEventClient(RootWindow* root_window, EventClient* client) { - root_window->SetProperty(kRootWindowEventClientKey, client); -} - -EventClient* GetEventClient(const RootWindow* root_window) { - return root_window ? - root_window->GetProperty(kRootWindowEventClientKey) : NULL; -} - -} // namespace client -} // namespace aura diff --git a/ui/aura/client/event_client.h b/ui/aura/client/event_client.h deleted file mode 100644 index caf3a2b..0000000 --- a/ui/aura/client/event_client.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_AURA_CLIENT_EVENT_CLIENT_H_ -#define UI_AURA_CLIENT_EVENT_CLIENT_H_ -#pragma once - -#include "ui/aura/aura_export.h" -#include "ui/aura/window.h" - -namespace aura { - -class Event; -class RootWindow; - -namespace client { - -// An interface implemented by an object that alters event processing. -class AURA_EXPORT EventClient { - public: - // Returns true if events can be processed by |window| or any of its children. - virtual bool CanProcessEventsWithinSubtree(const Window* window) const = 0; - - protected: - virtual ~EventClient() {} -}; - -// Sets/Gets the event client on the RootWindow. -AURA_EXPORT void SetEventClient(RootWindow* root_window, EventClient* client); -AURA_EXPORT EventClient* GetEventClient(const RootWindow* root_window); - -} // namespace clients -} // namespace aura - -#endif // UI_AURA_CLIENT_EVENT_CLIENT_H_ diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 65c0fb1..12ee747 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -12,7 +12,6 @@ #include "base/message_loop.h" #include "ui/aura/aura_switches.h" #include "ui/aura/client/activation_client.h" -#include "ui/aura/client/event_client.h" #include "ui/aura/env.h" #include "ui/aura/root_window_host.h" #include "ui/aura/root_window_observer.h" @@ -195,12 +194,6 @@ bool RootWindow::DispatchMouseEvent(MouseEvent* event) { bool RootWindow::DispatchKeyEvent(KeyEvent* event) { DispatchHeldMouseMove(); KeyEvent translated_event(*event); - - client::EventClient* client = client::GetEventClient(GetRootWindow()); - if (client && !client->CanProcessEventsWithinSubtree(focused_window_)) { - SetFocusedWindow(NULL, NULL); - return false; - } return ProcessKeyEvent(focused_window_, &translated_event); } diff --git a/ui/aura/root_window_unittest.cc b/ui/aura/root_window_unittest.cc index 778ed39..3b336f0 100644 --- a/ui/aura/root_window_unittest.cc +++ b/ui/aura/root_window_unittest.cc @@ -5,16 +5,12 @@ #include "ui/aura/root_window.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/client/event_client.h" #include "ui/aura/env.h" #include "ui/aura/event.h" -#include "ui/aura/event_filter.h" #include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/event_generator.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/test/test_windows.h" #include "ui/base/hit_test.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" @@ -167,153 +163,4 @@ TEST_F(RootWindowTest, TranslatedEvent) { EXPECT_EQ("100,100", translated_event.root_location().ToString()); } -namespace { - -class TestEventClient : public client::EventClient { - public: - static const int kNonLockWindowId = 100; - static const int kLockWindowId = 200; - - explicit TestEventClient(RootWindow* root_window) - : root_window_(root_window), - lock_(false) { - client::SetEventClient(root_window_, this); - Window* lock_window = - test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_); - lock_window->set_id(kLockWindowId); - Window* non_lock_window = - test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_); - non_lock_window->set_id(kNonLockWindowId); - } - virtual ~TestEventClient() { - client::SetEventClient(root_window_, NULL); - } - - // Starts/stops locking. Locking prevents windows other than those inside - // the lock container from receiving events, getting focus etc. - void Lock() { - lock_ = true; - } - void Unlock() { - lock_ = false; - } - - Window* GetLockWindow() { - return const_cast<Window*>( - static_cast<const TestEventClient*>(this)->GetLockWindow()); - } - const Window* GetLockWindow() const { - return root_window_->GetChildById(kLockWindowId); - } - Window* GetNonLockWindow() { - return root_window_->GetChildById(kNonLockWindowId); - } - - private: - // Overridden from client::EventClient: - virtual bool CanProcessEventsWithinSubtree( - const Window* window) const OVERRIDE { - return lock_ ? GetLockWindow()->Contains(window) : true; - } - - RootWindow* root_window_; - bool lock_; - - DISALLOW_COPY_AND_ASSIGN(TestEventClient); -}; - -class TestEventFilter : public aura::EventFilter { - public: - TestEventFilter() { - Reset(); - } - virtual ~TestEventFilter() {} - - void Reset() { - mouse_event_count_ = 0; - } - - int mouse_event_count() const { return mouse_event_count_; } - - private: - virtual bool PreHandleKeyEvent(Window* target, KeyEvent* event) OVERRIDE { - return true; - } - virtual bool PreHandleMouseEvent(Window* target, MouseEvent* event) OVERRIDE { - ++mouse_event_count_; - return true; - } - virtual ui::TouchStatus PreHandleTouchEvent(Window* target, - TouchEvent* event) OVERRIDE { - return ui::TOUCH_STATUS_UNKNOWN; - } - virtual ui::GestureStatus PreHandleGestureEvent( - Window* target, - GestureEvent* event) OVERRIDE { - return ui::GESTURE_STATUS_UNKNOWN; - } - - int mouse_event_count_; - - DISALLOW_COPY_AND_ASSIGN(TestEventFilter); -}; - -} // namespace - -TEST_F(RootWindowTest, CanProcessEventsWithinSubtree) { - TestEventClient client(root_window()); - test::TestWindowDelegate d; - - TestEventFilter* nonlock_ef = new TestEventFilter; - TestEventFilter* lock_ef = new TestEventFilter; - client.GetNonLockWindow()->SetEventFilter(nonlock_ef); - client.GetLockWindow()->SetEventFilter(lock_ef); - - Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20), - client.GetNonLockWindow()); - w1->set_id(1); - Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20), - client.GetNonLockWindow()); - w2->set_id(2); - scoped_ptr<Window> w3( - test::CreateTestWindowWithDelegate(&d, 3, gfx::Rect(20, 20, 20, 20), - client.GetLockWindow())); - - w1->Focus(); - EXPECT_TRUE(w1->GetFocusManager()->IsFocusedWindow(w1)); - - client.Lock(); - - // Since we're locked, the attempt to focus w2 will be ignored. - w2->Focus(); - EXPECT_TRUE(w1->GetFocusManager()->IsFocusedWindow(w1)); - EXPECT_FALSE(w1->GetFocusManager()->IsFocusedWindow(w2)); - - { - // Attempting to send a key event to w1 (not in the lock container) should - // cause focus to be reset. - test::EventGenerator generator(root_window()); - generator.PressKey(ui::VKEY_SPACE, 0); - EXPECT_EQ(NULL, w1->GetFocusManager()->GetFocusedWindow()); - } - - { - // Events sent to a window not in the lock container will not be processed. - // i.e. never sent to the non-lock container's event filter. - test::EventGenerator generator(root_window(), w1); - generator.PressLeftButton(); - EXPECT_EQ(0, nonlock_ef->mouse_event_count()); - - // Events sent to a window in the lock container will be processed. - test::EventGenerator generator3(root_window(), w3.get()); - generator3.PressLeftButton(); - EXPECT_EQ(1, lock_ef->mouse_event_count()); - } - - // Prevent w3 from being deleted by the hierarchy since its delegate is owned - // by this scope. - w3->parent()->RemoveChild(w3.get()); -} - - } // namespace aura diff --git a/ui/aura/window.cc b/ui/aura/window.cc index dfa6881..8f08a4b 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc @@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/stl_util.h" #include "base/string_util.h" -#include "ui/aura/client/event_client.h" #include "ui/aura/client/stacking_client.h" #include "ui/aura/client/visibility_client.h" #include "ui/aura/env.h" @@ -54,6 +53,7 @@ Window::Window(WindowDelegate* delegate) id_(-1), transparent_(false), user_data_(NULL), + stops_event_propagation_(false), ignore_events_(false), hit_test_bounds_override_outer_(0), hit_test_bounds_override_inner_(0) { @@ -449,24 +449,12 @@ bool Window::HasFocus() const { bool Window::CanFocus() const { if (!IsVisible() || !parent_ || (delegate_ && !delegate_->CanFocus())) return false; - - // The client may forbid certain windows from receiving focus at a given point - // in time. - client::EventClient* client = client::GetEventClient(GetRootWindow()); - if (client && !client->CanProcessEventsWithinSubtree(this)) - return false; - - return parent_->CanFocus(); + return !IsBehindStopEventsWindow() && parent_->CanFocus(); } bool Window::CanReceiveEvents() const { - // The client may forbid certain windows from receiving events at a given - // point in time. - client::EventClient* client = client::GetEventClient(GetRootWindow()); - if (client && !client->CanProcessEventsWithinSubtree(this)) - return false; - - return parent_ && IsVisible() && parent_->CanReceiveEvents(); + return parent_ && IsVisible() && !IsBehindStopEventsWindow() && + parent_->CanReceiveEvents(); } internal::FocusManager* Window::GetFocusManager() { @@ -502,6 +490,15 @@ bool Window::HasCapture() { return root_window && root_window->capture_window() == this; } +bool Window::StopsEventPropagation() const { + if (!stops_event_propagation_ || children_.empty()) + return false; + aura::Window::Windows::const_iterator it = + std::find_if(children_.begin(), children_.end(), + std::mem_fun(&aura::Window::IsVisible)); + return it != children_.end(); +} + void Window::SuppressPaint() { layer_->SuppressPaint(); } @@ -656,16 +653,6 @@ Window* Window::GetWindowForPoint(const gfx::Point& local_point, rend = children_.rend(); it != rend; ++it) { Window* child = *it; - - if (for_event_handling) { - // The client may not allow events to be processed by certain subtrees. - client::EventClient* client = client::GetEventClient(GetRootWindow()); - if (client && !client->CanProcessEventsWithinSubtree(child)) - continue; - } - - // We don't process events for invisible windows or those that have asked - // to ignore events. if (!child->IsVisible() || (for_event_handling && child->ignore_events_)) continue; @@ -676,6 +663,9 @@ Window* Window::GetWindowForPoint(const gfx::Point& local_point, for_event_handling); if (match) return match; + + if (for_event_handling && child->StopsEventPropagation()) + break; } return delegate_ ? this : NULL; @@ -810,4 +800,15 @@ void Window::UpdateLayerName(const std::string& name) { #endif } +bool Window::IsBehindStopEventsWindow() const { + Windows::const_iterator i = std::find(parent_->children().begin(), + parent_->children().end(), + this); + for (++i; i != parent_->children().end(); ++i) { + if ((*i)->StopsEventPropagation()) + return true; + } + return false; +} + } // namespace aura diff --git a/ui/aura/window.h b/ui/aura/window.h index e728760..9c2703b 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h @@ -218,6 +218,15 @@ class AURA_EXPORT Window : public ui::LayerDelegate { void AddObserver(WindowObserver* observer); void RemoveObserver(WindowObserver* observer); + // When set to true, this Window will stop propagation of all events targeted + // at Windows below it in the z-order, but only if this Window has children. + // This is used to implement lock-screen type functionality where we do not + // want events to be sent to running logged-in windows when the lock screen is + // displayed. + void set_stops_event_propagation(bool stops_event_propagation) { + stops_event_propagation_ = stops_event_propagation; + } + void set_ignore_events(bool ignore_events) { ignore_events_ = ignore_events; } // Sets the window to grab hits for an area extending |outer| pixels outside @@ -285,6 +294,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // Returns true if this window has a mouse capture. bool HasCapture(); + // Returns true if this window is currently stopping event + // propagation for any windows behind it in the z-order. + bool StopsEventPropagation() const; + // Suppresses painting window content by disgarding damaged rect and ignoring // new paint requests. void SuppressPaint(); @@ -345,7 +358,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // If |return_tightest| is true, returns the tightest-containing (i.e. // furthest down the hierarchy) Window containing the point; otherwise, // returns the loosest. If |for_event_handling| is true, then hit-test masks - // are honored; otherwise, only bounds checks are performed. + // and StopsEventPropagation() are honored; otherwise, only bounds checks are + // performed. Window* GetWindowForPoint(const gfx::Point& local_point, bool return_tightest, bool for_event_handling); @@ -378,6 +392,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // Updates the layer name with a name based on the window's name and id. void UpdateLayerName(const std::string& name); + // Returns true if this window is behind a window that stops event + // propagation. + bool IsBehindStopEventsWindow() const; + client::WindowType type_; WindowDelegate* delegate_; @@ -419,6 +437,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate { void* user_data_; + // When true, events are not sent to windows behind this one in the z-order, + // provided this window has children. See set_stops_event_propagation(). + bool stops_event_propagation_; + // Makes the window pass all events through to any windows behind it. bool ignore_events_; diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 7f7fd75..bac8e51 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -355,6 +355,10 @@ TEST_F(WindowTest, GetTopWindowContainingPoint) { scoped_ptr<Window> w311( CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get())); + // The stop-event-propagation flag shouldn't have any effect on the behavior + // of this method. + w3->set_stops_event_propagation(true); + EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0))); EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5))); EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10))); @@ -804,6 +808,58 @@ TEST_F(WindowTest, Visibility) { EXPECT_TRUE(w3->IsVisible()); } +// When set_consume_events() is called with |true| for a Window, that Window +// should make sure that none behind it in the z-order see events if it has +// children. If it does not have children, event targeting works as usual. +TEST_F(WindowTest, StopsEventPropagation) { + TestWindowDelegate d11; + TestWindowDelegate d111; + TestWindowDelegate d121; + scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1, + gfx::Rect(0, 0, 500, 500), NULL)); + scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11, + gfx::Rect(0, 0, 500, 500), w1.get())); + scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111, + gfx::Rect(50, 50, 450, 450), w11.get())); + scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12, + gfx::Rect(0, 0, 500, 500), w1.get())); + scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121, + gfx::Rect(150, 150, 50, 50), NULL)); + + w12->set_stops_event_propagation(true); + EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10))); + + EXPECT_TRUE(w111->CanFocus()); + EXPECT_TRUE(w111->CanReceiveEvents()); + w111->Focus(); + EXPECT_EQ(w111.get(), w1->GetFocusManager()->GetFocusedWindow()); + + w12->AddChild(w121.get()); + + EXPECT_EQ(NULL, w1->GetEventHandlerForPoint(gfx::Point(10, 10))); + EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(175, 175))); + + // It should be possible to focus w121 since it is at or above the + // consumes_events_ window. + EXPECT_TRUE(w121->CanFocus()); + EXPECT_TRUE(w121->CanReceiveEvents()); + w121->Focus(); + EXPECT_EQ(w121.get(), w1->GetFocusManager()->GetFocusedWindow()); + + // An attempt to focus 111 should be ignored and w121 should retain focus, + // since a consumes_events_ window with a child is in the z-index above w111. + EXPECT_FALSE(w111->CanReceiveEvents()); + w111->Focus(); + EXPECT_EQ(w121.get(), w1->GetFocusManager()->GetFocusedWindow()); + + // Hiding w121 should make 111 focusable. + w121->Hide(); + EXPECT_TRUE(w111->CanFocus()); + EXPECT_TRUE(w111->CanReceiveEvents()); + w111->Focus(); + EXPECT_EQ(w111.get(), w1->GetFocusManager()->GetFocusedWindow()); +} + TEST_F(WindowTest, IgnoreEventsTest) { TestWindowDelegate d11; TestWindowDelegate d12; diff --git a/ui/oak/oak_aura_window_display.cc b/ui/oak/oak_aura_window_display.cc index fce9406..214a005 100644 --- a/ui/oak/oak_aura_window_display.cc +++ b/ui/oak/oak_aura_window_display.cc @@ -32,6 +32,7 @@ ROW_ROOTWINDOW, ROW_TRANSIENTCHILDREN, ROW_TRANSIENTPARENT, ROW_USERDATA, +ROW_STOPSEVENTPROPAGATION, ROW_IGNOREEVENTS, ROW_CANFOCUS, ROW_HITTESTBOUNDSOVERRIDE, @@ -136,6 +137,9 @@ string16 OakAuraWindowDisplay::GetText(int row, int column_id) { window_->transient_parent()); case ROW_USERDATA: return PropertyWithVoidStar("User Data: ", window_->user_data()); + case ROW_STOPSEVENTPROPAGATION: + return PropertyWithBool("Stops event propagation: ", + window_->StopsEventPropagation()); case ROW_IGNOREEVENTS: return PropertyWithBool("Can receive events: ", window_->CanReceiveEvents()); |