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/auto_reset.h"
10#include "base/bind.h"
11#include "base/command_line.h"
12#include "base/debug/trace_event.h"
13#include "base/logging.h"
14#include "base/message_loop/message_loop.h"
15#include "ui/aura/client/activation_client.h"
16#include "ui/aura/client/capture_client.h"
17#include "ui/aura/client/cursor_client.h"
18#include "ui/aura/client/event_client.h"
19#include "ui/aura/client/focus_client.h"
20#include "ui/aura/client/screen_position_client.h"
21#include "ui/aura/env.h"
22#include "ui/aura/root_window_host.h"
23#include "ui/aura/root_window_observer.h"
24#include "ui/aura/root_window_transformer.h"
25#include "ui/aura/window.h"
26#include "ui/aura/window_delegate.h"
27#include "ui/aura/window_tracker.h"
28#include "ui/base/events/event.h"
29#include "ui/base/gestures/gesture_recognizer.h"
30#include "ui/base/gestures/gesture_types.h"
31#include "ui/base/hit_test.h"
32#include "ui/base/view_prop.h"
33#include "ui/compositor/compositor.h"
34#include "ui/compositor/dip_util.h"
35#include "ui/compositor/layer.h"
36#include "ui/compositor/layer_animator.h"
37#include "ui/gfx/display.h"
38#include "ui/gfx/point3_f.h"
39#include "ui/gfx/point_conversions.h"
40#include "ui/gfx/screen.h"
41#include "ui/gfx/size_conversions.h"
42
43using std::vector;
44
45namespace aura {
46
47namespace {
48
49const 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.
54bool 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
61float GetDeviceScaleFactorFromDisplay(Window* window) {
62  return gfx::Screen::GetScreenFor(window)->
63      GetDisplayNearestWindow(window).device_scale_factor();
64}
65
66Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
67  return consumer && !consumer->ignores_events() ?
68      static_cast<Window*>(consumer) : NULL;
69}
70
71void SetLastMouseLocation(const RootWindow* 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);
81  }
82}
83
84RootWindowHost* CreateHost(RootWindow* root_window,
85                           const RootWindow::CreateParams& params) {
86  RootWindowHost* host = params.host ?
87      params.host : RootWindowHost::Create(params.initial_bounds);
88  host->SetDelegate(root_window);
89  return host;
90}
91
92class SimpleRootWindowTransformer : public RootWindowTransformer {
93 public:
94  SimpleRootWindowTransformer(const RootWindow* root_window,
95                              const gfx::Transform& transform)
96      : root_window_(root_window),
97        transform_(transform) {
98  }
99
100  // RootWindowTransformer overrides:
101  virtual gfx::Transform GetTransform() const OVERRIDE {
102    return transform_;
103  }
104
105  virtual gfx::Transform GetInverseTransform() const OVERRIDE {
106    gfx::Transform invert;
107    if (!transform_.GetInverse(&invert))
108      return transform_;
109    return invert;
110  }
111
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()));
118  }
119
120  virtual gfx::Insets GetHostInsets() const OVERRIDE {
121    return gfx::Insets();
122  }
123
124 private:
125  virtual ~SimpleRootWindowTransformer() {}
126
127  const RootWindow* root_window_;
128  const gfx::Transform transform_;
129
130  DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
131};
132
133}  // namespace
134
135RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds)
136    : initial_bounds(a_initial_bounds),
137      host(NULL) {
138}
139
140////////////////////////////////////////////////////////////////////////////////
141// RootWindow, public:
142
143RootWindow::RootWindow(const CreateParams& params)
144    : Window(NULL),
145      host_(CreateHost(this, params)),
146      schedule_paint_factory_(this),
147      event_factory_(this),
148      touch_ids_down_(0),
149      last_cursor_(ui::kCursorNull),
150      mouse_pressed_handler_(NULL),
151      mouse_moved_handler_(NULL),
152      mouse_event_dispatch_target_(NULL),
153      event_dispatch_target_(NULL),
154      gesture_recognizer_(ui::GestureRecognizer::Create(this)),
155      synthesize_mouse_move_(false),
156      waiting_on_compositing_end_(false),
157      draw_on_compositing_end_(false),
158      defer_draw_scheduling_(false),
159      move_hold_count_(0),
160      held_event_factory_(this),
161      repostable_event_factory_(this) {
162  SetName("RootWindow");
163
164  compositor_.reset(new ui::Compositor(this, host_->GetAcceleratedWidget()));
165  DCHECK(compositor_.get());
166  compositor_->AddObserver(this);
167
168  prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(),
169                               kRootWindowForAcceleratedWidget,
170                               this));
171}
172
173RootWindow::~RootWindow() {
174  compositor_->RemoveObserver(this);
175  // Make sure to destroy the compositor before terminating so that state is
176  // cleared and we don't hit asserts.
177  compositor_.reset();
178
179  // Tear down in reverse.  Frees any references held by the host.
180  host_.reset(NULL);
181
182  // An observer may have been added by an animation on the RootWindow.
183  layer()->GetAnimator()->RemoveObserver(this);
184}
185
186// static
187RootWindow* RootWindow::GetForAcceleratedWidget(
188    gfx::AcceleratedWidget widget) {
189  return reinterpret_cast<RootWindow*>(
190      ui::ViewProp::GetValue(widget, kRootWindowForAcceleratedWidget));
191}
192
193void RootWindow::Init() {
194  compositor()->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(this),
195                                host_->GetBounds().size());
196  Window::Init(ui::LAYER_NOT_DRAWN);
197  compositor()->SetRootLayer(layer());
198  transformer_.reset(new SimpleRootWindowTransformer(this, gfx::Transform()));
199  UpdateRootWindowSize(GetHostSize());
200  Env::GetInstance()->NotifyRootWindowInitialized(this);
201  Show();
202}
203
204void RootWindow::ShowRootWindow() {
205  host_->Show();
206}
207
208void RootWindow::HideRootWindow() {
209  host_->Hide();
210}
211
212void RootWindow::PrepareForShutdown() {
213  host_->PrepareForShutdown();
214  // discard synthesize event request as well.
215  synthesize_mouse_move_ = false;
216}
217
218void RootWindow::RepostEvent(const ui::LocatedEvent& event) {
219  // We allow for only one outstanding repostable event. This is used
220  // in exiting context menus.  A dropped repost request is allowed.
221  if (event.type() == ui::ET_MOUSE_PRESSED) {
222    held_repostable_event_.reset(
223        new ui::MouseEvent(
224            static_cast<const ui::MouseEvent&>(event),
225            static_cast<aura::Window*>(event.target()),
226            static_cast<aura::Window*>(this)));
227    base::MessageLoop::current()->PostTask(
228        FROM_HERE,
229        base::Bind(&RootWindow::DispatchHeldEvents,
230                   repostable_event_factory_.GetWeakPtr()));
231  } else {
232    DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN);
233    held_repostable_event_.reset();
234    // TODO(sschmitz): add similar code for gesture events.
235  }
236}
237
238RootWindowHostDelegate* RootWindow::AsRootWindowHostDelegate() {
239  return this;
240}
241
242void RootWindow::SetHostSize(const gfx::Size& size_in_pixel) {
243  DispatchHeldEvents();
244  gfx::Rect bounds = host_->GetBounds();
245  bounds.set_size(size_in_pixel);
246  host_->SetBounds(bounds);
247
248  // Requery the location to constrain it within the new root window size.
249  gfx::Point point;
250  if (host_->QueryMouseLocation(&point))
251    SetLastMouseLocation(this, ui::ConvertPointToDIP(layer(), point));
252
253  synthesize_mouse_move_ = false;
254}
255
256gfx::Size RootWindow::GetHostSize() const {
257  return host_->GetBounds().size();
258}
259
260void RootWindow::SetHostBounds(const gfx::Rect& bounds_in_pixel) {
261  DCHECK(!bounds_in_pixel.IsEmpty());
262  DispatchHeldEvents();
263  host_->SetBounds(bounds_in_pixel);
264  synthesize_mouse_move_ = false;
265}
266
267gfx::Point RootWindow::GetHostOrigin() const {
268  return host_->GetBounds().origin();
269}
270
271void 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);
276}
277
278void RootWindow::OnCursorVisibilityChanged(bool show) {
279  host_->OnCursorVisibilityChanged(show);
280}
281
282void RootWindow::OnMouseEventsEnableStateChanged(bool enabled) {
283  // Send entered / exited so that visual state can be updated to match
284  // mouse events state.
285  PostMouseMoveEventAfterWindowChange();
286  // TODO(mazda): Add code to disable mouse events when |enabled| == false.
287}
288
289void RootWindow::MoveCursorTo(const gfx::Point& location_in_dip) {
290  gfx::Point host_location(location_in_dip);
291  ConvertPointToHost(&host_location);
292  MoveCursorToInternal(location_in_dip, host_location);
293}
294
295void RootWindow::MoveCursorToHostLocation(const gfx::Point& host_location) {
296  gfx::Point root_location(host_location);
297  ConvertPointFromHost(&root_location);
298  MoveCursorToInternal(root_location, host_location);
299}
300
301bool RootWindow::ConfineCursorToWindow() {
302  // We would like to be able to confine the cursor to that window. However,
303  // currently, we do not have such functionality in X. So we just confine
304  // to the root window. This is ok because this option is currently only
305  // being used in fullscreen mode, so root_window bounds = window bounds.
306  return host_->ConfineCursorToRootWindow();
307}
308
309void RootWindow::Draw() {
310  defer_draw_scheduling_ = false;
311  if (waiting_on_compositing_end_) {
312    draw_on_compositing_end_ = true;
313    return;
314  }
315  waiting_on_compositing_end_ = true;
316
317  TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::Draw",
318                           compositor_->last_started_frame() + 1);
319
320  compositor_->Draw();
321}
322
323void RootWindow::ScheduleFullRedraw() {
324  compositor_->ScheduleFullRedraw();
325}
326
327void RootWindow::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
328  compositor_->ScheduleRedrawRect(damage_rect);
329}
330
331Window* RootWindow::GetGestureTarget(ui::GestureEvent* event) {
332  Window* target = client::GetCaptureWindow(this);
333  if (!target) {
334    target = ConsumerToWindow(
335        gesture_recognizer_->GetTargetForGestureEvent(event));
336  }
337
338  return target;
339}
340
341bool RootWindow::DispatchGestureEvent(ui::GestureEvent* event) {
342  DispatchHeldEvents();
343
344  Window* target = GetGestureTarget(event);
345  if (target) {
346    event->ConvertLocationToTarget(static_cast<Window*>(this), target);
347    ProcessEvent(target, event);
348    return event->handled();
349  }
350
351  return false;
352}
353
354void RootWindow::OnWindowDestroying(Window* window) {
355  DispatchMouseExitToHidingWindow(window);
356  OnWindowHidden(window, WINDOW_DESTROYED);
357
358  if (window->IsVisible() &&
359      window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
360    PostMouseMoveEventAfterWindowChange();
361  }
362}
363
364void RootWindow::OnWindowBoundsChanged(Window* window,
365                                       bool contained_mouse_point) {
366  if (contained_mouse_point ||
367      (window->IsVisible() &&
368       window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
369    PostMouseMoveEventAfterWindowChange();
370  }
371}
372
373void RootWindow::DispatchMouseExitToHidingWindow(Window* window) {
374  // The mouse capture is intentionally ignored. Think that a mouse enters
375  // to a window, the window sets the capture, the mouse exits the window,
376  // and then it releases the capture. In that case OnMouseExited won't
377  // be called. So it is natural not to emit OnMouseExited even though
378  // |window| is the capture window.
379  gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
380  if (window->Contains(mouse_moved_handler_) &&
381      window->ContainsPointInRoot(last_mouse_location)) {
382    ui::MouseEvent event(ui::ET_MOUSE_EXITED,
383                         last_mouse_location,
384                         last_mouse_location,
385                         ui::EF_NONE);
386    DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
387  }
388}
389
390void 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
398void RootWindow::OnWindowTransformed(Window* window, bool contained_mouse) {
399  if (contained_mouse ||
400      (window->IsVisible() &&
401       window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
402    PostMouseMoveEventAfterWindowChange();
403  }
404}
405
406void RootWindow::OnKeyboardMappingChanged() {
407  FOR_EACH_OBSERVER(RootWindowObserver, observers_,
408                    OnKeyboardMappingChanged(this));
409}
410
411void RootWindow::OnRootWindowHostCloseRequested() {
412  FOR_EACH_OBSERVER(RootWindowObserver, observers_,
413                    OnRootWindowHostCloseRequested(this));
414}
415
416void RootWindow::AddRootWindowObserver(RootWindowObserver* observer) {
417  observers_.AddObserver(observer);
418}
419
420void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) {
421  observers_.RemoveObserver(observer);
422}
423
424void RootWindow::PostNativeEvent(const base::NativeEvent& native_event) {
425#if !defined(OS_MACOSX)
426  host_->PostNativeEvent(native_event);
427#endif
428}
429
430void RootWindow::ConvertPointToNativeScreen(gfx::Point* point) const {
431  ConvertPointToHost(point);
432  gfx::Point location = host_->GetLocationOnNativeScreen();
433  point->Offset(location.x(), location.y());
434}
435
436void RootWindow::ConvertPointFromNativeScreen(gfx::Point* point) const {
437  gfx::Point location = host_->GetLocationOnNativeScreen();
438  point->Offset(-location.x(), -location.y());
439  ConvertPointFromHost(point);
440}
441
442void RootWindow::ConvertPointToHost(gfx::Point* point) const {
443  gfx::Point3F point_3f(*point);
444  GetRootTransform().TransformPoint(point_3f);
445  *point = gfx::ToFlooredPoint(point_3f.AsPointF());
446}
447
448void RootWindow::ConvertPointFromHost(gfx::Point* point) const {
449  gfx::Point3F point_3f(*point);
450  GetInverseRootTransform().TransformPoint(point_3f);
451  *point = gfx::ToFlooredPoint(point_3f.AsPointF());
452}
453
454void RootWindow::ProcessedTouchEvent(ui::TouchEvent* event,
455                                     Window* window,
456                                     ui::EventResult result) {
457  scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
458  gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
459      *event, result, window));
460  ProcessGestures(gestures.get());
461}
462
463void RootWindow::SetGestureRecognizerForTesting(ui::GestureRecognizer* gr) {
464  gesture_recognizer_.reset(gr);
465}
466
467gfx::AcceleratedWidget RootWindow::GetAcceleratedWidget() {
468  return host_->GetAcceleratedWidget();
469}
470
471void RootWindow::ToggleFullScreen() {
472  host_->ToggleFullScreen();
473}
474
475void RootWindow::HoldPointerMoves() {
476  if (!move_hold_count_)
477    held_event_factory_.InvalidateWeakPtrs();
478  ++move_hold_count_;
479  TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::HoldPointerMoves", this);
480}
481
482void RootWindow::ReleasePointerMoves() {
483  --move_hold_count_;
484  DCHECK_GE(move_hold_count_, 0);
485  if (!move_hold_count_ && held_move_event_) {
486    // We don't want to call DispatchHeldEvents directly, because this might be
487    // called from a deep stack while another event, in which case dispatching
488    // another one may not be safe/expected.  Instead we post a task, that we
489    // may cancel if HoldPointerMoves is called again before it executes.
490    base::MessageLoop::current()->PostTask(
491        FROM_HERE,
492        base::Bind(&RootWindow::DispatchHeldEvents,
493                   held_event_factory_.GetWeakPtr()));
494  }
495  TRACE_EVENT_ASYNC_END0("ui", "RootWindow::HoldPointerMoves", this);
496}
497
498void RootWindow::SetFocusWhenShown(bool focused) {
499  host_->SetFocusWhenShown(focused);
500}
501
502bool RootWindow::CopyAreaToSkCanvas(const gfx::Rect& source_bounds,
503                                    const gfx::Point& dest_offset,
504                                    SkCanvas* canvas) {
505  DCHECK(canvas);
506  DCHECK(bounds().Contains(source_bounds));
507  gfx::Rect source_pixels = ui::ConvertRectToPixel(layer(), source_bounds);
508  return host_->CopyAreaToSkCanvas(source_pixels, dest_offset, canvas);
509}
510
511gfx::Point RootWindow::GetLastMouseLocationInRoot() const {
512  gfx::Point location = Env::GetInstance()->last_mouse_location();
513  client::ScreenPositionClient* client = client::GetScreenPositionClient(this);
514  if (client)
515    client->ConvertPointFromScreen(this, &location);
516  return location;
517}
518
519////////////////////////////////////////////////////////////////////////////////
520// RootWindow, Window overrides:
521
522RootWindow* RootWindow::GetRootWindow() {
523  return this;
524}
525
526const RootWindow* RootWindow::GetRootWindow() const {
527  return this;
528}
529
530void RootWindow::SetTransform(const gfx::Transform& transform) {
531  scoped_ptr<RootWindowTransformer> transformer(
532      new SimpleRootWindowTransformer(this, transform));
533  SetRootWindowTransformer(transformer.Pass());
534}
535
536void RootWindow::SetRootWindowTransformer(
537    scoped_ptr<RootWindowTransformer> transformer) {
538  transformer_ = transformer.Pass();
539  host_->SetInsets(transformer_->GetHostInsets());
540  Window::SetTransform(transformer_->GetTransform());
541  // If the layer is not animating, then we need to update the root window
542  // size immediately.
543  if (!layer()->GetAnimator()->is_animating())
544    UpdateRootWindowSize(GetHostSize());
545}
546
547gfx::Transform RootWindow::GetRootTransform() const {
548  float scale = ui::GetDeviceScaleFactor(layer());
549  gfx::Transform transform;
550  transform.Scale(scale, scale);
551  transform *= transformer_->GetTransform();
552  return transform;
553}
554
555////////////////////////////////////////////////////////////////////////////////
556// RootWindow, ui::EventTarget implementation:
557
558ui::EventTarget* RootWindow::GetParentTarget() {
559  return client::GetEventClient(this) ?
560      client::GetEventClient(this)->GetToplevelEventTarget() :
561          Env::GetInstance();
562}
563
564////////////////////////////////////////////////////////////////////////////////
565// RootWindow, ui::CompositorDelegate implementation:
566
567void RootWindow::ScheduleDraw() {
568  DCHECK(!ui::Compositor::WasInitializedWithThread());
569  if (!defer_draw_scheduling_) {
570    defer_draw_scheduling_ = true;
571    base::MessageLoop::current()->PostTask(
572        FROM_HERE,
573        base::Bind(&RootWindow::Draw, schedule_paint_factory_.GetWeakPtr()));
574  }
575}
576
577////////////////////////////////////////////////////////////////////////////////
578// RootWindow, ui::CompositorObserver implementation:
579
580void RootWindow::OnCompositingDidCommit(ui::Compositor*) {
581}
582
583void RootWindow::OnCompositingStarted(ui::Compositor*,
584                                      base::TimeTicks start_time) {
585}
586
587void RootWindow::OnCompositingEnded(ui::Compositor*) {
588  TRACE_EVENT_ASYNC_END0("ui", "RootWindow::Draw",
589                         compositor_->last_ended_frame());
590  waiting_on_compositing_end_ = false;
591  if (draw_on_compositing_end_) {
592    draw_on_compositing_end_ = false;
593
594    // Call ScheduleDraw() instead of Draw() in order to allow other
595    // ui::CompositorObservers to be notified before starting another
596    // draw cycle.
597    ScheduleDraw();
598  }
599}
600
601void RootWindow::OnCompositingAborted(ui::Compositor*) {
602}
603
604void RootWindow::OnCompositingLockStateChanged(ui::Compositor*) {
605}
606
607void RootWindow::OnUpdateVSyncParameters(ui::Compositor* compositor,
608                                         base::TimeTicks timebase,
609                                         base::TimeDelta interval) {
610}
611
612////////////////////////////////////////////////////////////////////////////////
613// RootWindow, ui::LayerDelegate implementation:
614
615void RootWindow::OnDeviceScaleFactorChanged(
616    float device_scale_factor) {
617  const bool cursor_is_in_bounds =
618      GetBoundsInScreen().Contains(Env::GetInstance()->last_mouse_location());
619  bool cursor_visible = false;
620  client::CursorClient* cursor_client = client::GetCursorClient(this);
621  if (cursor_is_in_bounds && cursor_client) {
622    cursor_visible = cursor_client->IsCursorVisible();
623    if (cursor_visible)
624      cursor_client->HideCursor();
625  }
626  host_->OnDeviceScaleFactorChanged(device_scale_factor);
627  Window::OnDeviceScaleFactorChanged(device_scale_factor);
628  // Update the device scale factor of the cursor client only when the last
629  // mouse location is on this root window.
630  if (cursor_is_in_bounds) {
631    if (cursor_client) {
632      const gfx::Display& display =
633          gfx::Screen::GetScreenFor(this)->GetDisplayNearestWindow(this);
634      cursor_client->SetDisplay(display);
635    }
636  }
637  if (cursor_is_in_bounds && cursor_client && cursor_visible)
638    cursor_client->ShowCursor();
639}
640
641////////////////////////////////////////////////////////////////////////////////
642// RootWindow, overridden from aura::Window:
643
644bool RootWindow::CanFocus() const {
645  return IsVisible();
646}
647
648bool RootWindow::CanReceiveEvents() const {
649  return IsVisible();
650}
651
652////////////////////////////////////////////////////////////////////////////////
653// RootWindow, overridden from aura::client::CaptureDelegate:
654
655void RootWindow::UpdateCapture(Window* old_capture,
656                               Window* new_capture) {
657  if (old_capture && old_capture->GetRootWindow() == this &&
658      old_capture->delegate()) {
659    // Send a capture changed event with bogus location data.
660    ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(),
661                         gfx::Point(), 0);
662
663    ProcessEvent(old_capture, &event);
664
665    old_capture->delegate()->OnCaptureLost();
666  }
667
668  // Reset the mouse_moved_handler_ if the mouse_moved_handler_ belongs
669  // to another root window when losing the capture.
670  if (mouse_moved_handler_ && old_capture &&
671      old_capture->Contains(mouse_moved_handler_) &&
672      old_capture->GetRootWindow() != this) {
673    mouse_moved_handler_ = NULL;
674  }
675
676  if (new_capture) {
677    // Make all subsequent mouse events and touch go to the capture window. We
678    // shouldn't need to send an event here as OnCaptureLost should take care of
679    // that.
680    if (mouse_moved_handler_ || Env::GetInstance()->is_mouse_button_down())
681      mouse_moved_handler_ = new_capture;
682  } else {
683    // Make sure mouse_moved_handler gets updated.
684    SynthesizeMouseMoveEvent();
685  }
686  mouse_pressed_handler_ = NULL;
687}
688
689void RootWindow::SetNativeCapture() {
690  host_->SetCapture();
691}
692
693void RootWindow::ReleaseNativeCapture() {
694  host_->ReleaseCapture();
695}
696
697bool RootWindow::QueryMouseLocationForTest(gfx::Point* point) const {
698  return host_->QueryMouseLocation(point);
699}
700
701void RootWindow::ClearMouseHandlers() {
702  mouse_pressed_handler_ = NULL;
703  mouse_moved_handler_ = NULL;
704  mouse_event_dispatch_target_ = NULL;
705}
706
707////////////////////////////////////////////////////////////////////////////////
708// RootWindow, private:
709
710void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent* event) {
711  event->UpdateForRootTransform(GetInverseRootTransform());
712}
713
714void RootWindow::MoveCursorToInternal(const gfx::Point& root_location,
715                                      const gfx::Point& host_location) {
716  host_->MoveCursorTo(host_location);
717  SetLastMouseLocation(this, root_location);
718  client::CursorClient* cursor_client = client::GetCursorClient(this);
719  if (cursor_client) {
720    const gfx::Display& display =
721        gfx::Screen::GetScreenFor(this)->GetDisplayNearestWindow(this);
722    cursor_client->SetDisplay(display);
723  }
724  synthesize_mouse_move_ = false;
725}
726
727void RootWindow::HandleMouseMoved(const ui::MouseEvent& event, Window* target) {
728  if (target == mouse_moved_handler_)
729    return;
730
731  DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
732
733  if (mouse_event_dispatch_target_ != target) {
734    mouse_moved_handler_ = NULL;
735    return;
736  }
737
738  mouse_moved_handler_ = target;
739
740  DispatchMouseEnterOrExit(event, ui::ET_MOUSE_ENTERED);
741}
742
743void RootWindow::DispatchMouseEnterOrExit(const ui::MouseEvent& event,
744                                          ui::EventType type) {
745  if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate())
746    return;
747
748  ui::MouseEvent translated_event(event,
749                                  static_cast<Window*>(this),
750                                  mouse_moved_handler_,
751                                  type,
752                                  event.flags() | ui::EF_IS_SYNTHESIZED);
753  ProcessEvent(mouse_moved_handler_, &translated_event);
754}
755
756void RootWindow::ProcessEvent(Window* target, ui::Event* event) {
757  Window* old_target = event_dispatch_target_;
758  event_dispatch_target_ = target;
759  if (DispatchEvent(target, event))
760    event_dispatch_target_ = old_target;
761}
762
763bool RootWindow::ProcessGestures(ui::GestureRecognizer::Gestures* gestures) {
764  if (!gestures || gestures->empty())
765    return false;
766
767  Window* target = GetGestureTarget(gestures->get().at(0));
768  Window* old_target = event_dispatch_target_;
769  event_dispatch_target_ = target;
770
771  bool handled = false;
772  for (size_t i = 0; i < gestures->size(); ++i) {
773    ui::GestureEvent* event = gestures->get().at(i);
774    event->ConvertLocationToTarget(static_cast<Window*>(this), target);
775    if (!DispatchEvent(target, event))
776      return false;  // |this| has been destroyed.
777    if (event->handled())
778      handled = true;
779    if (event_dispatch_target_ != target)  // |target| has been destroyed.
780      break;
781  }
782  event_dispatch_target_ = old_target;
783  return handled;
784}
785
786void RootWindow::OnWindowRemovedFromRootWindow(Window* detached,
787                                               RootWindow* new_root) {
788  DCHECK(aura::client::GetCaptureWindow(this) != this);
789
790  DispatchMouseExitToHidingWindow(detached);
791  OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
792
793  if (detached->IsVisible() &&
794      detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
795    PostMouseMoveEventAfterWindowChange();
796  }
797}
798
799void RootWindow::OnWindowHidden(Window* invisible, WindowHiddenReason reason) {
800  // TODO(beng): This should be removed once FocusController is turned on.
801  if (client::GetFocusClient(this)) {
802    client::GetFocusClient(this)->OnWindowHiddenInRootWindow(
803        invisible, this, reason == WINDOW_DESTROYED);
804  }
805
806  // Do not clear the capture, and the |event_dispatch_target_| if the
807  // window is moving across root windows, because the target itself
808  // is actually still visible and clearing them stops further event
809  // processing, which can cause unexpected behaviors. See
810  // crbug.com/157583
811  if (reason != WINDOW_MOVING) {
812    Window* capture_window = aura::client::GetCaptureWindow(this);
813    // If the ancestor of the capture window is hidden,
814    // release the capture.
815    if (invisible->Contains(capture_window) && invisible != this)
816      capture_window->ReleaseCapture();
817
818    if (invisible->Contains(event_dispatch_target_))
819      event_dispatch_target_ = NULL;
820  }
821
822  // If the ancestor of any event handler windows are invisible, release the
823  // pointer to those windows.
824  if (invisible->Contains(mouse_pressed_handler_))
825    mouse_pressed_handler_ = NULL;
826  if (invisible->Contains(mouse_moved_handler_))
827    mouse_moved_handler_ = NULL;
828  if (invisible->Contains(mouse_event_dispatch_target_))
829    mouse_event_dispatch_target_ = NULL;
830
831  CleanupGestureRecognizerState(invisible);
832}
833
834void RootWindow::CleanupGestureRecognizerState(Window* window) {
835  gesture_recognizer_->CleanupStateForConsumer(window);
836  Windows windows = window->children();
837  for (Windows::const_iterator iter = windows.begin();
838      iter != windows.end();
839      ++iter) {
840    CleanupGestureRecognizerState(*iter);
841  }
842}
843
844void RootWindow::UpdateRootWindowSize(const gfx::Size& host_size) {
845  SetBounds(transformer_->GetRootWindowBounds(host_size));
846}
847
848void RootWindow::OnWindowAddedToRootWindow(Window* attached) {
849  if (attached->IsVisible() &&
850      attached->ContainsPointInRoot(GetLastMouseLocationInRoot()))
851    PostMouseMoveEventAfterWindowChange();
852}
853
854bool RootWindow::CanDispatchToTarget(ui::EventTarget* target) {
855  return event_dispatch_target_ == target;
856}
857
858bool RootWindow::DispatchLongPressGestureEvent(ui::GestureEvent* event) {
859  return DispatchGestureEvent(event);
860}
861
862bool RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) {
863  return OnHostTouchEvent(event);
864}
865
866void RootWindow::OnLayerAnimationEnded(
867    ui::LayerAnimationSequence* animation) {
868  UpdateRootWindowSize(GetHostSize());
869}
870
871void RootWindow::OnLayerAnimationScheduled(
872    ui::LayerAnimationSequence* animation) {
873}
874
875void RootWindow::OnLayerAnimationAborted(
876    ui::LayerAnimationSequence* animation) {
877}
878
879////////////////////////////////////////////////////////////////////////////////
880// RootWindow, RootWindowHostDelegate implementation:
881
882bool RootWindow::OnHostKeyEvent(ui::KeyEvent* event) {
883  DispatchHeldEvents();
884  if (event->key_code() == ui::VKEY_UNKNOWN)
885    return false;
886  client::EventClient* client = client::GetEventClient(GetRootWindow());
887  Window* focused_window = client::GetFocusClient(this)->GetFocusedWindow();
888  if (client && !client->CanProcessEventsWithinSubtree(focused_window)) {
889    client::GetFocusClient(this)->FocusWindow(NULL);
890    return false;
891  }
892  ProcessEvent(focused_window ? focused_window : this, event);
893  return event->handled();
894}
895
896bool RootWindow::OnHostMouseEvent(ui::MouseEvent* event) {
897  if (event->type() == ui::ET_MOUSE_DRAGGED ||
898      (event->flags() & ui::EF_IS_SYNTHESIZED)) {
899    if (move_hold_count_) {
900      Window* null_window = static_cast<Window*>(NULL);
901      held_move_event_.reset(
902          new ui::MouseEvent(*event, null_window, null_window));
903      return true;
904    } else {
905      // We may have a held event for a period between the time move_hold_count_
906      // fell to 0 and the DispatchHeldEvents executes. Since we're going to
907      // dispatch the new event directly below, we can reset the old one.
908      held_move_event_.reset();
909    }
910  }
911  DispatchHeldEvents();
912  return DispatchMouseEventImpl(event);
913}
914
915bool RootWindow::OnHostScrollEvent(ui::ScrollEvent* event) {
916  DispatchHeldEvents();
917
918  TransformEventForDeviceScaleFactor(event);
919  SetLastMouseLocation(this, event->location());
920  synthesize_mouse_move_ = false;
921
922  Window* target = mouse_pressed_handler_ ?
923      mouse_pressed_handler_ : client::GetCaptureWindow(this);
924
925  if (!target)
926    target = GetEventHandlerForPoint(event->location());
927
928  if (!target)
929    target = this;
930
931  event->ConvertLocationToTarget(static_cast<Window*>(this), target);
932  int flags = event->flags();
933  if (IsNonClientLocation(target, event->location()))
934    flags |= ui::EF_IS_NON_CLIENT;
935  event->set_flags(flags);
936
937  ProcessEvent(target, event);
938  return event->handled();
939}
940
941bool RootWindow::OnHostTouchEvent(ui::TouchEvent* event) {
942  if ((event->type() == ui::ET_TOUCH_MOVED)) {
943    if (move_hold_count_) {
944      Window* null_window = static_cast<Window*>(NULL);
945      held_move_event_.reset(
946          new ui::TouchEvent(*event, null_window, null_window));
947      return true;
948    } else {
949      // We may have a held event for a period between the time move_hold_count_
950      // fell to 0 and the DispatchHeldEvents executes. Since we're going to
951      // dispatch the new event directly below, we can reset the old one.
952      held_move_event_.reset();
953    }
954  }
955  DispatchHeldEvents();
956  return DispatchTouchEventImpl(event);
957}
958
959void RootWindow::OnHostCancelMode() {
960  ui::CancelModeEvent event;
961  Window* focused_window = client::GetFocusClient(this)->GetFocusedWindow();
962  ProcessEvent(focused_window ? focused_window : this, &event);
963}
964
965void RootWindow::OnHostActivated() {
966  Env::GetInstance()->RootWindowActivated(this);
967}
968
969void RootWindow::OnHostLostWindowCapture() {
970  Window* capture_window = client::GetCaptureWindow(this);
971  if (capture_window && capture_window->GetRootWindow() == this)
972    capture_window->ReleaseCapture();
973}
974
975void RootWindow::OnHostLostMouseGrab() {
976  ClearMouseHandlers();
977}
978
979void RootWindow::OnHostPaint(const gfx::Rect& damage_rect) {
980  compositor_->ScheduleRedrawRect(damage_rect);
981}
982
983void RootWindow::OnHostMoved(const gfx::Point& origin) {
984  FOR_EACH_OBSERVER(RootWindowObserver, observers_,
985                    OnRootWindowHostMoved(this, origin));
986}
987
988void RootWindow::OnHostResized(const gfx::Size& size) {
989  DispatchHeldEvents();
990  // The compositor should have the same size as the native root window host.
991  // Get the latest scale from display because it might have been changed.
992  compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(this), size);
993
994  // The layer, and the observers should be notified of the
995  // transformed size of the root window.
996  UpdateRootWindowSize(size);
997  FOR_EACH_OBSERVER(RootWindowObserver, observers_,
998                    OnRootWindowHostResized(this));
999}
1000
1001float RootWindow::GetDeviceScaleFactor() {
1002  return compositor()->device_scale_factor();
1003}
1004
1005RootWindow* RootWindow::AsRootWindow() {
1006  return this;
1007}
1008
1009////////////////////////////////////////////////////////////////////////////////
1010// RootWindow, private:
1011
1012bool RootWindow::DispatchMouseEventImpl(ui::MouseEvent* event) {
1013  TransformEventForDeviceScaleFactor(event);
1014  Window* target = mouse_pressed_handler_ ?
1015      mouse_pressed_handler_ : client::GetCaptureWindow(this);
1016  if (!target)
1017    target = GetEventHandlerForPoint(event->location());
1018  return DispatchMouseEventToTarget(event, target);
1019}
1020
1021bool RootWindow::DispatchMouseEventRepost(ui::MouseEvent* event) {
1022  if (event->type() != ui::ET_MOUSE_PRESSED)
1023    return false;
1024  mouse_pressed_handler_ = NULL;
1025  Window* target = GetEventHandlerForPoint(event->location());
1026  return DispatchMouseEventToTarget(event, target);
1027}
1028
1029bool RootWindow::DispatchMouseEventToTarget(ui::MouseEvent* event,
1030                                            Window* target) {
1031  client::CursorClient* cursor_client = client::GetCursorClient(this);
1032  if (cursor_client &&
1033      !cursor_client->IsMouseEventsEnabled() &&
1034      (event->flags() & ui::EF_IS_SYNTHESIZED))
1035    return false;
1036
1037  static const int kMouseButtonFlagMask =
1038      ui::EF_LEFT_MOUSE_BUTTON |
1039      ui::EF_MIDDLE_MOUSE_BUTTON |
1040      ui::EF_RIGHT_MOUSE_BUTTON;
1041  base::AutoReset<Window*> reset(&mouse_event_dispatch_target_, target);
1042  SetLastMouseLocation(this, event->location());
1043  synthesize_mouse_move_ = false;
1044  switch (event->type()) {
1045    case ui::ET_MOUSE_EXITED:
1046      if (!target) {
1047        DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
1048        mouse_moved_handler_ = NULL;
1049      }
1050      break;
1051    case ui::ET_MOUSE_MOVED:
1052      mouse_event_dispatch_target_ = target;
1053      HandleMouseMoved(*event, target);
1054      if (mouse_event_dispatch_target_ != target)
1055        return false;
1056      break;
1057    case ui::ET_MOUSE_PRESSED:
1058      // Don't set the mouse pressed handler for non client mouse down events.
1059      // These are only sent by Windows and are not always followed with non
1060      // client mouse up events which causes subsequent mouse events to be
1061      // sent to the wrong target.
1062      if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
1063        mouse_pressed_handler_ = target;
1064      Env::GetInstance()->set_mouse_button_flags(
1065          event->flags() & kMouseButtonFlagMask);
1066      break;
1067    case ui::ET_MOUSE_RELEASED:
1068      mouse_pressed_handler_ = NULL;
1069      Env::GetInstance()->set_mouse_button_flags(event->flags() &
1070          kMouseButtonFlagMask & ~event->changed_button_flags());
1071      break;
1072    default:
1073      break;
1074  }
1075  if (target) {
1076    event->ConvertLocationToTarget(static_cast<Window*>(this), target);
1077    if (IsNonClientLocation(target, event->location()))
1078      event->set_flags(event->flags() | ui::EF_IS_NON_CLIENT);
1079    ProcessEvent(target, event);
1080    return event->handled();
1081  }
1082  return false;
1083}
1084
1085bool RootWindow::DispatchTouchEventImpl(ui::TouchEvent* event) {
1086  switch (event->type()) {
1087    case ui::ET_TOUCH_PRESSED:
1088      touch_ids_down_ |= (1 << event->touch_id());
1089      Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
1090      break;
1091
1092      // Handle ET_TOUCH_CANCELLED only if it has a native event.
1093    case ui::ET_TOUCH_CANCELLED:
1094      if (!event->HasNativeEvent())
1095        break;
1096      // fallthrough
1097    case ui::ET_TOUCH_RELEASED:
1098      touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^
1099            (1 << event->touch_id());
1100      Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
1101      break;
1102
1103    default:
1104      break;
1105  }
1106  TransformEventForDeviceScaleFactor(event);
1107  bool handled = false;
1108  Window* target = client::GetCaptureWindow(this);
1109  if (!target) {
1110    target = ConsumerToWindow(
1111        gesture_recognizer_->GetTouchLockedTarget(event));
1112    if (!target) {
1113      target = ConsumerToWindow(
1114          gesture_recognizer_->GetTargetForLocation(event->location()));
1115    }
1116  }
1117
1118  // The gesture recognizer processes touch events in the system coordinates. So
1119  // keep a copy of the touch event here before possibly converting the event to
1120  // a window's local coordinate system.
1121  ui::TouchEvent event_for_gr(*event);
1122
1123  ui::EventResult result = ui::ER_UNHANDLED;
1124  if (!target && !bounds().Contains(event->location())) {
1125    // If the initial touch is outside the root window, target the root.
1126    target = this;
1127    ProcessEvent(target ? target : NULL, event);
1128    result = event->result();
1129  } else {
1130    // We only come here when the first contact was within the root window.
1131    if (!target) {
1132      target = GetEventHandlerForPoint(event->location());
1133      if (!target)
1134        return false;
1135    }
1136
1137    event->ConvertLocationToTarget(static_cast<Window*>(this), target);
1138    ProcessEvent(target, event);
1139    handled = event->handled();
1140    result = event->result();
1141  }
1142
1143  // Get the list of GestureEvents from GestureRecognizer.
1144  scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
1145  gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
1146      event_for_gr, result, target));
1147
1148  return ProcessGestures(gestures.get()) ? true : handled;
1149}
1150
1151void RootWindow::DispatchHeldEvents() {
1152  if (held_repostable_event_) {
1153    if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) {
1154      ui::MouseEvent mouse_event(
1155          static_cast<const ui::MouseEvent&>(*held_repostable_event_.get()));
1156      held_repostable_event_.reset(); // must be reset before dispatch
1157      DispatchMouseEventRepost(&mouse_event);
1158    } else {
1159      DCHECK(held_repostable_event_->type() == ui::ET_GESTURE_TAP_DOWN);
1160      // TODO(sschmitz): add similar code for gesture events
1161    }
1162    held_repostable_event_.reset();
1163  }
1164  if (held_move_event_ && held_move_event_->IsMouseEvent()) {
1165    // If a mouse move has been synthesized, the target location is suspect,
1166    // so drop the held event.
1167    if (!synthesize_mouse_move_)
1168      DispatchMouseEventImpl(
1169          static_cast<ui::MouseEvent*>(held_move_event_.get()));
1170    held_move_event_.reset();
1171  } else if (held_move_event_ && held_move_event_->IsTouchEvent()) {
1172    DispatchTouchEventImpl(
1173        static_cast<ui::TouchEvent*>(held_move_event_.get()));
1174    held_move_event_.reset();
1175  }
1176}
1177
1178void RootWindow::PostMouseMoveEventAfterWindowChange() {
1179  if (synthesize_mouse_move_)
1180    return;
1181  synthesize_mouse_move_ = true;
1182  base::MessageLoop::current()->PostTask(
1183      FROM_HERE,
1184      base::Bind(&RootWindow::SynthesizeMouseMoveEvent,
1185                 event_factory_.GetWeakPtr()));
1186}
1187
1188void RootWindow::SynthesizeMouseMoveEvent() {
1189  if (!synthesize_mouse_move_)
1190    return;
1191  synthesize_mouse_move_ = false;
1192  gfx::Point root_mouse_location = GetLastMouseLocationInRoot();
1193  if (!bounds().Contains(root_mouse_location))
1194    return;
1195  gfx::Point host_mouse_location = root_mouse_location;
1196  ConvertPointToHost(&host_mouse_location);
1197
1198  ui::MouseEvent event(ui::ET_MOUSE_MOVED,
1199                       host_mouse_location,
1200                       host_mouse_location,
1201                       ui::EF_IS_SYNTHESIZED);
1202  OnHostMouseEvent(&event);
1203}
1204
1205gfx::Transform RootWindow::GetInverseRootTransform() const {
1206  float scale = ui::GetDeviceScaleFactor(layer());
1207  gfx::Transform transform;
1208  transform.Scale(1.0f / scale, 1.0f / scale);
1209  return transformer_->GetInverseTransform() * transform;
1210}
1211
1212}  // namespace aura
1213