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