Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / aura / root_window.cc
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.
4
5 #include "ui/aura/root_window.h"
6
7 #include <vector>
8
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"
35
36 using std::vector;
37
38 typedef ui::EventDispatchDetails DispatchDetails;
39
40 namespace aura {
41
42 namespace {
43
44 const char kRootWindowForAcceleratedWidget[] =
45     "__AURA_ROOT_WINDOW_ACCELERATED_WIDGET__";
46
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;
54 }
55
56 Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
57   return consumer ? static_cast<Window*>(consumer) : NULL;
58 }
59
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);
70   }
71 }
72
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;
79 }
80
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;
89 }
90
91 }  // namespace
92
93 RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds)
94     : initial_bounds(a_initial_bounds),
95       host(NULL) {
96 }
97
98 ////////////////////////////////////////////////////////////////////////////////
99 // RootWindow, public:
100
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()));
118
119   prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(),
120                                kRootWindowForAcceleratedWidget,
121                                this));
122   ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
123 }
124
125 RootWindow::~RootWindow() {
126   TRACE_EVENT0("shutdown", "RootWindow::Destructor");
127
128   ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
129
130   // An observer may have been added by an animation on the RootWindow.
131   window()->layer()->GetAnimator()->RemoveObserver(this);
132
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();
138
139   // Destroying/removing child windows may try to access |host_| (eg.
140   // GetAcceleratedWidget())
141   host_.reset(NULL);
142
143   window()->set_dispatcher(NULL);
144 }
145
146 // static
147 RootWindow* RootWindow::GetForAcceleratedWidget(
148     gfx::AcceleratedWidget widget) {
149   return reinterpret_cast<RootWindow*>(
150       ui::ViewProp::GetValue(widget, kRootWindowForAcceleratedWidget));
151 }
152
153 void RootWindow::PrepareForShutdown() {
154   host_->PrepareForShutdown();
155   // discard synthesize event request as well.
156   synthesize_mouse_move_ = false;
157 }
158
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.
179   }
180 }
181
182 WindowTreeHostDelegate* RootWindow::AsWindowTreeHostDelegate() {
183   return this;
184 }
185
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.
191 }
192
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());
199   }
200   if (!target) {
201     target = ConsumerToWindow(
202         ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
203   }
204
205   return target;
206 }
207
208 void RootWindow::DispatchGestureEvent(ui::GestureEvent* event) {
209   DispatchDetails details = DispatchHeldEvents();
210   if (details.dispatcher_destroyed)
211     return;
212
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;
219   }
220 }
221
222 void RootWindow::OnWindowDestroying(Window* window) {
223   DispatchMouseExitToHidingWindow(window);
224   if (window->IsVisible() &&
225       window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
226     PostMouseMoveEventAfterWindowChange();
227   }
228
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);
232 }
233
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();
240   }
241 }
242
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);
253 }
254
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;
262 }
263
264 void RootWindow::OnWindowVisibilityChanged(Window* window, bool is_visible) {
265   if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
266     PostMouseMoveEventAfterWindowChange();
267
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);
272 }
273
274 void RootWindow::OnWindowTransformed(Window* window, bool contained_mouse) {
275   if (contained_mouse ||
276       (window->IsVisible() &&
277        window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
278     PostMouseMoveEventAfterWindowChange();
279   }
280 }
281
282 void RootWindow::OnKeyboardMappingChanged() {
283   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
284                     OnKeyboardMappingChanged(this));
285 }
286
287 void RootWindow::OnWindowTreeHostCloseRequested() {
288   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
289                     OnWindowTreeHostCloseRequested(this));
290 }
291
292 void RootWindow::AddRootWindowObserver(RootWindowObserver* observer) {
293   observers_.AddObserver(observer);
294 }
295
296 void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) {
297   observers_.RemoveObserver(observer);
298 }
299
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;
309 }
310
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);
316 }
317
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()));
330   }
331   TRACE_EVENT_ASYNC_END0("ui", "RootWindow::HoldPointerMoves", this);
332 }
333
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;
341 }
342
343 ////////////////////////////////////////////////////////////////////////////////
344 // RootWindow, private:
345
346 void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent* event) {
347   event->UpdateForRootTransform(host()->GetInverseRootTransform());
348 }
349
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());
356   }
357
358   if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate())
359     return DispatchDetails();
360
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);
375 }
376
377 ui::EventDispatchDetails RootWindow::ProcessGestures(
378     ui::GestureRecognizer::Gestures* gestures) {
379   DispatchDetails details;
380   if (!gestures || gestures->empty())
381     return details;
382
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;
390   }
391   return details;
392 }
393
394 void RootWindow::OnWindowAddedToRootWindow(Window* attached) {
395   if (attached->IsVisible() &&
396       attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
397     PostMouseMoveEventAfterWindowChange();
398   }
399 }
400
401 void RootWindow::OnWindowRemovedFromRootWindow(Window* detached,
402                                                Window* new_root) {
403   DCHECK(aura::client::GetCaptureWindow(window()) != window());
404
405   DispatchMouseExitToHidingWindow(detached);
406   if (detached->IsVisible() &&
407       detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
408     PostMouseMoveEventAfterWindowChange();
409   }
410
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);
414 }
415
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;
423
424   CleanupGestureState(invisible);
425
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());
433
434     if (invisible->Contains(event_dispatch_target_))
435       event_dispatch_target_ = NULL;
436
437     if (invisible->Contains(old_dispatch_target_))
438       old_dispatch_target_ = NULL;
439
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();
445   }
446 }
447
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);
456   }
457 }
458
459 ////////////////////////////////////////////////////////////////////////////////
460 // RootWindow, aura::client::CaptureDelegate implementation:
461
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;
469
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);
475
476     DispatchDetails details = DispatchEvent(old_capture, &event);
477     if (details.dispatcher_destroyed)
478       return;
479
480     old_capture->delegate()->OnCaptureLost();
481   }
482
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;
493   }
494   mouse_pressed_handler_ = NULL;
495 }
496
497 void RootWindow::OnOtherRootGotCapture() {
498   mouse_moved_handler_ = NULL;
499   mouse_pressed_handler_ = NULL;
500 }
501
502 void RootWindow::SetNativeCapture() {
503   host_->SetCapture();
504 }
505
506 void RootWindow::ReleaseNativeCapture() {
507   host_->ReleaseCapture();
508 }
509
510 ////////////////////////////////////////////////////////////////////////////////
511 // RootWindow, ui::EventProcessor implementation:
512 ui::EventTarget* RootWindow::GetRootTarget() {
513   return window();
514 }
515
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;
522   }
523   if (event->IsMouseEvent() ||
524       event->IsScrollEvent() ||
525       event->IsTouchEvent() ||
526       event->IsGestureEvent()) {
527     TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event));
528   }
529 }
530
531 ////////////////////////////////////////////////////////////////////////////////
532 // RootWindow, ui::EventDispatcherDelegate implementation:
533
534 bool RootWindow::CanDispatchToTarget(ui::EventTarget* target) {
535   return event_dispatch_target_ == target;
536 }
537
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;
548     }
549   }
550
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));
559   }
560   old_dispatch_target_ = event_dispatch_target_;
561   event_dispatch_target_ = static_cast<Window*>(target);
562   return DispatchDetails();
563 }
564
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
575
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());
587     }
588   }
589
590   return details;
591 }
592
593 ////////////////////////////////////////////////////////////////////////////////
594 // RootWindow, ui::GestureEventHelper implementation:
595
596 bool RootWindow::CanDispatchToConsumer(ui::GestureConsumer* consumer) {
597   Window* consumer_window = ConsumerToWindow(consumer);;
598   return (consumer_window && consumer_window->GetRootWindow() == window());
599 }
600
601 void RootWindow::DispatchPostponedGestureEvent(ui::GestureEvent* event) {
602   DispatchGestureEvent(event);
603 }
604
605 void RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) {
606   DispatchDetails details = OnEventFromSource(event);
607   if (details.dispatcher_destroyed)
608     return;
609 }
610
611 ////////////////////////////////////////////////////////////////////////////////
612 // RootWindow, ui::LayerAnimationObserver implementation:
613
614 void RootWindow::OnLayerAnimationEnded(
615     ui::LayerAnimationSequence* animation) {
616   host()->UpdateRootWindowSize(host_->GetBounds().size());
617 }
618
619 void RootWindow::OnLayerAnimationScheduled(
620     ui::LayerAnimationSequence* animation) {
621 }
622
623 void RootWindow::OnLayerAnimationAborted(
624     ui::LayerAnimationSequence* animation) {
625 }
626
627 ////////////////////////////////////////////////////////////////////////////////
628 // RootWindow, WindowTreeHostDelegate implementation:
629
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;
637 }
638
639 void RootWindow::OnHostActivated() {
640   Env::GetInstance()->RootWindowActivated(this);
641 }
642
643 void RootWindow::OnHostLostWindowCapture() {
644   Window* capture_window = client::GetCaptureWindow(window());
645   if (capture_window && capture_window->GetRootWindow() == window())
646     capture_window->ReleaseCapture();
647 }
648
649 void RootWindow::OnHostLostMouseGrab() {
650   mouse_pressed_handler_ = NULL;
651   mouse_moved_handler_ = NULL;
652 }
653
654 void RootWindow::OnHostMoved(const gfx::Point& origin) {
655   TRACE_EVENT1("ui", "RootWindow::OnHostMoved",
656                "origin", origin.ToString());
657
658   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
659                     OnWindowTreeHostMoved(this, origin));
660 }
661
662 void RootWindow::OnHostResized(const gfx::Size& size) {
663   TRACE_EVENT1("ui", "RootWindow::OnHostResized",
664                "size", size.ToString());
665
666   DispatchDetails details = DispatchHeldEvents();
667   if (details.dispatcher_destroyed)
668     return;
669   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
670                     OnWindowTreeHostResized(this));
671
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));
677   }
678   synthesize_mouse_move_ = false;
679 }
680
681 void RootWindow::OnCursorMovedToRootLocation(const gfx::Point& root_location) {
682   SetLastMouseLocation(window(), root_location);
683   synthesize_mouse_move_ = false;
684 }
685
686 RootWindow* RootWindow::AsRootWindow() {
687   return this;
688 }
689
690 const RootWindow* RootWindow::AsRootWindow() const {
691   return this;
692 }
693
694 ui::EventProcessor* RootWindow::GetEventProcessor() {
695   return this;
696 }
697
698 ////////////////////////////////////////////////////////////////////////////////
699 // RootWindow, private:
700
701 ui::EventDispatchDetails RootWindow::DispatchHeldEvents() {
702   if (!held_repostable_event_ && !held_move_event_)
703     return DispatchDetails();
704
705   CHECK(!dispatching_held_event_);
706   dispatching_held_event_ = true;
707
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();
717     }
718     if (dispatch_details.dispatcher_destroyed)
719       return dispatch_details;
720   }
721
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());
728     }
729     if (!dispatch_details.dispatcher_destroyed)
730       held_move_event_.reset();
731   }
732
733   if (!dispatch_details.dispatcher_destroyed)
734     dispatching_held_event_ = false;
735   return dispatch_details;
736 }
737
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()));
746 }
747
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,
762                        0);
763   return OnEventFromSource(&event);
764 }
765
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);
772
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;
779   }
780 }
781
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;
790   }
791
792   if (IsEventCandidateForHold(*event) && !dispatching_held_event_) {
793     if (move_hold_count_) {
794       if (!(event->flags() & ui::EF_IS_SYNTHESIZED) &&
795           event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
796         SetLastMouseLocation(window(), event->root_location());
797       }
798       held_move_event_.reset(new ui::MouseEvent(*event, target, window()));
799       event->SetHandled();
800       return;
801     } else {
802       // We may have a held event for a period between the time move_hold_count_
803       // fell to 0 and the DispatchHeldEvents executes. Since we're going to
804       // dispatch the new event directly below, we can reset the old one.
805       held_move_event_.reset();
806     }
807   }
808
809   const int kMouseButtonFlagMask = ui::EF_LEFT_MOUSE_BUTTON |
810                                    ui::EF_MIDDLE_MOUSE_BUTTON |
811                                    ui::EF_RIGHT_MOUSE_BUTTON;
812   switch (event->type()) {
813     case ui::ET_MOUSE_EXITED:
814       if (!target || target == window()) {
815         DispatchDetails details =
816             DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
817         if (details.dispatcher_destroyed) {
818           event->SetHandled();
819           return;
820         }
821         mouse_moved_handler_ = NULL;
822       }
823       break;
824     case ui::ET_MOUSE_MOVED:
825       // Send an exit to the current |mouse_moved_handler_| and an enter to
826       // |target|. Take care that both us and |target| aren't destroyed during
827       // dispatch.
828       if (target != mouse_moved_handler_) {
829         aura::Window* old_mouse_moved_handler = mouse_moved_handler_;
830         WindowTracker live_window;
831         live_window.Add(target);
832         DispatchDetails details =
833             DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
834         if (details.dispatcher_destroyed) {
835           event->SetHandled();
836           return;
837         }
838         // If the |mouse_moved_handler_| changes out from under us, assume a
839         // nested message loop ran and we don't need to do anything.
840         if (mouse_moved_handler_ != old_mouse_moved_handler) {
841           event->SetHandled();
842           return;
843         }
844         if (!live_window.Contains(target) || details.target_destroyed) {
845           mouse_moved_handler_ = NULL;
846           event->SetHandled();
847           return;
848         }
849         live_window.Remove(target);
850
851         mouse_moved_handler_ = target;
852         details = DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED);
853         if (details.dispatcher_destroyed || details.target_destroyed) {
854           event->SetHandled();
855           return;
856         }
857       }
858       break;
859     case ui::ET_MOUSE_PRESSED:
860       // Don't set the mouse pressed handler for non client mouse down events.
861       // These are only sent by Windows and are not always followed with non
862       // client mouse up events which causes subsequent mouse events to be
863       // sent to the wrong target.
864       if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
865         mouse_pressed_handler_ = target;
866       Env::GetInstance()->set_mouse_button_flags(
867           event->flags() & kMouseButtonFlagMask);
868       break;
869     case ui::ET_MOUSE_RELEASED:
870       mouse_pressed_handler_ = NULL;
871       Env::GetInstance()->set_mouse_button_flags(event->flags() &
872           kMouseButtonFlagMask & ~event->changed_button_flags());
873       break;
874     default:
875       break;
876   }
877
878   PreDispatchLocatedEvent(target, event);
879 }
880
881 void RootWindow::PreDispatchTouchEvent(Window* target,
882                                        ui::TouchEvent* event) {
883   switch (event->type()) {
884     case ui::ET_TOUCH_PRESSED:
885       touch_ids_down_ |= (1 << event->touch_id());
886       Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
887       break;
888
889       // Handle ET_TOUCH_CANCELLED only if it has a native event.
890     case ui::ET_TOUCH_CANCELLED:
891       if (!event->HasNativeEvent())
892         break;
893       // fallthrough
894     case ui::ET_TOUCH_RELEASED:
895       touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^
896             (1 << event->touch_id());
897       Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
898       break;
899
900     case ui::ET_TOUCH_MOVED:
901       if (move_hold_count_ && !dispatching_held_event_) {
902         held_move_event_.reset(new ui::TouchEvent(*event, target, window()));
903         event->SetHandled();
904         return;
905       }
906       break;
907
908     default:
909       NOTREACHED();
910       break;
911   }
912   PreDispatchLocatedEvent(target, event);
913 }
914
915 }  // namespace aura