• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/root_window_transformer.h"
22 #include "ui/aura/window.h"
23 #include "ui/aura/window_delegate.h"
24 #include "ui/aura/window_targeter.h"
25 #include "ui/aura/window_tracker.h"
26 #include "ui/aura/window_tree_host.h"
27 #include "ui/base/hit_test.h"
28 #include "ui/base/view_prop.h"
29 #include "ui/compositor/dip_util.h"
30 #include "ui/compositor/layer.h"
31 #include "ui/compositor/layer_animator.h"
32 #include "ui/events/event.h"
33 #include "ui/events/gestures/gesture_recognizer.h"
34 #include "ui/events/gestures/gesture_types.h"
35 #include "ui/gfx/display.h"
36 #include "ui/gfx/point3_f.h"
37 #include "ui/gfx/point_conversions.h"
38 #include "ui/gfx/screen.h"
39 #include "ui/gfx/size_conversions.h"
40 
41 using std::vector;
42 
43 typedef ui::EventDispatchDetails DispatchDetails;
44 
45 namespace aura {
46 
47 namespace {
48 
49 const char kRootWindowForAcceleratedWidget[] =
50     "__AURA_ROOT_WINDOW_ACCELERATED_WIDGET__";
51 
52 // Returns true if |target| has a non-client (frame) component at |location|,
53 // in window coordinates.
IsNonClientLocation(Window * target,const gfx::Point & location)54 bool IsNonClientLocation(Window* target, const gfx::Point& location) {
55   if (!target->delegate())
56     return false;
57   int hit_test_code = target->delegate()->GetNonClientComponent(location);
58   return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE;
59 }
60 
GetDeviceScaleFactorFromDisplay(Window * window)61 float GetDeviceScaleFactorFromDisplay(Window* window) {
62   gfx::Display display = gfx::Screen::GetScreenFor(window)->
63       GetDisplayNearestWindow(window);
64   DCHECK(display.is_valid());
65   return display.device_scale_factor();
66 }
67 
ConsumerToWindow(ui::GestureConsumer * consumer)68 Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
69   return consumer ? static_cast<Window*>(consumer) : NULL;
70 }
71 
SetLastMouseLocation(const Window * root_window,const gfx::Point & location_in_root)72 void SetLastMouseLocation(const Window* root_window,
73                           const gfx::Point& location_in_root) {
74   client::ScreenPositionClient* client =
75       client::GetScreenPositionClient(root_window);
76   if (client) {
77     gfx::Point location_in_screen = location_in_root;
78     client->ConvertPointToScreen(root_window, &location_in_screen);
79     Env::GetInstance()->set_last_mouse_location(location_in_screen);
80   } else {
81     Env::GetInstance()->set_last_mouse_location(location_in_root);
82   }
83 }
84 
CreateHost(RootWindow * root_window,const RootWindow::CreateParams & params)85 RootWindowHost* CreateHost(RootWindow* root_window,
86                            const RootWindow::CreateParams& params) {
87   RootWindowHost* host = params.host ?
88       params.host : RootWindowHost::Create(params.initial_bounds);
89   host->set_delegate(root_window);
90   return host;
91 }
92 
IsUsingEventProcessorForDispatch(const ui::Event & event)93 bool IsUsingEventProcessorForDispatch(const ui::Event& event) {
94   return event.IsKeyEvent() ||
95          event.IsScrollEvent();
96 }
97 
98 class SimpleRootWindowTransformer : public RootWindowTransformer {
99  public:
SimpleRootWindowTransformer(const Window * root_window,const gfx::Transform & transform)100   SimpleRootWindowTransformer(const Window* root_window,
101                               const gfx::Transform& transform)
102       : root_window_(root_window),
103         transform_(transform) {
104   }
105 
106   // RootWindowTransformer overrides:
GetTransform() const107   virtual gfx::Transform GetTransform() const OVERRIDE {
108     return transform_;
109   }
110 
GetInverseTransform() const111   virtual gfx::Transform GetInverseTransform() const OVERRIDE {
112     gfx::Transform invert;
113     if (!transform_.GetInverse(&invert))
114       return transform_;
115     return invert;
116   }
117 
GetRootWindowBounds(const gfx::Size & host_size) const118   virtual gfx::Rect GetRootWindowBounds(
119       const gfx::Size& host_size) const OVERRIDE {
120     gfx::Rect bounds(host_size);
121     gfx::RectF new_bounds(ui::ConvertRectToDIP(root_window_->layer(), bounds));
122     transform_.TransformRect(&new_bounds);
123     return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
124   }
125 
GetHostInsets() const126   virtual gfx::Insets GetHostInsets() const OVERRIDE {
127     return gfx::Insets();
128   }
129 
130  private:
~SimpleRootWindowTransformer()131   virtual ~SimpleRootWindowTransformer() {}
132 
133   const Window* root_window_;
134   const gfx::Transform transform_;
135 
136   DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
137 };
138 
139 }  // namespace
140 
CreateParams(const gfx::Rect & a_initial_bounds)141 RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds)
142     : initial_bounds(a_initial_bounds),
143       host(NULL) {
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 // RootWindow, public:
148 
RootWindow(const CreateParams & params)149 RootWindow::RootWindow(const CreateParams& params)
150     : window_(new Window(NULL)),
151       host_(CreateHost(this, params)),
152       touch_ids_down_(0),
153       last_cursor_(ui::kCursorNull),
154       mouse_pressed_handler_(NULL),
155       mouse_moved_handler_(NULL),
156       event_dispatch_target_(NULL),
157       old_dispatch_target_(NULL),
158       synthesize_mouse_move_(false),
159       move_hold_count_(0),
160       dispatching_held_event_(false),
161       repost_event_factory_(this),
162       held_event_factory_(this) {
163   window()->set_dispatcher(this);
164   window()->SetName("RootWindow");
165   window()->set_event_targeter(
166       scoped_ptr<ui::EventTargeter>(new WindowTargeter()));
167 
168   compositor_.reset(new ui::Compositor(host_->GetAcceleratedWidget()));
169   DCHECK(compositor_.get());
170 
171   prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(),
172                                kRootWindowForAcceleratedWidget,
173                                this));
174   ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
175 }
176 
~RootWindow()177 RootWindow::~RootWindow() {
178   TRACE_EVENT0("shutdown", "RootWindow::Destructor");
179 
180   ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
181 
182   // Make sure to destroy the compositor before terminating so that state is
183   // cleared and we don't hit asserts.
184   compositor_.reset();
185 
186   // An observer may have been added by an animation on the RootWindow.
187   window()->layer()->GetAnimator()->RemoveObserver(this);
188 
189   // Destroy child windows while we're still valid. This is also done by
190   // ~Window, but by that time any calls to virtual methods overriden here (such
191   // as GetRootWindow()) result in Window's implementation. By destroying here
192   // we ensure GetRootWindow() still returns this.
193   window()->RemoveOrDestroyChildren();
194 
195   // Destroying/removing child windows may try to access |host_| (eg.
196   // GetAcceleratedWidget())
197   host_.reset(NULL);
198 
199   window()->set_dispatcher(NULL);
200 }
201 
202 // static
GetForAcceleratedWidget(gfx::AcceleratedWidget widget)203 RootWindow* RootWindow::GetForAcceleratedWidget(
204     gfx::AcceleratedWidget widget) {
205   return reinterpret_cast<RootWindow*>(
206       ui::ViewProp::GetValue(widget, kRootWindowForAcceleratedWidget));
207 }
208 
Init()209 void RootWindow::Init() {
210   compositor()->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
211                                 host_->GetBounds().size());
212   window()->Init(ui::LAYER_NOT_DRAWN);
213   compositor()->SetRootLayer(window()->layer());
214   transformer_.reset(
215       new SimpleRootWindowTransformer(window(), gfx::Transform()));
216   UpdateRootWindowSize(host_->GetBounds().size());
217   Env::GetInstance()->NotifyRootWindowInitialized(this);
218   window()->Show();
219 }
220 
PrepareForShutdown()221 void RootWindow::PrepareForShutdown() {
222   host_->PrepareForShutdown();
223   // discard synthesize event request as well.
224   synthesize_mouse_move_ = false;
225 }
226 
RepostEvent(const ui::LocatedEvent & event)227 void RootWindow::RepostEvent(const ui::LocatedEvent& event) {
228   DCHECK(event.type() == ui::ET_MOUSE_PRESSED ||
229          event.type() == ui::ET_GESTURE_TAP_DOWN);
230   // We allow for only one outstanding repostable event. This is used
231   // in exiting context menus.  A dropped repost request is allowed.
232   if (event.type() == ui::ET_MOUSE_PRESSED) {
233     held_repostable_event_.reset(
234         new ui::MouseEvent(
235             static_cast<const ui::MouseEvent&>(event),
236             static_cast<aura::Window*>(event.target()),
237             window()));
238     base::MessageLoop::current()->PostNonNestableTask(
239         FROM_HERE,
240         base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents),
241                    repost_event_factory_.GetWeakPtr()));
242   } else {
243     DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN);
244     held_repostable_event_.reset();
245     // TODO(rbyers): Reposing of gestures is tricky to get
246     // right, so it's not yet supported.  crbug.com/170987.
247   }
248 }
249 
AsRootWindowHostDelegate()250 RootWindowHostDelegate* RootWindow::AsRootWindowHostDelegate() {
251   return this;
252 }
253 
SetHostSize(const gfx::Size & size_in_pixel)254 void RootWindow::SetHostSize(const gfx::Size& size_in_pixel) {
255   DispatchDetails details = DispatchHeldEvents();
256   if (details.dispatcher_destroyed)
257     return;
258   gfx::Rect bounds = host_->GetBounds();
259   bounds.set_size(size_in_pixel);
260   host_->SetBounds(bounds);
261 
262   // Requery the location to constrain it within the new root window size.
263   gfx::Point point;
264   if (host_->QueryMouseLocation(&point)) {
265     SetLastMouseLocation(window(),
266                          ui::ConvertPointToDIP(window()->layer(), point));
267   }
268 
269   synthesize_mouse_move_ = false;
270 }
271 
SetHostBounds(const gfx::Rect & bounds_in_pixel)272 void RootWindow::SetHostBounds(const gfx::Rect& bounds_in_pixel) {
273   DCHECK(!bounds_in_pixel.IsEmpty());
274   DispatchDetails details = DispatchHeldEvents();
275   if (details.dispatcher_destroyed)
276     return;
277   host_->SetBounds(bounds_in_pixel);
278   synthesize_mouse_move_ = false;
279 }
280 
SetCursor(gfx::NativeCursor cursor)281 void RootWindow::SetCursor(gfx::NativeCursor cursor) {
282   last_cursor_ = cursor;
283   // A lot of code seems to depend on NULL cursors actually showing an arrow,
284   // so just pass everything along to the host.
285   host_->SetCursor(cursor);
286 }
287 
OnCursorVisibilityChanged(bool show)288 void RootWindow::OnCursorVisibilityChanged(bool show) {
289   // Clear any existing mouse hover effects when the cursor becomes invisible.
290   // Note we do not need to dispatch a mouse enter when the cursor becomes
291   // visible because that can only happen in response to a mouse event, which
292   // will trigger its own mouse enter.
293   if (!show)
294     DispatchMouseExitAtPoint(GetLastMouseLocationInRoot());
295 
296   host_->OnCursorVisibilityChanged(show);
297 }
298 
OnMouseEventsEnableStateChanged(bool enabled)299 void RootWindow::OnMouseEventsEnableStateChanged(bool enabled) {
300   // Send entered / exited so that visual state can be updated to match
301   // mouse events state.
302   PostMouseMoveEventAfterWindowChange();
303   // TODO(mazda): Add code to disable mouse events when |enabled| == false.
304 }
305 
MoveCursorTo(const gfx::Point & location_in_dip)306 void RootWindow::MoveCursorTo(const gfx::Point& location_in_dip) {
307   gfx::Point host_location(location_in_dip);
308   ConvertPointToHost(&host_location);
309   MoveCursorToInternal(location_in_dip, host_location);
310 }
311 
MoveCursorToHostLocation(const gfx::Point & host_location)312 void RootWindow::MoveCursorToHostLocation(const gfx::Point& host_location) {
313   gfx::Point root_location(host_location);
314   ConvertPointFromHost(&root_location);
315   MoveCursorToInternal(root_location, host_location);
316 }
317 
ScheduleRedrawRect(const gfx::Rect & damage_rect)318 void RootWindow::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
319   compositor_->ScheduleRedrawRect(damage_rect);
320 }
321 
GetGestureTarget(ui::GestureEvent * event)322 Window* RootWindow::GetGestureTarget(ui::GestureEvent* event) {
323   Window* target = NULL;
324   if (!event->IsEndingEvent()) {
325     // The window that received the start event (e.g. scroll begin) needs to
326     // receive the end event (e.g. scroll end).
327     target = client::GetCaptureWindow(window());
328   }
329   if (!target) {
330     target = ConsumerToWindow(
331         ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
332   }
333 
334   return target;
335 }
336 
DispatchGestureEvent(ui::GestureEvent * event)337 void RootWindow::DispatchGestureEvent(ui::GestureEvent* event) {
338   DispatchDetails details = DispatchHeldEvents();
339   if (details.dispatcher_destroyed)
340     return;
341 
342   Window* target = GetGestureTarget(event);
343   if (target) {
344     event->ConvertLocationToTarget(window(), target);
345     DispatchDetails details = DispatchEvent(target, event);
346     if (details.dispatcher_destroyed)
347       return;
348   }
349 }
350 
OnWindowDestroying(Window * window)351 void RootWindow::OnWindowDestroying(Window* window) {
352   DispatchMouseExitToHidingWindow(window);
353   OnWindowHidden(window, WINDOW_DESTROYED);
354 
355   if (window->IsVisible() &&
356       window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
357     PostMouseMoveEventAfterWindowChange();
358   }
359 }
360 
OnWindowBoundsChanged(Window * window,bool contained_mouse_point)361 void RootWindow::OnWindowBoundsChanged(Window* window,
362                                        bool contained_mouse_point) {
363   if (contained_mouse_point ||
364       (window->IsVisible() &&
365        window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
366     PostMouseMoveEventAfterWindowChange();
367   }
368 }
369 
DispatchMouseExitToHidingWindow(Window * window)370 void RootWindow::DispatchMouseExitToHidingWindow(Window* window) {
371   // The mouse capture is intentionally ignored. Think that a mouse enters
372   // to a window, the window sets the capture, the mouse exits the window,
373   // and then it releases the capture. In that case OnMouseExited won't
374   // be called. So it is natural not to emit OnMouseExited even though
375   // |window| is the capture window.
376   gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
377   if (window->Contains(mouse_moved_handler_) &&
378       window->ContainsPointInRoot(last_mouse_location))
379     DispatchMouseExitAtPoint(last_mouse_location);
380 }
381 
DispatchMouseExitAtPoint(const gfx::Point & point)382 void RootWindow::DispatchMouseExitAtPoint(const gfx::Point& point) {
383   ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE);
384   DispatchDetails details =
385       DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
386   if (details.dispatcher_destroyed)
387     return;
388 }
389 
OnWindowVisibilityChanged(Window * window,bool is_visible)390 void RootWindow::OnWindowVisibilityChanged(Window* window, bool is_visible) {
391   if (!is_visible)
392     OnWindowHidden(window, WINDOW_HIDDEN);
393 
394   if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
395     PostMouseMoveEventAfterWindowChange();
396 }
397 
OnWindowTransformed(Window * window,bool contained_mouse)398 void RootWindow::OnWindowTransformed(Window* window, bool contained_mouse) {
399   if (contained_mouse ||
400       (window->IsVisible() &&
401        window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
402     PostMouseMoveEventAfterWindowChange();
403   }
404 }
405 
OnKeyboardMappingChanged()406 void RootWindow::OnKeyboardMappingChanged() {
407   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
408                     OnKeyboardMappingChanged(this));
409 }
410 
OnRootWindowHostCloseRequested()411 void RootWindow::OnRootWindowHostCloseRequested() {
412   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
413                     OnRootWindowHostCloseRequested(this));
414 }
415 
AddRootWindowObserver(RootWindowObserver * observer)416 void RootWindow::AddRootWindowObserver(RootWindowObserver* observer) {
417   observers_.AddObserver(observer);
418 }
419 
RemoveRootWindowObserver(RootWindowObserver * observer)420 void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) {
421   observers_.RemoveObserver(observer);
422 }
423 
ConvertPointToHost(gfx::Point * point) const424 void RootWindow::ConvertPointToHost(gfx::Point* point) const {
425   gfx::Point3F point_3f(*point);
426   GetRootTransform().TransformPoint(&point_3f);
427   *point = gfx::ToFlooredPoint(point_3f.AsPointF());
428 }
429 
ConvertPointFromHost(gfx::Point * point) const430 void RootWindow::ConvertPointFromHost(gfx::Point* point) const {
431   gfx::Point3F point_3f(*point);
432   GetInverseRootTransform().TransformPoint(&point_3f);
433   *point = gfx::ToFlooredPoint(point_3f.AsPointF());
434 }
435 
ProcessedTouchEvent(ui::TouchEvent * event,Window * window,ui::EventResult result)436 void RootWindow::ProcessedTouchEvent(ui::TouchEvent* event,
437                                      Window* window,
438                                      ui::EventResult result) {
439   scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
440   gestures.reset(ui::GestureRecognizer::Get()->
441       ProcessTouchEventForGesture(*event, result, window));
442   DispatchDetails details = ProcessGestures(gestures.get());
443   if (details.dispatcher_destroyed)
444     return;
445 }
446 
HoldPointerMoves()447 void RootWindow::HoldPointerMoves() {
448   if (!move_hold_count_)
449     held_event_factory_.InvalidateWeakPtrs();
450   ++move_hold_count_;
451   TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::HoldPointerMoves", this);
452 }
453 
ReleasePointerMoves()454 void RootWindow::ReleasePointerMoves() {
455   --move_hold_count_;
456   DCHECK_GE(move_hold_count_, 0);
457   if (!move_hold_count_ && held_move_event_) {
458     // We don't want to call DispatchHeldEvents directly, because this might be
459     // called from a deep stack while another event, in which case dispatching
460     // another one may not be safe/expected.  Instead we post a task, that we
461     // may cancel if HoldPointerMoves is called again before it executes.
462     base::MessageLoop::current()->PostNonNestableTask(
463         FROM_HERE,
464         base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents),
465                    held_event_factory_.GetWeakPtr()));
466   }
467   TRACE_EVENT_ASYNC_END0("ui", "RootWindow::HoldPointerMoves", this);
468 }
469 
GetLastMouseLocationInRoot() const470 gfx::Point RootWindow::GetLastMouseLocationInRoot() const {
471   gfx::Point location = Env::GetInstance()->last_mouse_location();
472   client::ScreenPositionClient* client =
473       client::GetScreenPositionClient(window());
474   if (client)
475     client->ConvertPointFromScreen(window(), &location);
476   return location;
477 }
478 
SetRootWindowTransformer(scoped_ptr<RootWindowTransformer> transformer)479 void RootWindow::SetRootWindowTransformer(
480     scoped_ptr<RootWindowTransformer> transformer) {
481   transformer_ = transformer.Pass();
482   host_->SetInsets(transformer_->GetHostInsets());
483   window()->SetTransform(transformer_->GetTransform());
484   // If the layer is not animating, then we need to update the root window
485   // size immediately.
486   if (!window()->layer()->GetAnimator()->is_animating())
487     UpdateRootWindowSize(host_->GetBounds().size());
488 }
489 
GetRootTransform() const490 gfx::Transform RootWindow::GetRootTransform() const {
491   float scale = ui::GetDeviceScaleFactor(window()->layer());
492   gfx::Transform transform;
493   transform.Scale(scale, scale);
494   transform *= transformer_->GetTransform();
495   return transform;
496 }
497 
SetTransform(const gfx::Transform & transform)498 void RootWindow::SetTransform(const gfx::Transform& transform) {
499   scoped_ptr<RootWindowTransformer> transformer(
500       new SimpleRootWindowTransformer(window(), transform));
501   SetRootWindowTransformer(transformer.Pass());
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 // RootWindow, private:
506 
TransformEventForDeviceScaleFactor(ui::LocatedEvent * event)507 void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent* event) {
508   event->UpdateForRootTransform(GetInverseRootTransform());
509 }
510 
MoveCursorToInternal(const gfx::Point & root_location,const gfx::Point & host_location)511 void RootWindow::MoveCursorToInternal(const gfx::Point& root_location,
512                                       const gfx::Point& host_location) {
513   host_->MoveCursorTo(host_location);
514   SetLastMouseLocation(window(), root_location);
515   client::CursorClient* cursor_client = client::GetCursorClient(window());
516   if (cursor_client) {
517     const gfx::Display& display =
518         gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
519     cursor_client->SetDisplay(display);
520   }
521   synthesize_mouse_move_ = false;
522 }
523 
DispatchMouseEnterOrExit(const ui::MouseEvent & event,ui::EventType type)524 ui::EventDispatchDetails RootWindow::DispatchMouseEnterOrExit(
525     const ui::MouseEvent& event,
526     ui::EventType type) {
527   if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate())
528     return DispatchDetails();
529 
530   ui::MouseEvent translated_event(event,
531                                   window(),
532                                   mouse_moved_handler_,
533                                   type,
534                                   event.flags() | ui::EF_IS_SYNTHESIZED);
535   return DispatchEvent(mouse_moved_handler_, &translated_event);
536 }
537 
ProcessGestures(ui::GestureRecognizer::Gestures * gestures)538 ui::EventDispatchDetails RootWindow::ProcessGestures(
539     ui::GestureRecognizer::Gestures* gestures) {
540   DispatchDetails details;
541   if (!gestures || gestures->empty())
542     return details;
543 
544   Window* target = GetGestureTarget(gestures->get().at(0));
545   for (size_t i = 0; i < gestures->size(); ++i) {
546     ui::GestureEvent* event = gestures->get().at(i);
547     event->ConvertLocationToTarget(window(), target);
548     details = DispatchEvent(target, event);
549     if (details.dispatcher_destroyed || details.target_destroyed)
550       break;
551   }
552   return details;
553 }
554 
OnWindowAddedToRootWindow(Window * attached)555 void RootWindow::OnWindowAddedToRootWindow(Window* attached) {
556   if (attached->IsVisible() &&
557       attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
558     PostMouseMoveEventAfterWindowChange();
559   }
560 }
561 
OnWindowRemovedFromRootWindow(Window * detached,Window * new_root)562 void RootWindow::OnWindowRemovedFromRootWindow(Window* detached,
563                                                Window* new_root) {
564   DCHECK(aura::client::GetCaptureWindow(window()) != window());
565 
566   DispatchMouseExitToHidingWindow(detached);
567   OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
568 
569   if (detached->IsVisible() &&
570       detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
571     PostMouseMoveEventAfterWindowChange();
572   }
573 }
574 
OnWindowHidden(Window * invisible,WindowHiddenReason reason)575 void RootWindow::OnWindowHidden(Window* invisible, WindowHiddenReason reason) {
576   // Do not clear the capture, and the |event_dispatch_target_| if the
577   // window is moving across root windows, because the target itself
578   // is actually still visible and clearing them stops further event
579   // processing, which can cause unexpected behaviors. See
580   // crbug.com/157583
581   if (reason != WINDOW_MOVING) {
582     Window* capture_window = aura::client::GetCaptureWindow(window());
583     // If the ancestor of the capture window is hidden,
584     // release the capture.
585     if (invisible->Contains(capture_window) && invisible != window())
586       capture_window->ReleaseCapture();
587 
588     if (invisible->Contains(event_dispatch_target_))
589       event_dispatch_target_ = NULL;
590 
591     if (invisible->Contains(old_dispatch_target_))
592       old_dispatch_target_ = NULL;
593   }
594 
595   // If the ancestor of any event handler windows are invisible, release the
596   // pointer to those windows.
597   if (invisible->Contains(mouse_pressed_handler_))
598     mouse_pressed_handler_ = NULL;
599   if (invisible->Contains(mouse_moved_handler_))
600     mouse_moved_handler_ = NULL;
601 
602   CleanupGestureState(invisible);
603 }
604 
CleanupGestureState(Window * window)605 void RootWindow::CleanupGestureState(Window* window) {
606   ui::GestureRecognizer::Get()->CancelActiveTouches(window);
607   ui::GestureRecognizer::Get()->CleanupStateForConsumer(window);
608   const Window::Windows& windows = window->children();
609   for (Window::Windows::const_iterator iter = windows.begin();
610       iter != windows.end();
611       ++iter) {
612     CleanupGestureState(*iter);
613   }
614 }
615 
UpdateRootWindowSize(const gfx::Size & host_size)616 void RootWindow::UpdateRootWindowSize(const gfx::Size& host_size) {
617   window()->SetBounds(transformer_->GetRootWindowBounds(host_size));
618 }
619 
620 ////////////////////////////////////////////////////////////////////////////////
621 // RootWindow, aura::client::CaptureDelegate implementation:
622 
UpdateCapture(Window * old_capture,Window * new_capture)623 void RootWindow::UpdateCapture(Window* old_capture,
624                                Window* new_capture) {
625   // |mouse_moved_handler_| may have been set to a Window in a different root
626   // (see below). Clear it here to ensure we don't end up referencing a stale
627   // Window.
628   if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_))
629     mouse_moved_handler_ = NULL;
630 
631   if (old_capture && old_capture->GetRootWindow() == window() &&
632       old_capture->delegate()) {
633     // Send a capture changed event with bogus location data.
634     ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(),
635                          gfx::Point(), 0);
636 
637     DispatchDetails details = DispatchEvent(old_capture, &event);
638     if (details.dispatcher_destroyed)
639       return;
640 
641     old_capture->delegate()->OnCaptureLost();
642   }
643 
644   if (new_capture) {
645     // Make all subsequent mouse events go to the capture window. We shouldn't
646     // need to send an event here as OnCaptureLost() should take care of that.
647     if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown())
648       mouse_moved_handler_ = new_capture;
649   } else {
650     // Make sure mouse_moved_handler gets updated.
651     DispatchDetails details = SynthesizeMouseMoveEvent();
652     if (details.dispatcher_destroyed)
653       return;
654   }
655   mouse_pressed_handler_ = NULL;
656 }
657 
OnOtherRootGotCapture()658 void RootWindow::OnOtherRootGotCapture() {
659   mouse_moved_handler_ = NULL;
660   mouse_pressed_handler_ = NULL;
661 }
662 
SetNativeCapture()663 void RootWindow::SetNativeCapture() {
664   host_->SetCapture();
665 }
666 
ReleaseNativeCapture()667 void RootWindow::ReleaseNativeCapture() {
668   host_->ReleaseCapture();
669 }
670 
671 ////////////////////////////////////////////////////////////////////////////////
672 // RootWindow, ui::EventProcessor implementation:
GetRootTarget()673 ui::EventTarget* RootWindow::GetRootTarget() {
674   return window();
675 }
676 
PrepareEventForDispatch(ui::Event * event)677 void RootWindow::PrepareEventForDispatch(ui::Event* event) {
678   if (event->IsMouseEvent() ||
679       event->IsScrollEvent() ||
680       event->IsTouchEvent() ||
681       event->IsGestureEvent()) {
682     TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event));
683   }
684 }
685 
686 ////////////////////////////////////////////////////////////////////////////////
687 // RootWindow, ui::EventDispatcherDelegate implementation:
688 
CanDispatchToTarget(ui::EventTarget * target)689 bool RootWindow::CanDispatchToTarget(ui::EventTarget* target) {
690   return event_dispatch_target_ == target;
691 }
692 
PreDispatchEvent(ui::EventTarget * target,ui::Event * event)693 ui::EventDispatchDetails RootWindow::PreDispatchEvent(ui::EventTarget* target,
694                                                       ui::Event* event) {
695   if (!dispatching_held_event_ && IsUsingEventProcessorForDispatch(*event)) {
696     DispatchDetails details = DispatchHeldEvents();
697     if (details.dispatcher_destroyed || details.target_destroyed)
698       return details;
699 
700     Window* target_window = static_cast<Window*>(target);
701     if (event->IsScrollEvent()) {
702       PreDispatchLocatedEvent(target_window,
703                               static_cast<ui::ScrollEvent*>(event));
704     }
705   }
706   old_dispatch_target_ = event_dispatch_target_;
707   event_dispatch_target_ = static_cast<Window*>(target);
708   return DispatchDetails();
709 }
710 
PostDispatchEvent(ui::EventTarget * target,const ui::Event & event)711 ui::EventDispatchDetails RootWindow::PostDispatchEvent(ui::EventTarget* target,
712                                                        const ui::Event& event) {
713   DispatchDetails details;
714   if (target != event_dispatch_target_)
715     details.target_destroyed = true;
716   event_dispatch_target_ = old_dispatch_target_;
717   old_dispatch_target_ = NULL;
718 #ifndef NDEBUG
719   DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_));
720 #endif
721   return details;
722 }
723 
724 ////////////////////////////////////////////////////////////////////////////////
725 // RootWindow, ui::GestureEventHelper implementation:
726 
CanDispatchToConsumer(ui::GestureConsumer * consumer)727 bool RootWindow::CanDispatchToConsumer(ui::GestureConsumer* consumer) {
728   Window* consumer_window = ConsumerToWindow(consumer);;
729   return (consumer_window && consumer_window->GetRootWindow() == window());
730 }
731 
DispatchPostponedGestureEvent(ui::GestureEvent * event)732 void RootWindow::DispatchPostponedGestureEvent(ui::GestureEvent* event) {
733   DispatchGestureEvent(event);
734 }
735 
DispatchCancelTouchEvent(ui::TouchEvent * event)736 void RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) {
737   OnHostTouchEvent(event);
738 }
739 
740 ////////////////////////////////////////////////////////////////////////////////
741 // RootWindow, ui::LayerAnimationObserver implementation:
742 
OnLayerAnimationEnded(ui::LayerAnimationSequence * animation)743 void RootWindow::OnLayerAnimationEnded(
744     ui::LayerAnimationSequence* animation) {
745   UpdateRootWindowSize(host_->GetBounds().size());
746 }
747 
OnLayerAnimationScheduled(ui::LayerAnimationSequence * animation)748 void RootWindow::OnLayerAnimationScheduled(
749     ui::LayerAnimationSequence* animation) {
750 }
751 
OnLayerAnimationAborted(ui::LayerAnimationSequence * animation)752 void RootWindow::OnLayerAnimationAborted(
753     ui::LayerAnimationSequence* animation) {
754 }
755 
756 ////////////////////////////////////////////////////////////////////////////////
757 // RootWindow, RootWindowHostDelegate implementation:
758 
OnHostKeyEvent(ui::KeyEvent * event)759 bool RootWindow::OnHostKeyEvent(ui::KeyEvent* event) {
760   DispatchDetails details = OnEventFromSource(event);
761   if (details.dispatcher_destroyed)
762     event->SetHandled();
763   return event->handled();
764 }
765 
OnHostMouseEvent(ui::MouseEvent * event)766 bool RootWindow::OnHostMouseEvent(ui::MouseEvent* event) {
767   DispatchDetails details = OnHostMouseEventImpl(event);
768   return event->handled() || details.dispatcher_destroyed;
769 }
770 
OnHostScrollEvent(ui::ScrollEvent * event)771 bool RootWindow::OnHostScrollEvent(ui::ScrollEvent* event) {
772   DispatchDetails details = OnEventFromSource(event);
773   if (details.dispatcher_destroyed)
774     event->SetHandled();
775   return event->handled();
776 }
777 
OnHostTouchEvent(ui::TouchEvent * event)778 bool RootWindow::OnHostTouchEvent(ui::TouchEvent* event) {
779   if ((event->type() == ui::ET_TOUCH_MOVED)) {
780     if (move_hold_count_) {
781       Window* null_window = static_cast<Window*>(NULL);
782       held_move_event_.reset(
783           new ui::TouchEvent(*event, null_window, null_window));
784       return true;
785     } else {
786       // We may have a held event for a period between the time move_hold_count_
787       // fell to 0 and the DispatchHeldEvents executes. Since we're going to
788       // dispatch the new event directly below, we can reset the old one.
789       held_move_event_.reset();
790     }
791   }
792   DispatchDetails details = DispatchHeldEvents();
793   if (details.dispatcher_destroyed)
794     return false;
795   details = DispatchTouchEventImpl(event);
796   if (details.dispatcher_destroyed)
797     return true;
798   return event->handled();
799 }
800 
OnHostCancelMode()801 void RootWindow::OnHostCancelMode() {
802   ui::CancelModeEvent event;
803   Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow();
804   DispatchDetails details =
805       DispatchEvent(focused_window ? focused_window : window(), &event);
806   if (details.dispatcher_destroyed)
807     return;
808 }
809 
OnHostActivated()810 void RootWindow::OnHostActivated() {
811   Env::GetInstance()->RootWindowActivated(this);
812 }
813 
OnHostLostWindowCapture()814 void RootWindow::OnHostLostWindowCapture() {
815   Window* capture_window = client::GetCaptureWindow(window());
816   if (capture_window && capture_window->GetRootWindow() == window())
817     capture_window->ReleaseCapture();
818 }
819 
OnHostLostMouseGrab()820 void RootWindow::OnHostLostMouseGrab() {
821   mouse_pressed_handler_ = NULL;
822   mouse_moved_handler_ = NULL;
823 }
824 
OnHostPaint(const gfx::Rect & damage_rect)825 void RootWindow::OnHostPaint(const gfx::Rect& damage_rect) {
826   compositor_->ScheduleRedrawRect(damage_rect);
827 }
828 
OnHostMoved(const gfx::Point & origin)829 void RootWindow::OnHostMoved(const gfx::Point& origin) {
830   TRACE_EVENT1("ui", "RootWindow::OnHostMoved",
831                "origin", origin.ToString());
832 
833   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
834                     OnRootWindowHostMoved(this, origin));
835 }
836 
OnHostResized(const gfx::Size & size)837 void RootWindow::OnHostResized(const gfx::Size& size) {
838   TRACE_EVENT1("ui", "RootWindow::OnHostResized",
839                "size", size.ToString());
840 
841   DispatchDetails details = DispatchHeldEvents();
842   if (details.dispatcher_destroyed)
843     return;
844   // The compositor should have the same size as the native root window host.
845   // Get the latest scale from display because it might have been changed.
846   compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), size);
847 
848   // The layer, and the observers should be notified of the
849   // transformed size of the root window.
850   UpdateRootWindowSize(host_->GetBounds().size());
851   FOR_EACH_OBSERVER(RootWindowObserver, observers_,
852                     OnRootWindowHostResized(this));
853 }
854 
GetDeviceScaleFactor()855 float RootWindow::GetDeviceScaleFactor() {
856   return compositor()->device_scale_factor();
857 }
858 
AsRootWindow()859 RootWindow* RootWindow::AsRootWindow() {
860   return this;
861 }
862 
AsRootWindow() const863 const RootWindow* RootWindow::AsRootWindow() const {
864   return this;
865 }
866 
GetEventProcessor()867 ui::EventProcessor* RootWindow::GetEventProcessor() {
868   return this;
869 }
870 
871 ////////////////////////////////////////////////////////////////////////////////
872 // RootWindow, private:
873 
OnHostMouseEventImpl(ui::MouseEvent * event)874 ui::EventDispatchDetails RootWindow::OnHostMouseEventImpl(
875     ui::MouseEvent* event) {
876   if (event->type() == ui::ET_MOUSE_DRAGGED ||
877       (event->flags() & ui::EF_IS_SYNTHESIZED)) {
878     if (move_hold_count_) {
879       Window* null_window = static_cast<Window*>(NULL);
880       held_move_event_.reset(
881           new ui::MouseEvent(*event, null_window, null_window));
882       event->SetHandled();
883       return DispatchDetails();
884     } else {
885       // We may have a held event for a period between the time move_hold_count_
886       // fell to 0 and the DispatchHeldEvents executes. Since we're going to
887       // dispatch the new event directly below, we can reset the old one.
888       held_move_event_.reset();
889     }
890   }
891   DispatchDetails details = DispatchHeldEvents();
892   if (details.dispatcher_destroyed)
893     return details;
894   return DispatchMouseEventImpl(event);
895 }
896 
DispatchMouseEventImpl(ui::MouseEvent * event)897 ui::EventDispatchDetails RootWindow::DispatchMouseEventImpl(
898     ui::MouseEvent* event) {
899   TransformEventForDeviceScaleFactor(event);
900   Window* target = mouse_pressed_handler_ ?
901       mouse_pressed_handler_ : client::GetCaptureWindow(window());
902   if (!target)
903     target = window()->GetEventHandlerForPoint(event->location());
904   return DispatchMouseEventToTarget(event, target);
905 }
906 
DispatchMouseEventRepost(ui::MouseEvent * event)907 ui::EventDispatchDetails RootWindow::DispatchMouseEventRepost(
908     ui::MouseEvent* event) {
909   if (event->type() != ui::ET_MOUSE_PRESSED)
910     return DispatchDetails();
911   Window* target = client::GetCaptureWindow(window());
912   WindowEventDispatcher* dispatcher = this;
913   if (!target) {
914     target = window()->GetEventHandlerForPoint(event->location());
915   } else {
916     dispatcher = target->GetDispatcher();
917     CHECK(dispatcher);  // Capture window better be in valid root.
918   }
919   dispatcher->mouse_pressed_handler_ = NULL;
920   return dispatcher->DispatchMouseEventToTarget(event, target);
921 }
922 
DispatchMouseEventToTarget(ui::MouseEvent * event,Window * target)923 ui::EventDispatchDetails RootWindow::DispatchMouseEventToTarget(
924     ui::MouseEvent* event,
925     Window* target) {
926   client::CursorClient* cursor_client = client::GetCursorClient(window());
927   if (cursor_client &&
928       !cursor_client->IsMouseEventsEnabled() &&
929       (event->flags() & ui::EF_IS_SYNTHESIZED))
930     return DispatchDetails();
931 
932   static const int kMouseButtonFlagMask =
933       ui::EF_LEFT_MOUSE_BUTTON |
934       ui::EF_MIDDLE_MOUSE_BUTTON |
935       ui::EF_RIGHT_MOUSE_BUTTON;
936   // WARNING: because of nested message loops |this| may be deleted after
937   // dispatching any event. Do not use AutoReset or the like here.
938   SetLastMouseLocation(window(), event->location());
939   synthesize_mouse_move_ = false;
940   switch (event->type()) {
941     case ui::ET_MOUSE_EXITED:
942       if (!target) {
943         DispatchDetails details =
944             DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
945         if (details.dispatcher_destroyed)
946           return details;
947         mouse_moved_handler_ = NULL;
948       }
949       break;
950     case ui::ET_MOUSE_MOVED:
951       // Send an exit to the current |mouse_moved_handler_| and an enter to
952       // |target|. Take care that both us and |target| aren't destroyed during
953       // dispatch.
954       if (target != mouse_moved_handler_) {
955         aura::Window* old_mouse_moved_handler = mouse_moved_handler_;
956         WindowTracker destroyed_tracker;
957         if (target)
958           destroyed_tracker.Add(target);
959         DispatchDetails details =
960             DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
961         if (details.dispatcher_destroyed)
962           return details;
963         // If the |mouse_moved_handler_| changes out from under us, assume a
964         // nested message loop ran and we don't need to do anything.
965         if (mouse_moved_handler_ != old_mouse_moved_handler)
966           return DispatchDetails();
967         if (destroyed_tracker.Contains(target)) {
968           destroyed_tracker.Remove(target);
969           mouse_moved_handler_ = target;
970           DispatchDetails details =
971               DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED);
972           if (details.dispatcher_destroyed)
973             return details;
974         } else {
975           mouse_moved_handler_ = NULL;
976           return DispatchDetails();
977         }
978       }
979       break;
980     case ui::ET_MOUSE_PRESSED:
981       // Don't set the mouse pressed handler for non client mouse down events.
982       // These are only sent by Windows and are not always followed with non
983       // client mouse up events which causes subsequent mouse events to be
984       // sent to the wrong target.
985       if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
986         mouse_pressed_handler_ = target;
987       Env::GetInstance()->set_mouse_button_flags(
988           event->flags() & kMouseButtonFlagMask);
989       break;
990     case ui::ET_MOUSE_RELEASED:
991       mouse_pressed_handler_ = NULL;
992       Env::GetInstance()->set_mouse_button_flags(event->flags() &
993           kMouseButtonFlagMask & ~event->changed_button_flags());
994       break;
995     default:
996       break;
997   }
998   if (target) {
999     event->ConvertLocationToTarget(window(), target);
1000     if (IsNonClientLocation(target, event->location()))
1001       event->set_flags(event->flags() | ui::EF_IS_NON_CLIENT);
1002     return DispatchEvent(target, event);
1003   }
1004   return DispatchDetails();
1005 }
1006 
DispatchTouchEventImpl(ui::TouchEvent * event)1007 ui::EventDispatchDetails RootWindow::DispatchTouchEventImpl(
1008     ui::TouchEvent* event) {
1009   switch (event->type()) {
1010     case ui::ET_TOUCH_PRESSED:
1011       touch_ids_down_ |= (1 << event->touch_id());
1012       Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
1013       break;
1014 
1015       // Handle ET_TOUCH_CANCELLED only if it has a native event.
1016     case ui::ET_TOUCH_CANCELLED:
1017       if (!event->HasNativeEvent())
1018         break;
1019       // fallthrough
1020     case ui::ET_TOUCH_RELEASED:
1021       touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^
1022             (1 << event->touch_id());
1023       Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
1024       break;
1025 
1026     default:
1027       break;
1028   }
1029   TransformEventForDeviceScaleFactor(event);
1030   Window* target = client::GetCaptureWindow(window());
1031   if (!target) {
1032     target = ConsumerToWindow(
1033         ui::GestureRecognizer::Get()->GetTouchLockedTarget(*event));
1034     if (!target) {
1035       target = ConsumerToWindow(ui::GestureRecognizer::Get()->
1036           GetTargetForLocation(event->location()));
1037     }
1038   }
1039 
1040   // The gesture recognizer processes touch events in the system coordinates. So
1041   // keep a copy of the touch event here before possibly converting the event to
1042   // a window's local coordinate system.
1043   ui::TouchEvent event_for_gr(*event);
1044 
1045   ui::EventResult result = ui::ER_UNHANDLED;
1046   if (!target && !window()->bounds().Contains(event->location())) {
1047     // If the initial touch is outside the root window, target the root.
1048     target = window();
1049     DispatchDetails details = DispatchEvent(target ? target : NULL, event);
1050     if (details.dispatcher_destroyed)
1051       return details;
1052     result = event->result();
1053   } else {
1054     // We only come here when the first contact was within the root window.
1055     if (!target) {
1056       target = window()->GetEventHandlerForPoint(event->location());
1057       if (!target)
1058         return DispatchDetails();
1059     }
1060 
1061     event->ConvertLocationToTarget(window(), target);
1062     DispatchDetails details = DispatchEvent(target, event);
1063     if (details.dispatcher_destroyed)
1064       return details;
1065     result = event->result();
1066   }
1067 
1068   // Get the list of GestureEvents from GestureRecognizer.
1069   scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
1070   gestures.reset(ui::GestureRecognizer::Get()->
1071       ProcessTouchEventForGesture(event_for_gr, result, target));
1072 
1073   return ProcessGestures(gestures.get());
1074 }
1075 
DispatchHeldEvents()1076 ui::EventDispatchDetails RootWindow::DispatchHeldEvents() {
1077   if (!held_repostable_event_ && !held_move_event_)
1078     return DispatchDetails();
1079 
1080   CHECK(!dispatching_held_event_);
1081   dispatching_held_event_ = true;
1082 
1083   DispatchDetails dispatch_details;
1084   if (held_repostable_event_) {
1085     if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) {
1086       scoped_ptr<ui::MouseEvent> mouse_event(
1087           static_cast<ui::MouseEvent*>(held_repostable_event_.release()));
1088       dispatch_details = DispatchMouseEventRepost(mouse_event.get());
1089     } else {
1090       // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
1091       NOTREACHED();
1092     }
1093     if (dispatch_details.dispatcher_destroyed)
1094       return dispatch_details;
1095   }
1096 
1097   if (held_move_event_ && held_move_event_->IsMouseEvent()) {
1098     // If a mouse move has been synthesized, the target location is suspect,
1099     // so drop the held event.
1100     if (!synthesize_mouse_move_) {
1101       dispatch_details = DispatchMouseEventImpl(
1102           static_cast<ui::MouseEvent*>(held_move_event_.get()));
1103     }
1104     if (!dispatch_details.dispatcher_destroyed)
1105       held_move_event_.reset();
1106   } else if (held_move_event_ && held_move_event_->IsTouchEvent()) {
1107     dispatch_details = DispatchTouchEventImpl(
1108         static_cast<ui::TouchEvent*>(held_move_event_.get()));
1109     if (!dispatch_details.dispatcher_destroyed)
1110       held_move_event_.reset();
1111   }
1112 
1113   if (!dispatch_details.dispatcher_destroyed)
1114     dispatching_held_event_ = false;
1115   return dispatch_details;
1116 }
1117 
PostMouseMoveEventAfterWindowChange()1118 void RootWindow::PostMouseMoveEventAfterWindowChange() {
1119   if (synthesize_mouse_move_)
1120     return;
1121   synthesize_mouse_move_ = true;
1122   base::MessageLoop::current()->PostNonNestableTask(
1123       FROM_HERE,
1124       base::Bind(&RootWindow::SynthesizeMouseMoveEventAsync,
1125                  held_event_factory_.GetWeakPtr()));
1126 }
1127 
SynthesizeMouseMoveEvent()1128 ui::EventDispatchDetails RootWindow::SynthesizeMouseMoveEvent() {
1129   DispatchDetails details;
1130   if (!synthesize_mouse_move_)
1131     return details;
1132   synthesize_mouse_move_ = false;
1133   gfx::Point root_mouse_location = GetLastMouseLocationInRoot();
1134   if (!window()->bounds().Contains(root_mouse_location))
1135     return details;
1136   gfx::Point host_mouse_location = root_mouse_location;
1137   ConvertPointToHost(&host_mouse_location);
1138 
1139   ui::MouseEvent event(ui::ET_MOUSE_MOVED,
1140                        host_mouse_location,
1141                        host_mouse_location,
1142                        ui::EF_IS_SYNTHESIZED);
1143   return OnHostMouseEventImpl(&event);
1144 }
1145 
SynthesizeMouseMoveEventAsync()1146 void RootWindow::SynthesizeMouseMoveEventAsync() {
1147   DispatchDetails details = SynthesizeMouseMoveEvent();
1148   if (details.dispatcher_destroyed)
1149     return;
1150 }
1151 
GetInverseRootTransform() const1152 gfx::Transform RootWindow::GetInverseRootTransform() const {
1153   float scale = ui::GetDeviceScaleFactor(window()->layer());
1154   gfx::Transform transform;
1155   transform.Scale(1.0f / scale, 1.0f / scale);
1156   return transformer_->GetInverseTransform() * transform;
1157 }
1158 
PreDispatchLocatedEvent(Window * target,ui::LocatedEvent * event)1159 void RootWindow::PreDispatchLocatedEvent(Window* target,
1160                                          ui::LocatedEvent* event) {
1161   int flags = event->flags();
1162   if (IsNonClientLocation(target, event->location()))
1163     flags |= ui::EF_IS_NON_CLIENT;
1164   event->set_flags(flags);
1165 
1166   if (!dispatching_held_event_) {
1167     SetLastMouseLocation(window(), event->location());
1168     synthesize_mouse_move_ = false;
1169   }
1170 }
1171 
1172 }  // namespace aura
1173