summaryrefslogtreecommitdiffstats
path: root/ui/aura
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-22 22:48:50 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-22 22:48:50 +0000
commit9d9ac7657928ab1f0dc219f7c4bd857f1986ba9d (patch)
tree04ae74c8391f19e76aac6471363efe1321c0f360 /ui/aura
parent452dc95ddca95d10700dcd51542b50725db355a6 (diff)
downloadchromium_src-9d9ac7657928ab1f0dc219f7c4bd857f1986ba9d.zip
chromium_src-9d9ac7657928ab1f0dc219f7c4bd857f1986ba9d.tar.gz
chromium_src-9d9ac7657928ab1f0dc219f7c4bd857f1986ba9d.tar.bz2
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 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@128328 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/aura')
-rw-r--r--ui/aura/aura.gyp2
-rw-r--r--ui/aura/client/event_client.cc27
-rw-r--r--ui/aura/client/event_client.h36
-rw-r--r--ui/aura/root_window.cc7
-rw-r--r--ui/aura/root_window_unittest.cc153
-rw-r--r--ui/aura/window.cc53
-rw-r--r--ui/aura/window.h24
-rw-r--r--ui/aura/window_unittest.cc56
8 files changed, 252 insertions, 106 deletions
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp
index e46a883..934a5d1 100644
--- a/ui/aura/aura.gyp
+++ b/ui/aura/aura.gyp
@@ -38,6 +38,8 @@
'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
new file mode 100644
index 0000000..dfb3410
--- /dev/null
+++ b/ui/aura/client/event_client.cc
@@ -0,0 +1,27 @@
+// 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
new file mode 100644
index 0000000..caf3a2b
--- /dev/null
+++ b/ui/aura/client/event_client.h
@@ -0,0 +1,36 @@
+// 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 1e8a6b5..a7a74a4 100644
--- a/ui/aura/root_window.cc
+++ b/ui/aura/root_window.cc
@@ -12,6 +12,7 @@
#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"
@@ -194,6 +195,12 @@ 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 3b336f0..778ed39 100644
--- a/ui/aura/root_window_unittest.cc
+++ b/ui/aura/root_window_unittest.cc
@@ -5,12 +5,16 @@
#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"
@@ -163,4 +167,153 @@ 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 8f08a4b..dfa6881 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -9,6 +9,7 @@
#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"
@@ -53,7 +54,6 @@ 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,12 +449,24 @@ bool Window::HasFocus() const {
bool Window::CanFocus() const {
if (!IsVisible() || !parent_ || (delegate_ && !delegate_->CanFocus()))
return false;
- return !IsBehindStopEventsWindow() && parent_->CanFocus();
+
+ // 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();
}
bool Window::CanReceiveEvents() const {
- return parent_ && IsVisible() && !IsBehindStopEventsWindow() &&
- parent_->CanReceiveEvents();
+ // 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();
}
internal::FocusManager* Window::GetFocusManager() {
@@ -490,15 +502,6 @@ 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();
}
@@ -653,6 +656,16 @@ 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;
@@ -663,9 +676,6 @@ 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;
@@ -800,15 +810,4 @@ 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 9c2703b..e728760 100644
--- a/ui/aura/window.h
+++ b/ui/aura/window.h
@@ -218,15 +218,6 @@ 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
@@ -294,10 +285,6 @@ 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();
@@ -358,8 +345,7 @@ 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
- // and StopsEventPropagation() are honored; otherwise, only bounds checks are
- // performed.
+ // are honored; otherwise, only bounds checks are performed.
Window* GetWindowForPoint(const gfx::Point& local_point,
bool return_tightest,
bool for_event_handling);
@@ -392,10 +378,6 @@ 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_;
@@ -437,10 +419,6 @@ 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 bac8e51..7f7fd75 100644
--- a/ui/aura/window_unittest.cc
+++ b/ui/aura/window_unittest.cc
@@ -355,10 +355,6 @@ 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)));
@@ -808,58 +804,6 @@ 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;