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 "ui/aura/root_window.h"
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/client/cursor_client.h"
16 #include "ui/aura/client/event_client.h"
17 #include "ui/aura/client/focus_client.h"
18 #include "ui/aura/client/screen_position_client.h"
19 #include "ui/aura/env.h"
20 #include "ui/aura/root_window_observer.h"
21 #include "ui/aura/window.h"
22 #include "ui/aura/window_delegate.h"
23 #include "ui/aura/window_targeter.h"
24 #include "ui/aura/window_tracker.h"
25 #include "ui/aura/window_tree_host.h"
26 #include "ui/base/hit_test.h"
27 #include "ui/base/view_prop.h"
28 #include "ui/compositor/dip_util.h"
29 #include "ui/compositor/layer.h"
30 #include "ui/compositor/layer_animator.h"
31 #include "ui/events/event.h"
32 #include "ui/events/gestures/gesture_recognizer.h"
33 #include "ui/events/gestures/gesture_types.h"
34 #include "ui/gfx/screen.h"
38 typedef ui::EventDispatchDetails DispatchDetails
;
44 const char kRootWindowForAcceleratedWidget
[] =
45 "__AURA_ROOT_WINDOW_ACCELERATED_WIDGET__";
47 // Returns true if |target| has a non-client (frame) component at |location|,
48 // in window coordinates.
49 bool IsNonClientLocation(Window
* target
, const gfx::Point
& location
) {
50 if (!target
->delegate())
52 int hit_test_code
= target
->delegate()->GetNonClientComponent(location
);
53 return hit_test_code
!= HTCLIENT
&& hit_test_code
!= HTNOWHERE
;
56 Window
* ConsumerToWindow(ui::GestureConsumer
* consumer
) {
57 return consumer
? static_cast<Window
*>(consumer
) : NULL
;
60 void SetLastMouseLocation(const Window
* root_window
,
61 const gfx::Point
& location_in_root
) {
62 client::ScreenPositionClient
* client
=
63 client::GetScreenPositionClient(root_window
);
65 gfx::Point location_in_screen
= location_in_root
;
66 client
->ConvertPointToScreen(root_window
, &location_in_screen
);
67 Env::GetInstance()->set_last_mouse_location(location_in_screen
);
69 Env::GetInstance()->set_last_mouse_location(location_in_root
);
73 WindowTreeHost
* CreateHost(RootWindow
* root_window
,
74 const RootWindow::CreateParams
& params
) {
75 WindowTreeHost
* host
= params
.host
?
76 params
.host
: WindowTreeHost::Create(params
.initial_bounds
);
77 host
->set_delegate(root_window
);
81 bool IsEventCandidateForHold(const ui::Event
& event
) {
82 if (event
.type() == ui::ET_TOUCH_MOVED
)
84 if (event
.type() == ui::ET_MOUSE_DRAGGED
)
86 if (event
.IsMouseEvent() && (event
.flags() & ui::EF_IS_SYNTHESIZED
))
93 RootWindow::CreateParams::CreateParams(const gfx::Rect
& a_initial_bounds
)
94 : initial_bounds(a_initial_bounds
),
98 ////////////////////////////////////////////////////////////////////////////////
99 // RootWindow, public:
101 RootWindow::RootWindow(const CreateParams
& params
)
102 : window_(new Window(NULL
)),
103 host_(CreateHost(this, params
)),
105 mouse_pressed_handler_(NULL
),
106 mouse_moved_handler_(NULL
),
107 event_dispatch_target_(NULL
),
108 old_dispatch_target_(NULL
),
109 synthesize_mouse_move_(false),
111 dispatching_held_event_(false),
112 repost_event_factory_(this),
113 held_event_factory_(this) {
114 window()->set_dispatcher(this);
115 window()->SetName("RootWindow");
116 window()->SetEventTargeter(
117 scoped_ptr
<ui::EventTargeter
>(new WindowTargeter()));
119 prop_
.reset(new ui::ViewProp(host_
->GetAcceleratedWidget(),
120 kRootWindowForAcceleratedWidget
,
122 ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
125 RootWindow::~RootWindow() {
126 TRACE_EVENT0("shutdown", "RootWindow::Destructor");
128 ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
130 // An observer may have been added by an animation on the RootWindow.
131 window()->layer()->GetAnimator()->RemoveObserver(this);
133 // Destroy child windows while we're still valid. This is also done by
134 // ~Window, but by that time any calls to virtual methods overriden here (such
135 // as GetRootWindow()) result in Window's implementation. By destroying here
136 // we ensure GetRootWindow() still returns this.
137 window()->RemoveOrDestroyChildren();
139 // Destroying/removing child windows may try to access |host_| (eg.
140 // GetAcceleratedWidget())
143 window()->set_dispatcher(NULL
);
147 RootWindow
* RootWindow::GetForAcceleratedWidget(
148 gfx::AcceleratedWidget widget
) {
149 return reinterpret_cast<RootWindow
*>(
150 ui::ViewProp::GetValue(widget
, kRootWindowForAcceleratedWidget
));
153 void RootWindow::PrepareForShutdown() {
154 host_
->PrepareForShutdown();
155 // discard synthesize event request as well.
156 synthesize_mouse_move_
= false;
159 void RootWindow::RepostEvent(const ui::LocatedEvent
& event
) {
160 DCHECK(event
.type() == ui::ET_MOUSE_PRESSED
||
161 event
.type() == ui::ET_GESTURE_TAP_DOWN
);
162 // We allow for only one outstanding repostable event. This is used
163 // in exiting context menus. A dropped repost request is allowed.
164 if (event
.type() == ui::ET_MOUSE_PRESSED
) {
165 held_repostable_event_
.reset(
167 static_cast<const ui::MouseEvent
&>(event
),
168 static_cast<aura::Window
*>(event
.target()),
170 base::MessageLoop::current()->PostNonNestableTask(
172 base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents
),
173 repost_event_factory_
.GetWeakPtr()));
175 DCHECK(event
.type() == ui::ET_GESTURE_TAP_DOWN
);
176 held_repostable_event_
.reset();
177 // TODO(rbyers): Reposing of gestures is tricky to get
178 // right, so it's not yet supported. crbug.com/170987.
182 WindowTreeHostDelegate
* RootWindow::AsWindowTreeHostDelegate() {
186 void RootWindow::OnMouseEventsEnableStateChanged(bool enabled
) {
187 // Send entered / exited so that visual state can be updated to match
188 // mouse events state.
189 PostMouseMoveEventAfterWindowChange();
190 // TODO(mazda): Add code to disable mouse events when |enabled| == false.
193 Window
* RootWindow::GetGestureTarget(ui::GestureEvent
* event
) {
194 Window
* target
= NULL
;
195 if (!event
->IsEndingEvent()) {
196 // The window that received the start event (e.g. scroll begin) needs to
197 // receive the end event (e.g. scroll end).
198 target
= client::GetCaptureWindow(window());
201 target
= ConsumerToWindow(
202 ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event
));
208 void RootWindow::DispatchGestureEvent(ui::GestureEvent
* event
) {
209 DispatchDetails details
= DispatchHeldEvents();
210 if (details
.dispatcher_destroyed
)
213 Window
* target
= GetGestureTarget(event
);
215 event
->ConvertLocationToTarget(window(), target
);
216 DispatchDetails details
= DispatchEvent(target
, event
);
217 if (details
.dispatcher_destroyed
)
222 void RootWindow::OnWindowDestroying(Window
* window
) {
223 DispatchMouseExitToHidingWindow(window
);
224 if (window
->IsVisible() &&
225 window
->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
226 PostMouseMoveEventAfterWindowChange();
229 // Hiding the window releases capture which can implicitly destroy the window
230 // so the window may no longer be valid after this call.
231 OnWindowHidden(window
, WINDOW_DESTROYED
);
234 void RootWindow::OnWindowBoundsChanged(Window
* window
,
235 bool contained_mouse_point
) {
236 if (contained_mouse_point
||
237 (window
->IsVisible() &&
238 window
->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
239 PostMouseMoveEventAfterWindowChange();
243 void RootWindow::DispatchMouseExitToHidingWindow(Window
* window
) {
244 // The mouse capture is intentionally ignored. Think that a mouse enters
245 // to a window, the window sets the capture, the mouse exits the window,
246 // and then it releases the capture. In that case OnMouseExited won't
247 // be called. So it is natural not to emit OnMouseExited even though
248 // |window| is the capture window.
249 gfx::Point last_mouse_location
= GetLastMouseLocationInRoot();
250 if (window
->Contains(mouse_moved_handler_
) &&
251 window
->ContainsPointInRoot(last_mouse_location
))
252 DispatchMouseExitAtPoint(last_mouse_location
);
255 void RootWindow::DispatchMouseExitAtPoint(const gfx::Point
& point
) {
256 ui::MouseEvent
event(ui::ET_MOUSE_EXITED
, point
, point
, ui::EF_NONE
,
258 DispatchDetails details
=
259 DispatchMouseEnterOrExit(event
, ui::ET_MOUSE_EXITED
);
260 if (details
.dispatcher_destroyed
)
264 void RootWindow::OnWindowVisibilityChanged(Window
* window
, bool is_visible
) {
265 if (window
->ContainsPointInRoot(GetLastMouseLocationInRoot()))
266 PostMouseMoveEventAfterWindowChange();
268 // Hiding the window releases capture which can implicitly destroy the window
269 // so the window may no longer be valid after this call.
271 OnWindowHidden(window
, WINDOW_HIDDEN
);
274 void RootWindow::OnWindowTransformed(Window
* window
, bool contained_mouse
) {
275 if (contained_mouse
||
276 (window
->IsVisible() &&
277 window
->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
278 PostMouseMoveEventAfterWindowChange();
282 void RootWindow::OnKeyboardMappingChanged() {
283 FOR_EACH_OBSERVER(RootWindowObserver
, observers_
,
284 OnKeyboardMappingChanged(this));
287 void RootWindow::OnWindowTreeHostCloseRequested() {
288 FOR_EACH_OBSERVER(RootWindowObserver
, observers_
,
289 OnWindowTreeHostCloseRequested(this));
292 void RootWindow::AddRootWindowObserver(RootWindowObserver
* observer
) {
293 observers_
.AddObserver(observer
);
296 void RootWindow::RemoveRootWindowObserver(RootWindowObserver
* observer
) {
297 observers_
.RemoveObserver(observer
);
300 void RootWindow::ProcessedTouchEvent(ui::TouchEvent
* event
,
302 ui::EventResult result
) {
303 scoped_ptr
<ui::GestureRecognizer::Gestures
> gestures
;
304 gestures
.reset(ui::GestureRecognizer::Get()->
305 ProcessTouchEventForGesture(*event
, result
, window
));
306 DispatchDetails details
= ProcessGestures(gestures
.get());
307 if (details
.dispatcher_destroyed
)
311 void RootWindow::HoldPointerMoves() {
312 if (!move_hold_count_
)
313 held_event_factory_
.InvalidateWeakPtrs();
315 TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::HoldPointerMoves", this);
318 void RootWindow::ReleasePointerMoves() {
320 DCHECK_GE(move_hold_count_
, 0);
321 if (!move_hold_count_
&& held_move_event_
) {
322 // We don't want to call DispatchHeldEvents directly, because this might be
323 // called from a deep stack while another event, in which case dispatching
324 // another one may not be safe/expected. Instead we post a task, that we
325 // may cancel if HoldPointerMoves is called again before it executes.
326 base::MessageLoop::current()->PostNonNestableTask(
328 base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents
),
329 held_event_factory_
.GetWeakPtr()));
331 TRACE_EVENT_ASYNC_END0("ui", "RootWindow::HoldPointerMoves", this);
334 gfx::Point
RootWindow::GetLastMouseLocationInRoot() const {
335 gfx::Point location
= Env::GetInstance()->last_mouse_location();
336 client::ScreenPositionClient
* client
=
337 client::GetScreenPositionClient(window());
339 client
->ConvertPointFromScreen(window(), &location
);
343 ////////////////////////////////////////////////////////////////////////////////
344 // RootWindow, private:
346 void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent
* event
) {
347 event
->UpdateForRootTransform(host()->GetInverseRootTransform());
350 ui::EventDispatchDetails
RootWindow::DispatchMouseEnterOrExit(
351 const ui::MouseEvent
& event
,
352 ui::EventType type
) {
353 if (event
.type() != ui::ET_MOUSE_CAPTURE_CHANGED
&&
354 !(event
.flags() & ui::EF_IS_SYNTHESIZED
)) {
355 SetLastMouseLocation(window(), event
.root_location());
358 if (!mouse_moved_handler_
|| !mouse_moved_handler_
->delegate())
359 return DispatchDetails();
361 // |event| may be an event in the process of being dispatched to a target (in
362 // which case its locations will be in the event's target's coordinate
363 // system), or a synthetic event created in root-window (in which case, the
364 // event's target will be NULL, and the event will be in the root-window's
365 // coordinate system.
366 aura::Window
* target
= static_cast<Window
*>(event
.target());
369 ui::MouseEvent
translated_event(event
,
371 mouse_moved_handler_
,
373 event
.flags() | ui::EF_IS_SYNTHESIZED
);
374 return DispatchEvent(mouse_moved_handler_
, &translated_event
);
377 ui::EventDispatchDetails
RootWindow::ProcessGestures(
378 ui::GestureRecognizer::Gestures
* gestures
) {
379 DispatchDetails details
;
380 if (!gestures
|| gestures
->empty())
383 Window
* target
= GetGestureTarget(gestures
->get().at(0));
384 for (size_t i
= 0; i
< gestures
->size(); ++i
) {
385 ui::GestureEvent
* event
= gestures
->get().at(i
);
386 event
->ConvertLocationToTarget(window(), target
);
387 details
= DispatchEvent(target
, event
);
388 if (details
.dispatcher_destroyed
|| details
.target_destroyed
)
394 void RootWindow::OnWindowAddedToRootWindow(Window
* attached
) {
395 if (attached
->IsVisible() &&
396 attached
->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
397 PostMouseMoveEventAfterWindowChange();
401 void RootWindow::OnWindowRemovedFromRootWindow(Window
* detached
,
403 DCHECK(aura::client::GetCaptureWindow(window()) != window());
405 DispatchMouseExitToHidingWindow(detached
);
406 if (detached
->IsVisible() &&
407 detached
->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
408 PostMouseMoveEventAfterWindowChange();
411 // Hiding the window releases capture which can implicitly destroy the window
412 // so the window may no longer be valid after this call.
413 OnWindowHidden(detached
, new_root
? WINDOW_MOVING
: WINDOW_HIDDEN
);
416 void RootWindow::OnWindowHidden(Window
* invisible
, WindowHiddenReason reason
) {
417 // If the window the mouse was pressed in becomes invisible, it should no
418 // longer receive mouse events.
419 if (invisible
->Contains(mouse_pressed_handler_
))
420 mouse_pressed_handler_
= NULL
;
421 if (invisible
->Contains(mouse_moved_handler_
))
422 mouse_moved_handler_
= NULL
;
424 CleanupGestureState(invisible
);
426 // Do not clear the capture, and the |event_dispatch_target_| if the
427 // window is moving across root windows, because the target itself
428 // is actually still visible and clearing them stops further event
429 // processing, which can cause unexpected behaviors. See
431 if (reason
!= WINDOW_MOVING
) {
432 Window
* capture_window
= aura::client::GetCaptureWindow(window());
434 if (invisible
->Contains(event_dispatch_target_
))
435 event_dispatch_target_
= NULL
;
437 if (invisible
->Contains(old_dispatch_target_
))
438 old_dispatch_target_
= NULL
;
440 // If the ancestor of the capture window is hidden, release the capture.
441 // Note that this may delete the window so do not use capture_window
443 if (invisible
->Contains(capture_window
) && invisible
!= window())
444 capture_window
->ReleaseCapture();
448 void RootWindow::CleanupGestureState(Window
* window
) {
449 ui::GestureRecognizer::Get()->CancelActiveTouches(window
);
450 ui::GestureRecognizer::Get()->CleanupStateForConsumer(window
);
451 const Window::Windows
& windows
= window
->children();
452 for (Window::Windows::const_iterator iter
= windows
.begin();
453 iter
!= windows
.end();
455 CleanupGestureState(*iter
);
459 ////////////////////////////////////////////////////////////////////////////////
460 // RootWindow, aura::client::CaptureDelegate implementation:
462 void RootWindow::UpdateCapture(Window
* old_capture
,
463 Window
* new_capture
) {
464 // |mouse_moved_handler_| may have been set to a Window in a different root
465 // (see below). Clear it here to ensure we don't end up referencing a stale
467 if (mouse_moved_handler_
&& !window()->Contains(mouse_moved_handler_
))
468 mouse_moved_handler_
= NULL
;
470 if (old_capture
&& old_capture
->GetRootWindow() == window() &&
471 old_capture
->delegate()) {
472 // Send a capture changed event with bogus location data.
473 ui::MouseEvent
event(ui::ET_MOUSE_CAPTURE_CHANGED
, gfx::Point(),
476 DispatchDetails details
= DispatchEvent(old_capture
, &event
);
477 if (details
.dispatcher_destroyed
)
480 old_capture
->delegate()->OnCaptureLost();
484 // Make all subsequent mouse events go to the capture window. We shouldn't
485 // need to send an event here as OnCaptureLost() should take care of that.
486 if (mouse_moved_handler_
|| Env::GetInstance()->IsMouseButtonDown())
487 mouse_moved_handler_
= new_capture
;
489 // Make sure mouse_moved_handler gets updated.
490 DispatchDetails details
= SynthesizeMouseMoveEvent();
491 if (details
.dispatcher_destroyed
)
494 mouse_pressed_handler_
= NULL
;
497 void RootWindow::OnOtherRootGotCapture() {
498 mouse_moved_handler_
= NULL
;
499 mouse_pressed_handler_
= NULL
;
502 void RootWindow::SetNativeCapture() {
506 void RootWindow::ReleaseNativeCapture() {
507 host_
->ReleaseCapture();
510 ////////////////////////////////////////////////////////////////////////////////
511 // RootWindow, ui::EventProcessor implementation:
512 ui::EventTarget
* RootWindow::GetRootTarget() {
516 void RootWindow::PrepareEventForDispatch(ui::Event
* event
) {
517 if (dispatching_held_event_
) {
518 // The held events are already in |window()|'s coordinate system. So it is
519 // not necessary to apply the transform to convert from the host's
520 // coordinate system to |window()|'s coordinate system.
523 if (event
->IsMouseEvent() ||
524 event
->IsScrollEvent() ||
525 event
->IsTouchEvent() ||
526 event
->IsGestureEvent()) {
527 TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent
*>(event
));
531 ////////////////////////////////////////////////////////////////////////////////
532 // RootWindow, ui::EventDispatcherDelegate implementation:
534 bool RootWindow::CanDispatchToTarget(ui::EventTarget
* target
) {
535 return event_dispatch_target_
== target
;
538 ui::EventDispatchDetails
RootWindow::PreDispatchEvent(ui::EventTarget
* target
,
540 if (!dispatching_held_event_
) {
541 bool can_be_held
= IsEventCandidateForHold(*event
);
542 if (!move_hold_count_
|| !can_be_held
) {
544 held_move_event_
.reset();
545 DispatchDetails details
= DispatchHeldEvents();
546 if (details
.dispatcher_destroyed
|| details
.target_destroyed
)
551 Window
* target_window
= static_cast<Window
*>(target
);
552 if (event
->IsMouseEvent()) {
553 PreDispatchMouseEvent(target_window
, static_cast<ui::MouseEvent
*>(event
));
554 } else if (event
->IsScrollEvent()) {
555 PreDispatchLocatedEvent(target_window
,
556 static_cast<ui::ScrollEvent
*>(event
));
557 } else if (event
->IsTouchEvent()) {
558 PreDispatchTouchEvent(target_window
, static_cast<ui::TouchEvent
*>(event
));
560 old_dispatch_target_
= event_dispatch_target_
;
561 event_dispatch_target_
= static_cast<Window
*>(target
);
562 return DispatchDetails();
565 ui::EventDispatchDetails
RootWindow::PostDispatchEvent(ui::EventTarget
* target
,
566 const ui::Event
& event
) {
567 DispatchDetails details
;
568 if (target
!= event_dispatch_target_
)
569 details
.target_destroyed
= true;
570 event_dispatch_target_
= old_dispatch_target_
;
571 old_dispatch_target_
= NULL
;
573 DCHECK(!event_dispatch_target_
|| window()->Contains(event_dispatch_target_
));
576 if (event
.IsTouchEvent() && !details
.target_destroyed
) {
577 // Do not let 'held' touch events contribute to any gestures.
578 if (!held_move_event_
|| !held_move_event_
->IsTouchEvent()) {
579 ui::TouchEvent
orig_event(static_cast<const ui::TouchEvent
&>(event
),
580 static_cast<Window
*>(event
.target()), window());
581 // Get the list of GestureEvents from GestureRecognizer.
582 scoped_ptr
<ui::GestureRecognizer::Gestures
> gestures
;
583 gestures
.reset(ui::GestureRecognizer::Get()->
584 ProcessTouchEventForGesture(orig_event
, event
.result(),
585 static_cast<Window
*>(target
)));
586 return ProcessGestures(gestures
.get());
593 ////////////////////////////////////////////////////////////////////////////////
594 // RootWindow, ui::GestureEventHelper implementation:
596 bool RootWindow::CanDispatchToConsumer(ui::GestureConsumer
* consumer
) {
597 Window
* consumer_window
= ConsumerToWindow(consumer
);;
598 return (consumer_window
&& consumer_window
->GetRootWindow() == window());
601 void RootWindow::DispatchPostponedGestureEvent(ui::GestureEvent
* event
) {
602 DispatchGestureEvent(event
);
605 void RootWindow::DispatchCancelTouchEvent(ui::TouchEvent
* event
) {
606 DispatchDetails details
= OnEventFromSource(event
);
607 if (details
.dispatcher_destroyed
)
611 ////////////////////////////////////////////////////////////////////////////////
612 // RootWindow, ui::LayerAnimationObserver implementation:
614 void RootWindow::OnLayerAnimationEnded(
615 ui::LayerAnimationSequence
* animation
) {
616 host()->UpdateRootWindowSize(host_
->GetBounds().size());
619 void RootWindow::OnLayerAnimationScheduled(
620 ui::LayerAnimationSequence
* animation
) {
623 void RootWindow::OnLayerAnimationAborted(
624 ui::LayerAnimationSequence
* animation
) {
627 ////////////////////////////////////////////////////////////////////////////////
628 // RootWindow, WindowTreeHostDelegate implementation:
630 void RootWindow::OnHostCancelMode() {
631 ui::CancelModeEvent event
;
632 Window
* focused_window
= client::GetFocusClient(window())->GetFocusedWindow();
633 DispatchDetails details
=
634 DispatchEvent(focused_window
? focused_window
: window(), &event
);
635 if (details
.dispatcher_destroyed
)
639 void RootWindow::OnHostActivated() {
640 Env::GetInstance()->RootWindowActivated(this);
643 void RootWindow::OnHostLostWindowCapture() {
644 Window
* capture_window
= client::GetCaptureWindow(window());
645 if (capture_window
&& capture_window
->GetRootWindow() == window())
646 capture_window
->ReleaseCapture();
649 void RootWindow::OnHostLostMouseGrab() {
650 mouse_pressed_handler_
= NULL
;
651 mouse_moved_handler_
= NULL
;
654 void RootWindow::OnHostMoved(const gfx::Point
& origin
) {
655 TRACE_EVENT1("ui", "RootWindow::OnHostMoved",
656 "origin", origin
.ToString());
658 FOR_EACH_OBSERVER(RootWindowObserver
, observers_
,
659 OnWindowTreeHostMoved(this, origin
));
662 void RootWindow::OnHostResized(const gfx::Size
& size
) {
663 TRACE_EVENT1("ui", "RootWindow::OnHostResized",
664 "size", size
.ToString());
666 DispatchDetails details
= DispatchHeldEvents();
667 if (details
.dispatcher_destroyed
)
669 FOR_EACH_OBSERVER(RootWindowObserver
, observers_
,
670 OnWindowTreeHostResized(this));
672 // Constrain the mouse position within the new root Window size.
674 if (host_
->QueryMouseLocation(&point
)) {
675 SetLastMouseLocation(window(),
676 ui::ConvertPointToDIP(window()->layer(), point
));
678 synthesize_mouse_move_
= false;
681 void RootWindow::OnCursorMovedToRootLocation(const gfx::Point
& root_location
) {
682 SetLastMouseLocation(window(), root_location
);
683 synthesize_mouse_move_
= false;
686 RootWindow
* RootWindow::AsRootWindow() {
690 const RootWindow
* RootWindow::AsRootWindow() const {
694 ui::EventProcessor
* RootWindow::GetEventProcessor() {
698 ////////////////////////////////////////////////////////////////////////////////
699 // RootWindow, private:
701 ui::EventDispatchDetails
RootWindow::DispatchHeldEvents() {
702 if (!held_repostable_event_
&& !held_move_event_
)
703 return DispatchDetails();
705 CHECK(!dispatching_held_event_
);
706 dispatching_held_event_
= true;
708 DispatchDetails dispatch_details
;
709 if (held_repostable_event_
) {
710 if (held_repostable_event_
->type() == ui::ET_MOUSE_PRESSED
) {
711 scoped_ptr
<ui::MouseEvent
> mouse_event(
712 static_cast<ui::MouseEvent
*>(held_repostable_event_
.release()));
713 dispatch_details
= OnEventFromSource(mouse_event
.get());
715 // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
718 if (dispatch_details
.dispatcher_destroyed
)
719 return dispatch_details
;
722 if (held_move_event_
) {
723 // If a mouse move has been synthesized, the target location is suspect,
724 // so drop the held mouse event.
725 if (held_move_event_
->IsTouchEvent() ||
726 (held_move_event_
->IsMouseEvent() && !synthesize_mouse_move_
)) {
727 dispatch_details
= OnEventFromSource(held_move_event_
.get());
729 if (!dispatch_details
.dispatcher_destroyed
)
730 held_move_event_
.reset();
733 if (!dispatch_details
.dispatcher_destroyed
)
734 dispatching_held_event_
= false;
735 return dispatch_details
;
738 void RootWindow::PostMouseMoveEventAfterWindowChange() {
739 if (synthesize_mouse_move_
)
741 synthesize_mouse_move_
= true;
742 base::MessageLoop::current()->PostNonNestableTask(
744 base::Bind(base::IgnoreResult(&RootWindow::SynthesizeMouseMoveEvent
),
745 held_event_factory_
.GetWeakPtr()));
748 ui::EventDispatchDetails
RootWindow::SynthesizeMouseMoveEvent() {
749 DispatchDetails details
;
750 if (!synthesize_mouse_move_
)
752 synthesize_mouse_move_
= false;
753 gfx::Point root_mouse_location
= GetLastMouseLocationInRoot();
754 if (!window()->bounds().Contains(root_mouse_location
))
756 gfx::Point host_mouse_location
= root_mouse_location
;
757 host()->ConvertPointToHost(&host_mouse_location
);
758 ui::MouseEvent
event(ui::ET_MOUSE_MOVED
,
761 ui::EF_IS_SYNTHESIZED
,
763 return OnEventFromSource(&event
);
766 void RootWindow::PreDispatchLocatedEvent(Window
* target
,
767 ui::LocatedEvent
* event
) {
768 int flags
= event
->flags();
769 if (IsNonClientLocation(target
, event
->location()))
770 flags
|= ui::EF_IS_NON_CLIENT
;
771 event
->set_flags(flags
);
773 if (!dispatching_held_event_
&&
774 (event
->IsMouseEvent() || event
->IsScrollEvent()) &&
775 !(event
->flags() & ui::EF_IS_SYNTHESIZED
)) {
776 if (event
->type() != ui::ET_MOUSE_CAPTURE_CHANGED
)
777 SetLastMouseLocation(window(), event
->root_location());
778 synthesize_mouse_move_
= false;
782 void RootWindow::PreDispatchMouseEvent(Window
* target
,
783 ui::MouseEvent
* event
) {
784 client::CursorClient
* cursor_client
= client::GetCursorClient(window());
786 !cursor_client
->IsMouseEventsEnabled() &&
787 (event
->flags() & ui::EF_IS_SYNTHESIZED
)) {
792 if (IsEventCandidateForHold(*event
) && !dispatching_held_event_
) {
793 if (move_hold_count_
) {
794 held_move_event_
.reset(new ui::MouseEvent(*event
, target
, window()));
798 // We may have a held event for a period between the time move_hold_count_
799 // fell to 0 and the DispatchHeldEvents executes. Since we're going to
800 // dispatch the new event directly below, we can reset the old one.
801 held_move_event_
.reset();
805 const int kMouseButtonFlagMask
= ui::EF_LEFT_MOUSE_BUTTON
|
806 ui::EF_MIDDLE_MOUSE_BUTTON
|
807 ui::EF_RIGHT_MOUSE_BUTTON
;
808 switch (event
->type()) {
809 case ui::ET_MOUSE_EXITED
:
810 if (!target
|| target
== window()) {
811 DispatchDetails details
=
812 DispatchMouseEnterOrExit(*event
, ui::ET_MOUSE_EXITED
);
813 if (details
.dispatcher_destroyed
) {
817 mouse_moved_handler_
= NULL
;
820 case ui::ET_MOUSE_MOVED
:
821 // Send an exit to the current |mouse_moved_handler_| and an enter to
822 // |target|. Take care that both us and |target| aren't destroyed during
824 if (target
!= mouse_moved_handler_
) {
825 aura::Window
* old_mouse_moved_handler
= mouse_moved_handler_
;
826 WindowTracker live_window
;
827 live_window
.Add(target
);
828 DispatchDetails details
=
829 DispatchMouseEnterOrExit(*event
, ui::ET_MOUSE_EXITED
);
830 if (details
.dispatcher_destroyed
) {
834 // If the |mouse_moved_handler_| changes out from under us, assume a
835 // nested message loop ran and we don't need to do anything.
836 if (mouse_moved_handler_
!= old_mouse_moved_handler
) {
840 if (!live_window
.Contains(target
) || details
.target_destroyed
) {
841 mouse_moved_handler_
= NULL
;
845 live_window
.Remove(target
);
847 mouse_moved_handler_
= target
;
848 details
= DispatchMouseEnterOrExit(*event
, ui::ET_MOUSE_ENTERED
);
849 if (details
.dispatcher_destroyed
|| details
.target_destroyed
) {
855 case ui::ET_MOUSE_PRESSED
:
856 // Don't set the mouse pressed handler for non client mouse down events.
857 // These are only sent by Windows and are not always followed with non
858 // client mouse up events which causes subsequent mouse events to be
859 // sent to the wrong target.
860 if (!(event
->flags() & ui::EF_IS_NON_CLIENT
) && !mouse_pressed_handler_
)
861 mouse_pressed_handler_
= target
;
862 Env::GetInstance()->set_mouse_button_flags(
863 event
->flags() & kMouseButtonFlagMask
);
865 case ui::ET_MOUSE_RELEASED
:
866 mouse_pressed_handler_
= NULL
;
867 Env::GetInstance()->set_mouse_button_flags(event
->flags() &
868 kMouseButtonFlagMask
& ~event
->changed_button_flags());
874 PreDispatchLocatedEvent(target
, event
);
877 void RootWindow::PreDispatchTouchEvent(Window
* target
,
878 ui::TouchEvent
* event
) {
879 switch (event
->type()) {
880 case ui::ET_TOUCH_PRESSED
:
881 touch_ids_down_
|= (1 << event
->touch_id());
882 Env::GetInstance()->set_touch_down(touch_ids_down_
!= 0);
885 // Handle ET_TOUCH_CANCELLED only if it has a native event.
886 case ui::ET_TOUCH_CANCELLED
:
887 if (!event
->HasNativeEvent())
890 case ui::ET_TOUCH_RELEASED
:
891 touch_ids_down_
= (touch_ids_down_
| (1 << event
->touch_id())) ^
892 (1 << event
->touch_id());
893 Env::GetInstance()->set_touch_down(touch_ids_down_
!= 0);
896 case ui::ET_TOUCH_MOVED
:
897 if (move_hold_count_
&& !dispatching_held_event_
) {
898 held_move_event_
.reset(new ui::TouchEvent(*event
, target
, window()));
908 PreDispatchLocatedEvent(target
, event
);