1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/root_window_event_filter.h"
8 #include "ash/wm/activation_controller.h"
9 #include "ash/wm/power_button_controller.h"
10 #include "ash/wm/window_util.h"
11 #include "ui/aura/event.h"
12 #include "ui/aura/focus_manager.h"
13 #include "ui/aura/root_window.h"
14 #include "ui/aura/window_delegate.h"
15 #include "ui/base/hit_test.h"
22 // Returns the default cursor for a window component.
23 gfx::NativeCursor
CursorForWindowComponent(int window_component
) {
24 switch (window_component
) {
26 return aura::kCursorSouthResize
;
28 return aura::kCursorSouthWestResize
;
30 return aura::kCursorSouthEastResize
;
32 return aura::kCursorWestResize
;
34 return aura::kCursorEastResize
;
36 return aura::kCursorNorthResize
;
38 return aura::kCursorNorthWestResize
;
40 return aura::kCursorNorthEastResize
;
42 return aura::kCursorNull
;
46 aura::Window
* FindFocusableWindowFor(aura::Window
* window
) {
47 while (window
&& !window
->CanFocus())
48 window
= window
->parent();
54 ////////////////////////////////////////////////////////////////////////////////
55 // RootWindowEventFilter, public:
57 RootWindowEventFilter::RootWindowEventFilter()
58 : cursor_lock_count_(0),
59 did_cursor_change_(false),
60 cursor_to_set_on_unlock_(0),
61 update_cursor_visibility_(true) {
64 RootWindowEventFilter::~RootWindowEventFilter() {
65 // Additional filters are not owned by RootWindowEventFilter and they
66 // should all be removed when running here. |filters_| has
67 // check_empty == true and will DCHECK failure if it is not empty.
70 void RootWindowEventFilter::LockCursor() {
74 void RootWindowEventFilter::UnlockCursor() {
76 DCHECK_GE(cursor_lock_count_
, 0);
77 if (cursor_lock_count_
== 0) {
78 if (did_cursor_change_
) {
79 did_cursor_change_
= false;
80 Shell::GetRootWindow()->SetCursor(cursor_to_set_on_unlock_
);
82 did_cursor_change_
= false;
83 cursor_to_set_on_unlock_
= 0;
87 void RootWindowEventFilter::AddFilter(aura::EventFilter
* filter
) {
88 filters_
.AddObserver(filter
);
91 void RootWindowEventFilter::RemoveFilter(aura::EventFilter
* filter
) {
92 filters_
.RemoveObserver(filter
);
95 size_t RootWindowEventFilter::GetFilterCount() const {
96 return filters_
.size();
99 ////////////////////////////////////////////////////////////////////////////////
100 // RootWindowEventFilter, EventFilter implementation:
102 bool RootWindowEventFilter::PreHandleKeyEvent(aura::Window
* target
,
103 aura::KeyEvent
* event
) {
104 return FilterKeyEvent(target
, event
);
107 bool RootWindowEventFilter::PreHandleMouseEvent(aura::Window
* target
,
108 aura::MouseEvent
* event
) {
109 // We must always update the cursor, otherwise the cursor can get stuck if an
110 // event filter registered with us consumes the event.
111 if (event
->type() == ui::ET_MOUSE_MOVED
) {
112 if (update_cursor_visibility_
)
113 SetCursorVisible(target
, event
, true);
115 UpdateCursor(target
, event
);
118 if (FilterMouseEvent(target
, event
))
121 if (event
->type() == ui::ET_MOUSE_PRESSED
&& GetActiveWindow() != target
)
122 target
->GetFocusManager()->SetFocusedWindow(FindFocusableWindowFor(target
));
127 ui::TouchStatus
RootWindowEventFilter::PreHandleTouchEvent(
128 aura::Window
* target
,
129 aura::TouchEvent
* event
) {
130 ui::TouchStatus status
= FilterTouchEvent(target
, event
);
131 if (status
!= ui::TOUCH_STATUS_UNKNOWN
)
134 if (event
->type() == ui::ET_TOUCH_PRESSED
) {
135 if (update_cursor_visibility_
)
136 SetCursorVisible(target
, event
, false);
138 target
->GetFocusManager()->SetFocusedWindow(FindFocusableWindowFor(target
));
140 return ui::TOUCH_STATUS_UNKNOWN
;
143 ui::GestureStatus
RootWindowEventFilter::PreHandleGestureEvent(
144 aura::Window
* target
,
145 aura::GestureEvent
* event
) {
147 return ui::GESTURE_STATUS_UNKNOWN
;
150 ////////////////////////////////////////////////////////////////////////////////
151 // RootWindowEventFilter, private:
153 void RootWindowEventFilter::UpdateCursor(aura::Window
* target
,
154 aura::MouseEvent
* event
) {
155 gfx::NativeCursor cursor
= target
->GetCursor(event
->location());
156 if (event
->flags() & ui::EF_IS_NON_CLIENT
) {
157 int window_component
=
158 target
->delegate()->GetNonClientComponent(event
->location());
159 cursor
= CursorForWindowComponent(window_component
);
161 if (cursor_lock_count_
== 0) {
162 Shell::GetRootWindow()->SetCursor(cursor
);
164 cursor_to_set_on_unlock_
= cursor
;
165 did_cursor_change_
= true;
169 void RootWindowEventFilter::SetCursorVisible(aura::Window
* target
,
170 aura::LocatedEvent
* event
,
172 Shell::GetRootWindow()->ShowCursor(show
);
175 bool RootWindowEventFilter::FilterKeyEvent(aura::Window
* target
,
176 aura::KeyEvent
* event
) {
177 bool handled
= false;
178 if (filters_
.might_have_observers()) {
179 ObserverListBase
<aura::EventFilter
>::Iterator
it(filters_
);
180 aura::EventFilter
* filter
;
181 while (!handled
&& (filter
= it
.GetNext()) != NULL
)
182 handled
= filter
->PreHandleKeyEvent(target
, event
);
187 bool RootWindowEventFilter::FilterMouseEvent(aura::Window
* target
,
188 aura::MouseEvent
* event
) {
189 bool handled
= false;
190 if (filters_
.might_have_observers()) {
191 ObserverListBase
<aura::EventFilter
>::Iterator
it(filters_
);
192 aura::EventFilter
* filter
;
193 while (!handled
&& (filter
= it
.GetNext()) != NULL
)
194 handled
= filter
->PreHandleMouseEvent(target
, event
);
199 ui::TouchStatus
RootWindowEventFilter::FilterTouchEvent(
200 aura::Window
* target
,
201 aura::TouchEvent
* event
) {
202 ui::TouchStatus status
= ui::TOUCH_STATUS_UNKNOWN
;
203 if (filters_
.might_have_observers()) {
204 ObserverListBase
<aura::EventFilter
>::Iterator
it(filters_
);
205 aura::EventFilter
* filter
;
206 while (status
== ui::TOUCH_STATUS_UNKNOWN
&&
207 (filter
= it
.GetNext()) != NULL
) {
208 status
= filter
->PreHandleTouchEvent(target
, event
);
214 } // namespace internal