Get foreground tab on Android
[chromium-blink-merge.git] / ui / aura / root_window.cc
blobc2c1ab58fb75bfd0c573e7924ea0ddaf955b3ecf
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/aura/root_window.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/client/cursor_client.h"
16 #include "ui/aura/client/event_client.h"
17 #include "ui/aura/client/focus_client.h"
18 #include "ui/aura/client/screen_position_client.h"
19 #include "ui/aura/env.h"
20 #include "ui/aura/root_window_observer.h"
21 #include "ui/aura/root_window_transformer.h"
22 #include "ui/aura/window.h"
23 #include "ui/aura/window_delegate.h"
24 #include "ui/aura/window_tracker.h"
25 #include "ui/aura/window_tree_host.h"
26 #include "ui/base/hit_test.h"
27 #include "ui/base/view_prop.h"
28 #include "ui/compositor/dip_util.h"
29 #include "ui/compositor/layer.h"
30 #include "ui/compositor/layer_animator.h"
31 #include "ui/events/event.h"
32 #include "ui/events/gestures/gesture_recognizer.h"
33 #include "ui/events/gestures/gesture_types.h"
34 #include "ui/gfx/display.h"
35 #include "ui/gfx/point3_f.h"
36 #include "ui/gfx/point_conversions.h"
37 #include "ui/gfx/screen.h"
38 #include "ui/gfx/size_conversions.h"
40 using std::vector;
42 typedef ui::EventDispatchDetails DispatchDetails;
44 namespace aura {
46 namespace {
48 const char kRootWindowForAcceleratedWidget[] =
49 "__AURA_ROOT_WINDOW_ACCELERATED_WIDGET__";
51 // Returns true if |target| has a non-client (frame) component at |location|,
52 // in window coordinates.
53 bool IsNonClientLocation(Window* target, const gfx::Point& location) {
54 if (!target->delegate())
55 return false;
56 int hit_test_code = target->delegate()->GetNonClientComponent(location);
57 return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE;
60 float GetDeviceScaleFactorFromDisplay(Window* window) {
61 gfx::Display display = gfx::Screen::GetScreenFor(window)->
62 GetDisplayNearestWindow(window);
63 DCHECK(display.is_valid());
64 return display.device_scale_factor();
67 Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
68 return consumer ? static_cast<Window*>(consumer) : NULL;
71 void SetLastMouseLocation(const Window* root_window,
72 const gfx::Point& location_in_root) {
73 client::ScreenPositionClient* client =
74 client::GetScreenPositionClient(root_window);
75 if (client) {
76 gfx::Point location_in_screen = location_in_root;
77 client->ConvertPointToScreen(root_window, &location_in_screen);
78 Env::GetInstance()->set_last_mouse_location(location_in_screen);
79 } else {
80 Env::GetInstance()->set_last_mouse_location(location_in_root);
84 RootWindowHost* CreateHost(RootWindow* root_window,
85 const RootWindow::CreateParams& params) {
86 RootWindowHost* host = params.host ?
87 params.host : RootWindowHost::Create(params.initial_bounds);
88 host->set_delegate(root_window);
89 return host;
92 class SimpleRootWindowTransformer : public RootWindowTransformer {
93 public:
94 SimpleRootWindowTransformer(const Window* root_window,
95 const gfx::Transform& transform)
96 : root_window_(root_window),
97 transform_(transform) {
100 // RootWindowTransformer overrides:
101 virtual gfx::Transform GetTransform() const OVERRIDE {
102 return transform_;
105 virtual gfx::Transform GetInverseTransform() const OVERRIDE {
106 gfx::Transform invert;
107 if (!transform_.GetInverse(&invert))
108 return transform_;
109 return invert;
112 virtual gfx::Rect GetRootWindowBounds(
113 const gfx::Size& host_size) const OVERRIDE {
114 gfx::Rect bounds(host_size);
115 gfx::RectF new_bounds(ui::ConvertRectToDIP(root_window_->layer(), bounds));
116 transform_.TransformRect(&new_bounds);
117 return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
120 virtual gfx::Insets GetHostInsets() const OVERRIDE {
121 return gfx::Insets();
124 private:
125 virtual ~SimpleRootWindowTransformer() {}
127 const Window* root_window_;
128 const gfx::Transform transform_;
130 DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
133 } // namespace
135 RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds)
136 : initial_bounds(a_initial_bounds),
137 host(NULL) {
140 ////////////////////////////////////////////////////////////////////////////////
141 // RootWindow, public:
143 RootWindow::RootWindow(const CreateParams& params)
144 : window_(new Window(NULL)),
145 host_(CreateHost(this, params)),
146 touch_ids_down_(0),
147 last_cursor_(ui::kCursorNull),
148 mouse_pressed_handler_(NULL),
149 mouse_moved_handler_(NULL),
150 event_dispatch_target_(NULL),
151 synthesize_mouse_move_(false),
152 move_hold_count_(0),
153 repost_event_factory_(this),
154 held_event_factory_(this) {
155 window()->set_dispatcher(this);
156 window()->SetName("RootWindow");
158 compositor_.reset(new ui::Compositor(host_->GetAcceleratedWidget()));
159 DCHECK(compositor_.get());
161 prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(),
162 kRootWindowForAcceleratedWidget,
163 this));
164 ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
167 RootWindow::~RootWindow() {
168 TRACE_EVENT0("shutdown", "RootWindow::Destructor");
170 ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
172 // Make sure to destroy the compositor before terminating so that state is
173 // cleared and we don't hit asserts.
174 compositor_.reset();
176 // An observer may have been added by an animation on the RootWindow.
177 window()->layer()->GetAnimator()->RemoveObserver(this);
179 // Destroy child windows while we're still valid. This is also done by
180 // ~Window, but by that time any calls to virtual methods overriden here (such
181 // as GetRootWindow()) result in Window's implementation. By destroying here
182 // we ensure GetRootWindow() still returns this.
183 window()->RemoveOrDestroyChildren();
185 // Destroying/removing child windows may try to access |host_| (eg.
186 // GetAcceleratedWidget())
187 host_.reset(NULL);
189 window()->set_dispatcher(NULL);
192 // static
193 RootWindow* RootWindow::GetForAcceleratedWidget(
194 gfx::AcceleratedWidget widget) {
195 return reinterpret_cast<RootWindow*>(
196 ui::ViewProp::GetValue(widget, kRootWindowForAcceleratedWidget));
199 void RootWindow::Init() {
200 compositor()->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
201 host_->GetBounds().size());
202 window()->Init(ui::LAYER_NOT_DRAWN);
203 compositor()->SetRootLayer(window()->layer());
204 transformer_.reset(
205 new SimpleRootWindowTransformer(window(), gfx::Transform()));
206 UpdateRootWindowSize(host_->GetBounds().size());
207 Env::GetInstance()->NotifyRootWindowInitialized(this);
208 window()->Show();
211 void RootWindow::PrepareForShutdown() {
212 host_->PrepareForShutdown();
213 // discard synthesize event request as well.
214 synthesize_mouse_move_ = false;
217 void RootWindow::RepostEvent(const ui::LocatedEvent& event) {
218 DCHECK(event.type() == ui::ET_MOUSE_PRESSED ||
219 event.type() == ui::ET_GESTURE_TAP_DOWN);
220 // We allow for only one outstanding repostable event. This is used
221 // in exiting context menus. A dropped repost request is allowed.
222 if (event.type() == ui::ET_MOUSE_PRESSED) {
223 held_repostable_event_.reset(
224 new ui::MouseEvent(
225 static_cast<const ui::MouseEvent&>(event),
226 static_cast<aura::Window*>(event.target()),
227 window()));
228 base::MessageLoop::current()->PostTask(
229 FROM_HERE,
230 base::Bind(&RootWindow::DispatchHeldEventsAsync,
231 repost_event_factory_.GetWeakPtr()));
232 } else {
233 DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN);
234 held_repostable_event_.reset();
235 // TODO(rbyers): Reposing of gestures is tricky to get
236 // right, so it's not yet supported. crbug.com/170987.
240 RootWindowHostDelegate* RootWindow::AsRootWindowHostDelegate() {
241 return this;
244 void RootWindow::SetHostSize(const gfx::Size& size_in_pixel) {
245 DispatchDetails details = DispatchHeldEvents();
246 if (details.dispatcher_destroyed)
247 return;
248 gfx::Rect bounds = host_->GetBounds();
249 bounds.set_size(size_in_pixel);
250 host_->SetBounds(bounds);
252 // Requery the location to constrain it within the new root window size.
253 gfx::Point point;
254 if (host_->QueryMouseLocation(&point)) {
255 SetLastMouseLocation(window(),
256 ui::ConvertPointToDIP(window()->layer(), point));
259 synthesize_mouse_move_ = false;
262 void RootWindow::SetHostBounds(const gfx::Rect& bounds_in_pixel) {
263 DCHECK(!bounds_in_pixel.IsEmpty());
264 DispatchDetails details = DispatchHeldEvents();
265 if (details.dispatcher_destroyed)
266 return;
267 host_->SetBounds(bounds_in_pixel);
268 synthesize_mouse_move_ = false;
271 void RootWindow::SetCursor(gfx::NativeCursor cursor) {
272 last_cursor_ = cursor;
273 // A lot of code seems to depend on NULL cursors actually showing an arrow,
274 // so just pass everything along to the host.
275 host_->SetCursor(cursor);
278 void RootWindow::OnCursorVisibilityChanged(bool show) {
279 // Clear any existing mouse hover effects when the cursor becomes invisible.
280 // Note we do not need to dispatch a mouse enter when the cursor becomes
281 // visible because that can only happen in response to a mouse event, which
282 // will trigger its own mouse enter.
283 if (!show)
284 DispatchMouseExitAtPoint(GetLastMouseLocationInRoot());
286 host_->OnCursorVisibilityChanged(show);
289 void RootWindow::OnMouseEventsEnableStateChanged(bool enabled) {
290 // Send entered / exited so that visual state can be updated to match
291 // mouse events state.
292 PostMouseMoveEventAfterWindowChange();
293 // TODO(mazda): Add code to disable mouse events when |enabled| == false.
296 void RootWindow::MoveCursorTo(const gfx::Point& location_in_dip) {
297 gfx::Point host_location(location_in_dip);
298 ConvertPointToHost(&host_location);
299 MoveCursorToInternal(location_in_dip, host_location);
302 void RootWindow::MoveCursorToHostLocation(const gfx::Point& host_location) {
303 gfx::Point root_location(host_location);
304 ConvertPointFromHost(&root_location);
305 MoveCursorToInternal(root_location, host_location);
308 void RootWindow::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
309 compositor_->ScheduleRedrawRect(damage_rect);
312 Window* RootWindow::GetGestureTarget(ui::GestureEvent* event) {
313 Window* target = client::GetCaptureWindow(window());
314 if (!target) {
315 target = ConsumerToWindow(
316 ui::GestureRecognizer::Get()->GetTargetForGestureEvent(event));
319 return target;
322 void RootWindow::DispatchGestureEvent(ui::GestureEvent* event) {
323 DispatchDetails details = DispatchHeldEvents();
324 if (details.dispatcher_destroyed)
325 return;
327 Window* target = GetGestureTarget(event);
328 if (target) {
329 event->ConvertLocationToTarget(window(), target);
330 DispatchDetails details = ProcessEvent(target, event);
331 if (details.dispatcher_destroyed)
332 return;
336 void RootWindow::OnWindowDestroying(Window* window) {
337 DispatchMouseExitToHidingWindow(window);
338 OnWindowHidden(window, WINDOW_DESTROYED);
340 if (window->IsVisible() &&
341 window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
342 PostMouseMoveEventAfterWindowChange();
346 void RootWindow::OnWindowBoundsChanged(Window* window,
347 bool contained_mouse_point) {
348 if (contained_mouse_point ||
349 (window->IsVisible() &&
350 window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
351 PostMouseMoveEventAfterWindowChange();
355 void RootWindow::DispatchMouseExitToHidingWindow(Window* window) {
356 // The mouse capture is intentionally ignored. Think that a mouse enters
357 // to a window, the window sets the capture, the mouse exits the window,
358 // and then it releases the capture. In that case OnMouseExited won't
359 // be called. So it is natural not to emit OnMouseExited even though
360 // |window| is the capture window.
361 gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
362 if (window->Contains(mouse_moved_handler_) &&
363 window->ContainsPointInRoot(last_mouse_location))
364 DispatchMouseExitAtPoint(last_mouse_location);
367 void RootWindow::DispatchMouseExitAtPoint(const gfx::Point& point) {
368 ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE);
369 DispatchDetails details =
370 DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
371 if (details.dispatcher_destroyed)
372 return;
375 void RootWindow::OnWindowVisibilityChanged(Window* window, bool is_visible) {
376 if (!is_visible)
377 OnWindowHidden(window, WINDOW_HIDDEN);
379 if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
380 PostMouseMoveEventAfterWindowChange();
383 void RootWindow::OnWindowTransformed(Window* window, bool contained_mouse) {
384 if (contained_mouse ||
385 (window->IsVisible() &&
386 window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
387 PostMouseMoveEventAfterWindowChange();
391 void RootWindow::OnKeyboardMappingChanged() {
392 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
393 OnKeyboardMappingChanged(this));
396 void RootWindow::OnRootWindowHostCloseRequested() {
397 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
398 OnRootWindowHostCloseRequested(this));
401 void RootWindow::AddRootWindowObserver(RootWindowObserver* observer) {
402 observers_.AddObserver(observer);
405 void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) {
406 observers_.RemoveObserver(observer);
409 void RootWindow::ConvertPointToHost(gfx::Point* point) const {
410 gfx::Point3F point_3f(*point);
411 GetRootTransform().TransformPoint(&point_3f);
412 *point = gfx::ToFlooredPoint(point_3f.AsPointF());
415 void RootWindow::ConvertPointFromHost(gfx::Point* point) const {
416 gfx::Point3F point_3f(*point);
417 GetInverseRootTransform().TransformPoint(&point_3f);
418 *point = gfx::ToFlooredPoint(point_3f.AsPointF());
421 void RootWindow::ProcessedTouchEvent(ui::TouchEvent* event,
422 Window* window,
423 ui::EventResult result) {
424 scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
425 gestures.reset(ui::GestureRecognizer::Get()->
426 ProcessTouchEventForGesture(*event, result, window));
427 DispatchDetails details = ProcessGestures(gestures.get());
428 if (details.dispatcher_destroyed)
429 return;
432 void RootWindow::HoldPointerMoves() {
433 if (!move_hold_count_)
434 held_event_factory_.InvalidateWeakPtrs();
435 ++move_hold_count_;
436 TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::HoldPointerMoves", this);
439 void RootWindow::ReleasePointerMoves() {
440 --move_hold_count_;
441 DCHECK_GE(move_hold_count_, 0);
442 if (!move_hold_count_ && held_move_event_) {
443 // We don't want to call DispatchHeldEvents directly, because this might be
444 // called from a deep stack while another event, in which case dispatching
445 // another one may not be safe/expected. Instead we post a task, that we
446 // may cancel if HoldPointerMoves is called again before it executes.
447 base::MessageLoop::current()->PostTask(
448 FROM_HERE,
449 base::Bind(&RootWindow::DispatchHeldEventsAsync,
450 held_event_factory_.GetWeakPtr()));
452 TRACE_EVENT_ASYNC_END0("ui", "RootWindow::HoldPointerMoves", this);
455 gfx::Point RootWindow::GetLastMouseLocationInRoot() const {
456 gfx::Point location = Env::GetInstance()->last_mouse_location();
457 client::ScreenPositionClient* client =
458 client::GetScreenPositionClient(window());
459 if (client)
460 client->ConvertPointFromScreen(window(), &location);
461 return location;
464 void RootWindow::SetRootWindowTransformer(
465 scoped_ptr<RootWindowTransformer> transformer) {
466 transformer_ = transformer.Pass();
467 host_->SetInsets(transformer_->GetHostInsets());
468 window()->SetTransform(transformer_->GetTransform());
469 // If the layer is not animating, then we need to update the root window
470 // size immediately.
471 if (!window()->layer()->GetAnimator()->is_animating())
472 UpdateRootWindowSize(host_->GetBounds().size());
475 gfx::Transform RootWindow::GetRootTransform() const {
476 float scale = ui::GetDeviceScaleFactor(window()->layer());
477 gfx::Transform transform;
478 transform.Scale(scale, scale);
479 transform *= transformer_->GetTransform();
480 return transform;
483 void RootWindow::SetTransform(const gfx::Transform& transform) {
484 scoped_ptr<RootWindowTransformer> transformer(
485 new SimpleRootWindowTransformer(window(), transform));
486 SetRootWindowTransformer(transformer.Pass());
489 ////////////////////////////////////////////////////////////////////////////////
490 // RootWindow, private:
492 void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent* event) {
493 event->UpdateForRootTransform(GetInverseRootTransform());
496 void RootWindow::MoveCursorToInternal(const gfx::Point& root_location,
497 const gfx::Point& host_location) {
498 host_->MoveCursorTo(host_location);
499 SetLastMouseLocation(window(), root_location);
500 client::CursorClient* cursor_client = client::GetCursorClient(window());
501 if (cursor_client) {
502 const gfx::Display& display =
503 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
504 cursor_client->SetDisplay(display);
506 synthesize_mouse_move_ = false;
509 ui::EventDispatchDetails RootWindow::DispatchMouseEnterOrExit(
510 const ui::MouseEvent& event,
511 ui::EventType type) {
512 if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate())
513 return DispatchDetails();
515 ui::MouseEvent translated_event(event,
516 window(),
517 mouse_moved_handler_,
518 type,
519 event.flags() | ui::EF_IS_SYNTHESIZED);
520 return ProcessEvent(mouse_moved_handler_, &translated_event);
523 ui::EventDispatchDetails RootWindow::ProcessEvent(Window* target,
524 ui::Event* event) {
525 Window* old_target = event_dispatch_target_;
526 event_dispatch_target_ = target;
527 DispatchDetails details = DispatchEvent(target, event);
528 if (!details.dispatcher_destroyed) {
529 if (event_dispatch_target_ != target)
530 details.target_destroyed = true;
531 event_dispatch_target_ = old_target;
533 return details;
536 ui::EventDispatchDetails RootWindow::ProcessGestures(
537 ui::GestureRecognizer::Gestures* gestures) {
538 DispatchDetails details;
539 if (!gestures || gestures->empty())
540 return details;
542 Window* target = GetGestureTarget(gestures->get().at(0));
543 for (size_t i = 0; i < gestures->size(); ++i) {
544 ui::GestureEvent* event = gestures->get().at(i);
545 event->ConvertLocationToTarget(window(), target);
546 details = ProcessEvent(target, event);
547 if (details.dispatcher_destroyed || details.target_destroyed)
548 break;
550 return details;
553 void RootWindow::OnWindowAddedToRootWindow(Window* attached) {
554 if (attached->IsVisible() &&
555 attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
556 PostMouseMoveEventAfterWindowChange();
560 void RootWindow::OnWindowRemovedFromRootWindow(Window* detached,
561 Window* new_root) {
562 DCHECK(aura::client::GetCaptureWindow(window()) != window());
564 DispatchMouseExitToHidingWindow(detached);
565 OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
567 if (detached->IsVisible() &&
568 detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
569 PostMouseMoveEventAfterWindowChange();
573 void RootWindow::OnWindowHidden(Window* invisible, WindowHiddenReason reason) {
574 // Do not clear the capture, and the |event_dispatch_target_| if the
575 // window is moving across root windows, because the target itself
576 // is actually still visible and clearing them stops further event
577 // processing, which can cause unexpected behaviors. See
578 // crbug.com/157583
579 if (reason != WINDOW_MOVING) {
580 Window* capture_window = aura::client::GetCaptureWindow(window());
581 // If the ancestor of the capture window is hidden,
582 // release the capture.
583 if (invisible->Contains(capture_window) && invisible != window())
584 capture_window->ReleaseCapture();
586 if (invisible->Contains(event_dispatch_target_))
587 event_dispatch_target_ = NULL;
590 // If the ancestor of any event handler windows are invisible, release the
591 // pointer to those windows.
592 if (invisible->Contains(mouse_pressed_handler_))
593 mouse_pressed_handler_ = NULL;
594 if (invisible->Contains(mouse_moved_handler_))
595 mouse_moved_handler_ = NULL;
597 CleanupGestureRecognizerState(invisible);
600 void RootWindow::CleanupGestureRecognizerState(Window* window) {
601 ui::GestureRecognizer::Get()->CleanupStateForConsumer(window);
602 const Window::Windows& windows = window->children();
603 for (Window::Windows::const_iterator iter = windows.begin();
604 iter != windows.end();
605 ++iter) {
606 CleanupGestureRecognizerState(*iter);
610 void RootWindow::UpdateRootWindowSize(const gfx::Size& host_size) {
611 window()->SetBounds(transformer_->GetRootWindowBounds(host_size));
614 ////////////////////////////////////////////////////////////////////////////////
615 // RootWindow, aura::client::CaptureDelegate implementation:
617 void RootWindow::UpdateCapture(Window* old_capture,
618 Window* new_capture) {
619 // |mouse_moved_handler_| may have been set to a Window in a different root
620 // (see below). Clear it here to ensure we don't end up referencing a stale
621 // Window.
622 if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_))
623 mouse_moved_handler_ = NULL;
625 if (old_capture && old_capture->GetRootWindow() == window() &&
626 old_capture->delegate()) {
627 // Send a capture changed event with bogus location data.
628 ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(),
629 gfx::Point(), 0);
631 DispatchDetails details = ProcessEvent(old_capture, &event);
632 if (details.dispatcher_destroyed)
633 return;
635 old_capture->delegate()->OnCaptureLost();
638 if (new_capture) {
639 // Make all subsequent mouse events go to the capture window. We shouldn't
640 // need to send an event here as OnCaptureLost() should take care of that.
641 if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown())
642 mouse_moved_handler_ = new_capture;
643 } else {
644 // Make sure mouse_moved_handler gets updated.
645 DispatchDetails details = SynthesizeMouseMoveEvent();
646 if (details.dispatcher_destroyed)
647 return;
649 mouse_pressed_handler_ = NULL;
652 void RootWindow::OnOtherRootGotCapture() {
653 mouse_moved_handler_ = NULL;
654 mouse_pressed_handler_ = NULL;
657 void RootWindow::SetNativeCapture() {
658 host_->SetCapture();
661 void RootWindow::ReleaseNativeCapture() {
662 host_->ReleaseCapture();
665 ////////////////////////////////////////////////////////////////////////////////
666 // RootWindow, ui::EventDispatcherDelegate implementation:
668 bool RootWindow::CanDispatchToTarget(ui::EventTarget* target) {
669 return event_dispatch_target_ == target;
672 ////////////////////////////////////////////////////////////////////////////////
673 // RootWindow, ui::GestureEventHelper implementation:
675 bool RootWindow::CanDispatchToConsumer(ui::GestureConsumer* consumer) {
676 Window* consumer_window = ConsumerToWindow(consumer);;
677 return (consumer_window && consumer_window->GetRootWindow() == window());
680 void RootWindow::DispatchPostponedGestureEvent(ui::GestureEvent* event) {
681 DispatchGestureEvent(event);
684 void RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) {
685 OnHostTouchEvent(event);
688 ////////////////////////////////////////////////////////////////////////////////
689 // RootWindow, ui::LayerAnimationObserver implementation:
691 void RootWindow::OnLayerAnimationEnded(
692 ui::LayerAnimationSequence* animation) {
693 UpdateRootWindowSize(host_->GetBounds().size());
696 void RootWindow::OnLayerAnimationScheduled(
697 ui::LayerAnimationSequence* animation) {
700 void RootWindow::OnLayerAnimationAborted(
701 ui::LayerAnimationSequence* animation) {
704 ////////////////////////////////////////////////////////////////////////////////
705 // RootWindow, RootWindowHostDelegate implementation:
707 bool RootWindow::OnHostKeyEvent(ui::KeyEvent* event) {
708 DispatchDetails details = DispatchHeldEvents();
709 if (details.dispatcher_destroyed)
710 return false;
711 if (event->key_code() == ui::VKEY_UNKNOWN)
712 return false;
713 client::EventClient* client = client::GetEventClient(window());
714 Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow();
715 if (client && !client->CanProcessEventsWithinSubtree(focused_window)) {
716 client::GetFocusClient(window())->FocusWindow(NULL);
717 return false;
719 details = ProcessEvent(focused_window ? focused_window : window(), event);
720 if (details.dispatcher_destroyed)
721 return true;
722 return event->handled();
725 bool RootWindow::OnHostMouseEvent(ui::MouseEvent* event) {
726 DispatchDetails details = OnHostMouseEventImpl(event);
727 return event->handled() || details.dispatcher_destroyed;
730 bool RootWindow::OnHostScrollEvent(ui::ScrollEvent* event) {
731 DispatchDetails details = DispatchHeldEvents();
732 if (details.dispatcher_destroyed)
733 return false;
735 TransformEventForDeviceScaleFactor(event);
736 SetLastMouseLocation(window(), event->location());
737 synthesize_mouse_move_ = false;
739 Window* target = mouse_pressed_handler_ ?
740 mouse_pressed_handler_ : client::GetCaptureWindow(window());
742 if (!target)
743 target = window()->GetEventHandlerForPoint(event->location());
745 if (!target)
746 target = window();
748 event->ConvertLocationToTarget(window(), target);
749 int flags = event->flags();
750 if (IsNonClientLocation(target, event->location()))
751 flags |= ui::EF_IS_NON_CLIENT;
752 event->set_flags(flags);
754 details = ProcessEvent(target, event);
755 if (details.dispatcher_destroyed)
756 return true;
757 return event->handled();
760 bool RootWindow::OnHostTouchEvent(ui::TouchEvent* event) {
761 if ((event->type() == ui::ET_TOUCH_MOVED)) {
762 if (move_hold_count_) {
763 Window* null_window = static_cast<Window*>(NULL);
764 held_move_event_.reset(
765 new ui::TouchEvent(*event, null_window, null_window));
766 return true;
767 } else {
768 // We may have a held event for a period between the time move_hold_count_
769 // fell to 0 and the DispatchHeldEvents executes. Since we're going to
770 // dispatch the new event directly below, we can reset the old one.
771 held_move_event_.reset();
774 DispatchDetails details = DispatchHeldEvents();
775 if (details.dispatcher_destroyed)
776 return false;
777 details = DispatchTouchEventImpl(event);
778 if (details.dispatcher_destroyed)
779 return true;
780 return event->handled();
783 void RootWindow::OnHostCancelMode() {
784 ui::CancelModeEvent event;
785 Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow();
786 DispatchDetails details =
787 ProcessEvent(focused_window ? focused_window : window(), &event);
788 if (details.dispatcher_destroyed)
789 return;
792 void RootWindow::OnHostActivated() {
793 Env::GetInstance()->RootWindowActivated(this);
796 void RootWindow::OnHostLostWindowCapture() {
797 Window* capture_window = client::GetCaptureWindow(window());
798 if (capture_window && capture_window->GetRootWindow() == window())
799 capture_window->ReleaseCapture();
802 void RootWindow::OnHostLostMouseGrab() {
803 mouse_pressed_handler_ = NULL;
804 mouse_moved_handler_ = NULL;
807 void RootWindow::OnHostPaint(const gfx::Rect& damage_rect) {
808 compositor_->ScheduleRedrawRect(damage_rect);
811 void RootWindow::OnHostMoved(const gfx::Point& origin) {
812 TRACE_EVENT1("ui", "RootWindow::OnHostMoved",
813 "origin", origin.ToString());
815 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
816 OnRootWindowHostMoved(this, origin));
819 void RootWindow::OnHostResized(const gfx::Size& size) {
820 TRACE_EVENT1("ui", "RootWindow::OnHostResized",
821 "size", size.ToString());
823 DispatchDetails details = DispatchHeldEvents();
824 if (details.dispatcher_destroyed)
825 return;
826 // The compositor should have the same size as the native root window host.
827 // Get the latest scale from display because it might have been changed.
828 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), size);
830 // The layer, and the observers should be notified of the
831 // transformed size of the root window.
832 UpdateRootWindowSize(size);
833 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
834 OnRootWindowHostResized(this));
837 float RootWindow::GetDeviceScaleFactor() {
838 return compositor()->device_scale_factor();
841 RootWindow* RootWindow::AsRootWindow() {
842 return this;
845 const RootWindow* RootWindow::AsRootWindow() const {
846 return this;
849 ////////////////////////////////////////////////////////////////////////////////
850 // RootWindow, private:
852 ui::EventDispatchDetails RootWindow::OnHostMouseEventImpl(
853 ui::MouseEvent* event) {
854 if (event->type() == ui::ET_MOUSE_DRAGGED ||
855 (event->flags() & ui::EF_IS_SYNTHESIZED)) {
856 if (move_hold_count_) {
857 Window* null_window = static_cast<Window*>(NULL);
858 held_move_event_.reset(
859 new ui::MouseEvent(*event, null_window, null_window));
860 event->SetHandled();
861 return DispatchDetails();
862 } else {
863 // We may have a held event for a period between the time move_hold_count_
864 // fell to 0 and the DispatchHeldEvents executes. Since we're going to
865 // dispatch the new event directly below, we can reset the old one.
866 held_move_event_.reset();
869 DispatchDetails details = DispatchHeldEvents();
870 if (details.dispatcher_destroyed)
871 return details;
872 return DispatchMouseEventImpl(event);
875 ui::EventDispatchDetails RootWindow::DispatchMouseEventImpl(
876 ui::MouseEvent* event) {
877 TransformEventForDeviceScaleFactor(event);
878 Window* target = mouse_pressed_handler_ ?
879 mouse_pressed_handler_ : client::GetCaptureWindow(window());
880 if (!target)
881 target = window()->GetEventHandlerForPoint(event->location());
882 return DispatchMouseEventToTarget(event, target);
885 ui::EventDispatchDetails RootWindow::DispatchMouseEventRepost(
886 ui::MouseEvent* event) {
887 if (event->type() != ui::ET_MOUSE_PRESSED)
888 return DispatchDetails();
889 Window* target = client::GetCaptureWindow(window());
890 WindowEventDispatcher* dispatcher = this;
891 if (!target) {
892 target = window()->GetEventHandlerForPoint(event->location());
893 } else {
894 dispatcher = target->GetDispatcher();
895 CHECK(dispatcher); // Capture window better be in valid root.
897 dispatcher->mouse_pressed_handler_ = NULL;
898 return dispatcher->DispatchMouseEventToTarget(event, target);
901 ui::EventDispatchDetails RootWindow::DispatchMouseEventToTarget(
902 ui::MouseEvent* event,
903 Window* target) {
904 client::CursorClient* cursor_client = client::GetCursorClient(window());
905 if (cursor_client &&
906 !cursor_client->IsMouseEventsEnabled() &&
907 (event->flags() & ui::EF_IS_SYNTHESIZED))
908 return DispatchDetails();
910 static const int kMouseButtonFlagMask =
911 ui::EF_LEFT_MOUSE_BUTTON |
912 ui::EF_MIDDLE_MOUSE_BUTTON |
913 ui::EF_RIGHT_MOUSE_BUTTON;
914 // WARNING: because of nested message loops |this| may be deleted after
915 // dispatching any event. Do not use AutoReset or the like here.
916 SetLastMouseLocation(window(), event->location());
917 synthesize_mouse_move_ = false;
918 switch (event->type()) {
919 case ui::ET_MOUSE_EXITED:
920 if (!target) {
921 DispatchDetails details =
922 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
923 if (details.dispatcher_destroyed)
924 return details;
925 mouse_moved_handler_ = NULL;
927 break;
928 case ui::ET_MOUSE_MOVED:
929 // Send an exit to the current |mouse_moved_handler_| and an enter to
930 // |target|. Take care that both us and |target| aren't destroyed during
931 // dispatch.
932 if (target != mouse_moved_handler_) {
933 aura::Window* old_mouse_moved_handler = mouse_moved_handler_;
934 WindowTracker destroyed_tracker;
935 if (target)
936 destroyed_tracker.Add(target);
937 DispatchDetails details =
938 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
939 if (details.dispatcher_destroyed)
940 return details;
941 // If the |mouse_moved_handler_| changes out from under us, assume a
942 // nested message loop ran and we don't need to do anything.
943 if (mouse_moved_handler_ != old_mouse_moved_handler)
944 return DispatchDetails();
945 if (destroyed_tracker.Contains(target)) {
946 destroyed_tracker.Remove(target);
947 mouse_moved_handler_ = target;
948 DispatchDetails details =
949 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED);
950 if (details.dispatcher_destroyed)
951 return details;
952 } else {
953 mouse_moved_handler_ = NULL;
954 return DispatchDetails();
957 break;
958 case ui::ET_MOUSE_PRESSED:
959 // Don't set the mouse pressed handler for non client mouse down events.
960 // These are only sent by Windows and are not always followed with non
961 // client mouse up events which causes subsequent mouse events to be
962 // sent to the wrong target.
963 if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
964 mouse_pressed_handler_ = target;
965 Env::GetInstance()->set_mouse_button_flags(
966 event->flags() & kMouseButtonFlagMask);
967 break;
968 case ui::ET_MOUSE_RELEASED:
969 mouse_pressed_handler_ = NULL;
970 Env::GetInstance()->set_mouse_button_flags(event->flags() &
971 kMouseButtonFlagMask & ~event->changed_button_flags());
972 break;
973 default:
974 break;
976 if (target) {
977 event->ConvertLocationToTarget(window(), target);
978 if (IsNonClientLocation(target, event->location()))
979 event->set_flags(event->flags() | ui::EF_IS_NON_CLIENT);
980 return ProcessEvent(target, event);
982 return DispatchDetails();
985 ui::EventDispatchDetails RootWindow::DispatchTouchEventImpl(
986 ui::TouchEvent* event) {
987 switch (event->type()) {
988 case ui::ET_TOUCH_PRESSED:
989 touch_ids_down_ |= (1 << event->touch_id());
990 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
991 break;
993 // Handle ET_TOUCH_CANCELLED only if it has a native event.
994 case ui::ET_TOUCH_CANCELLED:
995 if (!event->HasNativeEvent())
996 break;
997 // fallthrough
998 case ui::ET_TOUCH_RELEASED:
999 touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^
1000 (1 << event->touch_id());
1001 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
1002 break;
1004 default:
1005 break;
1007 TransformEventForDeviceScaleFactor(event);
1008 Window* target = client::GetCaptureWindow(window());
1009 if (!target) {
1010 target = ConsumerToWindow(
1011 ui::GestureRecognizer::Get()->GetTouchLockedTarget(event));
1012 if (!target) {
1013 target = ConsumerToWindow(ui::GestureRecognizer::Get()->
1014 GetTargetForLocation(event->location()));
1018 // The gesture recognizer processes touch events in the system coordinates. So
1019 // keep a copy of the touch event here before possibly converting the event to
1020 // a window's local coordinate system.
1021 ui::TouchEvent event_for_gr(*event);
1023 ui::EventResult result = ui::ER_UNHANDLED;
1024 if (!target && !window()->bounds().Contains(event->location())) {
1025 // If the initial touch is outside the root window, target the root.
1026 target = window();
1027 DispatchDetails details = ProcessEvent(target ? target : NULL, event);
1028 if (details.dispatcher_destroyed)
1029 return details;
1030 result = event->result();
1031 } else {
1032 // We only come here when the first contact was within the root window.
1033 if (!target) {
1034 target = window()->GetEventHandlerForPoint(event->location());
1035 if (!target)
1036 return DispatchDetails();
1039 event->ConvertLocationToTarget(window(), target);
1040 DispatchDetails details = ProcessEvent(target, event);
1041 if (details.dispatcher_destroyed)
1042 return details;
1043 result = event->result();
1046 // Get the list of GestureEvents from GestureRecognizer.
1047 scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
1048 gestures.reset(ui::GestureRecognizer::Get()->
1049 ProcessTouchEventForGesture(event_for_gr, result, target));
1051 return ProcessGestures(gestures.get());
1054 ui::EventDispatchDetails RootWindow::DispatchHeldEvents() {
1055 DispatchDetails dispatch_details;
1056 if (held_repostable_event_) {
1057 if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) {
1058 scoped_ptr<ui::MouseEvent> mouse_event(
1059 static_cast<ui::MouseEvent*>(held_repostable_event_.release()));
1060 dispatch_details = DispatchMouseEventRepost(mouse_event.get());
1061 } else {
1062 // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
1063 NOTREACHED();
1065 if (dispatch_details.dispatcher_destroyed)
1066 return dispatch_details;
1069 if (held_move_event_ && held_move_event_->IsMouseEvent()) {
1070 // If a mouse move has been synthesized, the target location is suspect,
1071 // so drop the held event.
1072 if (!synthesize_mouse_move_)
1073 dispatch_details = DispatchMouseEventImpl(
1074 static_cast<ui::MouseEvent*>(held_move_event_.get()));
1075 if (!dispatch_details.dispatcher_destroyed)
1076 held_move_event_.reset();
1077 } else if (held_move_event_ && held_move_event_->IsTouchEvent()) {
1078 dispatch_details = DispatchTouchEventImpl(
1079 static_cast<ui::TouchEvent*>(held_move_event_.get()));
1080 if (!dispatch_details.dispatcher_destroyed)
1081 held_move_event_.reset();
1084 return dispatch_details;
1087 void RootWindow::DispatchHeldEventsAsync() {
1088 DispatchDetails details = DispatchHeldEvents();
1089 if (details.dispatcher_destroyed)
1090 return;
1093 void RootWindow::PostMouseMoveEventAfterWindowChange() {
1094 if (synthesize_mouse_move_)
1095 return;
1096 synthesize_mouse_move_ = true;
1097 base::MessageLoop::current()->PostTask(
1098 FROM_HERE,
1099 base::Bind(&RootWindow::SynthesizeMouseMoveEventAsync,
1100 held_event_factory_.GetWeakPtr()));
1103 ui::EventDispatchDetails RootWindow::SynthesizeMouseMoveEvent() {
1104 DispatchDetails details;
1105 if (!synthesize_mouse_move_)
1106 return details;
1107 synthesize_mouse_move_ = false;
1108 gfx::Point root_mouse_location = GetLastMouseLocationInRoot();
1109 if (!window()->bounds().Contains(root_mouse_location))
1110 return details;
1111 gfx::Point host_mouse_location = root_mouse_location;
1112 ConvertPointToHost(&host_mouse_location);
1114 ui::MouseEvent event(ui::ET_MOUSE_MOVED,
1115 host_mouse_location,
1116 host_mouse_location,
1117 ui::EF_IS_SYNTHESIZED);
1118 return OnHostMouseEventImpl(&event);
1121 void RootWindow::SynthesizeMouseMoveEventAsync() {
1122 DispatchDetails details = SynthesizeMouseMoveEvent();
1123 if (details.dispatcher_destroyed)
1124 return;
1127 gfx::Transform RootWindow::GetInverseRootTransform() const {
1128 float scale = ui::GetDeviceScaleFactor(window()->layer());
1129 gfx::Transform transform;
1130 transform.Scale(1.0f / scale, 1.0f / scale);
1131 return transformer_->GetInverseTransform() * transform;
1134 } // namespace aura