NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / ui / aura / root_window.cc
blob04ced914c62ad451637a4728e17e2ef8a20a384d
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"
7 #include <vector>
9 #include "base/bind.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"
36 using std::vector;
38 typedef ui::EventDispatchDetails DispatchDetails;
40 namespace aura {
42 namespace {
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())
51 return false;
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);
64 if (client) {
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);
68 } else {
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);
78 return host;
81 bool IsEventCandidateForHold(const ui::Event& event) {
82 if (event.type() == ui::ET_TOUCH_MOVED)
83 return true;
84 if (event.type() == ui::ET_MOUSE_DRAGGED)
85 return true;
86 if (event.IsMouseEvent() && (event.flags() & ui::EF_IS_SYNTHESIZED))
87 return true;
88 return false;
91 } // namespace
93 RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds)
94 : initial_bounds(a_initial_bounds),
95 host(NULL) {
98 ////////////////////////////////////////////////////////////////////////////////
99 // RootWindow, public:
101 RootWindow::RootWindow(const CreateParams& params)
102 : window_(new Window(NULL)),
103 host_(CreateHost(this, params)),
104 touch_ids_down_(0),
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),
110 move_hold_count_(0),
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,
121 this));
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())
141 host_.reset(NULL);
143 window()->set_dispatcher(NULL);
146 // static
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(
166 new ui::MouseEvent(
167 static_cast<const ui::MouseEvent&>(event),
168 static_cast<aura::Window*>(event.target()),
169 window()));
170 base::MessageLoop::current()->PostNonNestableTask(
171 FROM_HERE,
172 base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents),
173 repost_event_factory_.GetWeakPtr()));
174 } else {
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() {
183 return this;
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());
200 if (!target) {
201 target = ConsumerToWindow(
202 ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
205 return target;
208 void RootWindow::DispatchGestureEvent(ui::GestureEvent* event) {
209 DispatchDetails details = DispatchHeldEvents();
210 if (details.dispatcher_destroyed)
211 return;
213 Window* target = GetGestureTarget(event);
214 if (target) {
215 event->ConvertLocationToTarget(window(), target);
216 DispatchDetails details = DispatchEvent(target, event);
217 if (details.dispatcher_destroyed)
218 return;
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,
257 ui::EF_NONE);
258 DispatchDetails details =
259 DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
260 if (details.dispatcher_destroyed)
261 return;
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.
270 if (!is_visible)
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,
301 Window* window,
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)
308 return;
311 void RootWindow::HoldPointerMoves() {
312 if (!move_hold_count_)
313 held_event_factory_.InvalidateWeakPtrs();
314 ++move_hold_count_;
315 TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::HoldPointerMoves", this);
318 void RootWindow::ReleasePointerMoves() {
319 --move_hold_count_;
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(
327 FROM_HERE,
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());
338 if (client)
339 client->ConvertPointFromScreen(window(), &location);
340 return 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());
367 if (!target)
368 target = window();
369 ui::MouseEvent translated_event(event,
370 target,
371 mouse_moved_handler_,
372 type,
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())
381 return details;
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)
389 break;
391 return details;
394 void RootWindow::OnWindowAddedToRootWindow(Window* attached) {
395 if (attached->IsVisible() &&
396 attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
397 PostMouseMoveEventAfterWindowChange();
401 void RootWindow::OnWindowRemovedFromRootWindow(Window* detached,
402 Window* new_root) {
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
430 // crbug.com/157583
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
442 // after this.
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();
454 ++iter) {
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
466 // Window.
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(),
474 gfx::Point(), 0, 0);
476 DispatchDetails details = DispatchEvent(old_capture, &event);
477 if (details.dispatcher_destroyed)
478 return;
480 old_capture->delegate()->OnCaptureLost();
483 if (new_capture) {
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;
488 } else {
489 // Make sure mouse_moved_handler gets updated.
490 DispatchDetails details = SynthesizeMouseMoveEvent();
491 if (details.dispatcher_destroyed)
492 return;
494 mouse_pressed_handler_ = NULL;
497 void RootWindow::OnOtherRootGotCapture() {
498 mouse_moved_handler_ = NULL;
499 mouse_pressed_handler_ = NULL;
502 void RootWindow::SetNativeCapture() {
503 host_->SetCapture();
506 void RootWindow::ReleaseNativeCapture() {
507 host_->ReleaseCapture();
510 ////////////////////////////////////////////////////////////////////////////////
511 // RootWindow, ui::EventProcessor implementation:
512 ui::EventTarget* RootWindow::GetRootTarget() {
513 return window();
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.
521 return;
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,
539 ui::Event* event) {
540 if (!dispatching_held_event_) {
541 bool can_be_held = IsEventCandidateForHold(*event);
542 if (!move_hold_count_ || !can_be_held) {
543 if (can_be_held)
544 held_move_event_.reset();
545 DispatchDetails details = DispatchHeldEvents();
546 if (details.dispatcher_destroyed || details.target_destroyed)
547 return details;
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;
572 #ifndef NDEBUG
573 DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_));
574 #endif
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());
590 return details;
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)
608 return;
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)
636 return;
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)
668 return;
669 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
670 OnWindowTreeHostResized(this));
672 // Constrain the mouse position within the new root Window size.
673 gfx::Point point;
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() {
687 return this;
690 const RootWindow* RootWindow::AsRootWindow() const {
691 return this;
694 ui::EventProcessor* RootWindow::GetEventProcessor() {
695 return this;
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());
714 } else {
715 // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
716 NOTREACHED();
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_)
740 return;
741 synthesize_mouse_move_ = true;
742 base::MessageLoop::current()->PostNonNestableTask(
743 FROM_HERE,
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_)
751 return details;
752 synthesize_mouse_move_ = false;
753 gfx::Point root_mouse_location = GetLastMouseLocationInRoot();
754 if (!window()->bounds().Contains(root_mouse_location))
755 return details;
756 gfx::Point host_mouse_location = root_mouse_location;
757 host()->ConvertPointToHost(&host_mouse_location);
758 ui::MouseEvent event(ui::ET_MOUSE_MOVED,
759 host_mouse_location,
760 host_mouse_location,
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());
785 if (cursor_client &&
786 !cursor_client->IsMouseEventsEnabled() &&
787 (event->flags() & ui::EF_IS_SYNTHESIZED)) {
788 event->SetHandled();
789 return;
792 if (IsEventCandidateForHold(*event) && !dispatching_held_event_) {
793 if (move_hold_count_) {
794 held_move_event_.reset(new ui::MouseEvent(*event, target, window()));
795 event->SetHandled();
796 return;
797 } else {
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) {
814 event->SetHandled();
815 return;
817 mouse_moved_handler_ = NULL;
819 break;
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
823 // dispatch.
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) {
831 event->SetHandled();
832 return;
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) {
837 event->SetHandled();
838 return;
840 if (!live_window.Contains(target) || details.target_destroyed) {
841 mouse_moved_handler_ = NULL;
842 event->SetHandled();
843 return;
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) {
850 event->SetHandled();
851 return;
854 break;
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);
864 break;
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());
869 break;
870 default:
871 break;
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);
883 break;
885 // Handle ET_TOUCH_CANCELLED only if it has a native event.
886 case ui::ET_TOUCH_CANCELLED:
887 if (!event->HasNativeEvent())
888 break;
889 // fallthrough
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);
894 break;
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()));
899 event->SetHandled();
900 return;
902 break;
904 default:
905 NOTREACHED();
906 break;
908 PreDispatchLocatedEvent(target, event);
911 } // namespace aura