blob: 3254f8f3abca9e8d4365d08aa6f8f9ad228e8b27 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <vector>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/client/capture_delegate.h"
#include "ui/aura/window_tree_host.h"
#include "ui/aura/window_tree_host_delegate.h"
#include "ui/base/cursor/cursor.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_dispatcher.h"
#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/events/gestures/gesture_types.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/transform.h"
namespace gfx {
class Size;
class Transform;
namespace ui {
class GestureEvent;
class GestureRecognizer;
class KeyEvent;
class LayerAnimationSequence;
class MouseEvent;
class ScrollEvent;
class TouchEvent;
class ViewProp;
namespace aura {
class RootWindow;
class RootWindowHost;
class RootWindowObserver;
class RootWindowTransformer;
class TestScreen;
// RootWindow is responsible for hosting a set of windows.
class AURA_EXPORT RootWindow : public ui::EventDispatcherDelegate,
public ui::GestureEventHelper,
public ui::LayerAnimationObserver,
public aura::client::CaptureDelegate,
public aura::RootWindowHostDelegate {
struct AURA_EXPORT CreateParams {
// CreateParams with initial_bounds and default host in pixel.
explicit CreateParams(const gfx::Rect& initial_bounds);
~CreateParams() {}
gfx::Rect initial_bounds;
// A host to use in place of the default one that RootWindow will create.
// NULL by default.
RootWindowHost* host;
explicit RootWindow(const CreateParams& params);
virtual ~RootWindow();
// Returns the RootWindowHost for the specified accelerated widget, or NULL
// if there is none associated.
static RootWindow* GetForAcceleratedWidget(gfx::AcceleratedWidget widget);
Window* window() {
return const_cast<Window*>(const_cast<const RootWindow*>(this)->window());
const Window* window() const { return window_.get(); }
RootWindowHost* host() {
return const_cast<RootWindowHost*>(
const_cast<const RootWindow*>(this)->host());
const RootWindowHost* host() const { return host_.get(); }
ui::Compositor* compositor() { return compositor_.get(); }
gfx::NativeCursor last_cursor() const { return last_cursor_; }
Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
Window* mouse_moved_handler() { return mouse_moved_handler_; }
// Initializes the root window.
void Init();
// Stop listening events in preparation for shutdown.
void PrepareForShutdown();
// Repost event for re-processing. Used when exiting context menus.
// We only support the ET_MOUSE_PRESSED and ET_GESTURE_TAP_DOWN event
// types (although the latter is currently a no-op).
void RepostEvent(const ui::LocatedEvent& event);
RootWindowHostDelegate* AsRootWindowHostDelegate();
// Gets/sets the size of the host window.
void SetHostSize(const gfx::Size& size_in_pixel);
// Sets the bounds of the host window.
void SetHostBounds(const gfx::Rect& size_in_pizel);
// Sets the currently-displayed cursor. If the cursor was previously hidden
// via ShowCursor(false), it will remain hidden until ShowCursor(true) is
// called, at which point the cursor that was last set via SetCursor() will be
// used.
void SetCursor(gfx::NativeCursor cursor);
// Invoked when the cursor's visibility has changed.
void OnCursorVisibilityChanged(bool visible);
// Invoked when the mouse events get enabled or disabled.
void OnMouseEventsEnableStateChanged(bool enabled);
// Moves the cursor to the specified location relative to the root window.
void MoveCursorTo(const gfx::Point& location);
// Moves the cursor to the |host_location| given in host coordinates.
void MoveCursorToHostLocation(const gfx::Point& host_location);
// Draw the damage_rect.
void ScheduleRedrawRect(const gfx::Rect& damage_rect);
// Returns a target window for the given gesture event.
Window* GetGestureTarget(ui::GestureEvent* event);
// Handles a gesture event. Returns true if handled. Unlike the other
// event-dispatching function (e.g. for touch/mouse/keyboard events), gesture
// events are dispatched from GestureRecognizer instead of RootWindowHost.
void DispatchGestureEvent(ui::GestureEvent* event);
// Invoked when |window| is being destroyed.
void OnWindowDestroying(Window* window);
// Invoked when |window|'s bounds have changed. |contained_mouse| indicates if
// the bounds before change contained the |last_moust_location()|.
void OnWindowBoundsChanged(Window* window, bool contained_mouse);
// Dispatches OnMouseExited to the |window| which is hiding if nessessary.
void DispatchMouseExitToHidingWindow(Window* window);
// Dispatches a ui::ET_MOUSE_EXITED event at |point|.
void DispatchMouseExitAtPoint(const gfx::Point& point);
// Invoked when |window|'s visibility has changed.
void OnWindowVisibilityChanged(Window* window, bool is_visible);
// Invoked when |window|'s tranfrom has changed. |contained_mouse|
// indicates if the bounds before change contained the
// |last_moust_location()|.
void OnWindowTransformed(Window* window, bool contained_mouse);
// Invoked when the keyboard mapping (in X11 terms: the mapping between
// keycodes and keysyms) has changed.
void OnKeyboardMappingChanged();
// The system windowing system has sent a request that we close our window.
void OnRootWindowHostCloseRequested();
// Add/remove observer. There is no need to remove the observer if
// the root window is being deleted. In particular, you SHOULD NOT remove
// in |WindowObserver::OnWindowDestroying| of the observer observing
// the root window because it is too late to remove it.
void AddRootWindowObserver(RootWindowObserver* observer);
void RemoveRootWindowObserver(RootWindowObserver* observer);
// Converts |point| from the root window's coordinate system to the
// host window's.
void ConvertPointToHost(gfx::Point* point) const;
// Converts |point| from the host window's coordinate system to the
// root window's.
void ConvertPointFromHost(gfx::Point* point) const;
// Gesture Recognition -------------------------------------------------------
// When a touch event is dispatched to a Window, it may want to process the
// touch event asynchronously. In such cases, the window should consume the
// event during the event dispatch. Once the event is properly processed, the
// window should let the RootWindow know about the result of the event
// processing, so that gesture events can be properly created and dispatched.
void ProcessedTouchEvent(ui::TouchEvent* event,
Window* window,
ui::EventResult result);
// These methods are used to defer the processing of mouse/touch events
// related to resize. A client (typically a RenderWidgetHostViewAura) can call
// HoldPointerMoves when an resize is initiated and then ReleasePointerMoves
// once the resize is completed.
// More than one hold can be invoked and each hold must be cancelled by a
// release before we resume normal operation.
void HoldPointerMoves();
void ReleasePointerMoves();
// Gets the last location seen in a mouse event in this root window's
// coordinates. This may return a point outside the root window's bounds.
gfx::Point GetLastMouseLocationInRoot() const;
void SetRootWindowTransformer(scoped_ptr<RootWindowTransformer> transformer);
gfx::Transform GetRootTransform() const;
void SetTransform(const gfx::Transform& transform);
FRIEND_TEST_ALL_PREFIXES(RootWindowTest, KeepTranslatedEventInRoot);
friend class Window;
friend class TestScreen;
// The parameter for OnWindowHidden() to specify why window is hidden.
enum WindowHiddenReason {
WINDOW_DESTROYED, // Window is destroyed.
WINDOW_HIDDEN, // Window is hidden.
WINDOW_MOVING, // Window is temporarily marked as hidden due to move
// across root windows.
// Updates the event with the appropriate transform for the device scale
// factor. The RootWindowHostDelegate dispatches events in the physical pixel
// coordinate. But the event processing from RootWindow onwards happen in
// device-independent pixel coordinate. So it is necessary to update the event
// received from the host.
void TransformEventForDeviceScaleFactor(ui::LocatedEvent* event);
// Moves the cursor to the specified location. This method is internally used
// by MoveCursorTo() and MoveCursorToHostLocation().
void MoveCursorToInternal(const gfx::Point& root_location,
const gfx::Point& host_location);
// Dispatches the specified event type (intended for enter/exit) to the
// |mouse_moved_handler_|.
ui::EventDispatchDetails DispatchMouseEnterOrExit(
const ui::MouseEvent& event,
ui::EventType type) WARN_UNUSED_RESULT;
ui::EventDispatchDetails ProcessEvent(Window* target,
ui::Event* event) WARN_UNUSED_RESULT;
ui::EventDispatchDetails ProcessGestures(
ui::GestureRecognizer::Gestures* gestures) WARN_UNUSED_RESULT;
// Called when a Window is attached or detached from the RootWindow.
void OnWindowAddedToRootWindow(Window* window);
void OnWindowRemovedFromRootWindow(Window* window, Window* new_root);
// Called when a window becomes invisible, either by being removed
// from root window hierarchy, via SetVisible(false) or being destroyed.
// |reason| specifies what triggered the hiding.
void OnWindowHidden(Window* invisible, WindowHiddenReason reason);
// Cleans up the gesture recognizer for all windows in |window| (including
// |window| itself).
void CleanupGestureRecognizerState(Window* window);
// Updates the root window's size using |host_size|, current
// transform and insets.
void UpdateRootWindowSize(const gfx::Size& host_size);
// Overridden from aura::client::CaptureDelegate:
virtual void UpdateCapture(Window* old_capture, Window* new_capture) OVERRIDE;
virtual void OnOtherRootGotCapture() OVERRIDE;
virtual void SetNativeCapture() OVERRIDE;
virtual void ReleaseNativeCapture() OVERRIDE;
// Overridden from ui::EventDispatcherDelegate.
virtual bool CanDispatchToTarget(ui::EventTarget* target) OVERRIDE;
// Overridden from ui::GestureEventHelper.
virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE;
virtual void DispatchPostponedGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
// Overridden from ui::LayerAnimationObserver:
virtual void OnLayerAnimationEnded(
ui::LayerAnimationSequence* animation) OVERRIDE;
virtual void OnLayerAnimationScheduled(
ui::LayerAnimationSequence* animation) OVERRIDE;
virtual void OnLayerAnimationAborted(
ui::LayerAnimationSequence* animation) OVERRIDE;
// Overridden from aura::RootWindowHostDelegate:
virtual bool OnHostKeyEvent(ui::KeyEvent* event) OVERRIDE;
virtual bool OnHostMouseEvent(ui::MouseEvent* event) OVERRIDE;
virtual bool OnHostScrollEvent(ui::ScrollEvent* event) OVERRIDE;
virtual bool OnHostTouchEvent(ui::TouchEvent* event) OVERRIDE;
virtual void OnHostCancelMode() OVERRIDE;
virtual void OnHostActivated() OVERRIDE;
virtual void OnHostLostWindowCapture() OVERRIDE;
virtual void OnHostLostMouseGrab() OVERRIDE;
virtual void OnHostPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void OnHostMoved(const gfx::Point& origin) OVERRIDE;
virtual void OnHostResized(const gfx::Size& size) OVERRIDE;
virtual float GetDeviceScaleFactor() OVERRIDE;
virtual RootWindow* AsRootWindow() OVERRIDE;
virtual const RootWindow* AsRootWindow() const OVERRIDE;
ui::EventDispatchDetails OnHostMouseEventImpl(ui::MouseEvent* event)
// We hold and aggregate mouse drags and touch moves as a way of throttling
// resizes when HoldMouseMoves() is called. The following methods are used to
// dispatch held and newly incoming mouse and touch events, typically when an
// event other than one of these needs dispatching or a matching
// ReleaseMouseMoves()/ReleaseTouchMoves() is called. NOTE: because these
// methods dispatch events from RootWindowHost the coordinates are in terms of
// the root.
ui::EventDispatchDetails DispatchMouseEventImpl(ui::MouseEvent* event)
ui::EventDispatchDetails DispatchMouseEventRepost(ui::MouseEvent* event)
ui::EventDispatchDetails DispatchMouseEventToTarget(ui::MouseEvent* event,
Window* target)
ui::EventDispatchDetails DispatchTouchEventImpl(ui::TouchEvent* event)
ui::EventDispatchDetails DispatchHeldEvents() WARN_UNUSED_RESULT;
// Creates and dispatches synthesized mouse move event using the
// current mouse location.
ui::EventDispatchDetails SynthesizeMouseMoveEvent() WARN_UNUSED_RESULT;
void DispatchHeldEventsAsync();
void SynthesizeMouseMoveEventAsync();
// Posts a task to send synthesized mouse move event if there
// is no a pending task.
void PostMouseMoveEventAfterWindowChange();
gfx::Transform GetInverseRootTransform() const;
// TODO(beng): evaluate the ideal ownership model.
scoped_ptr<Window> window_;
scoped_ptr<ui::Compositor> compositor_;
scoped_ptr<RootWindowHost> host_;
// Touch ids that are currently down.
uint32 touch_ids_down_;
// Last cursor set. Used for testing.
gfx::NativeCursor last_cursor_;
ObserverList<RootWindowObserver> observers_;
Window* mouse_pressed_handler_;
Window* mouse_moved_handler_;
Window* event_dispatch_target_;
bool synthesize_mouse_move_;
bool waiting_on_compositing_end_;
bool draw_on_compositing_end_;
bool defer_draw_scheduling_;
// How many move holds are outstanding. We try to defer dispatching
// touch/mouse moves while the count is > 0.
int move_hold_count_;
scoped_ptr<ui::LocatedEvent> held_move_event_;
// Allowing for reposting of events. Used when exiting context menus.
scoped_ptr<ui::LocatedEvent> held_repostable_event_;
scoped_ptr<ui::ViewProp> prop_;
scoped_ptr<RootWindowTransformer> transformer_;
// Used to schedule reposting an event.
base::WeakPtrFactory<RootWindow> repost_event_factory_;
// Used to schedule DispatchHeldEvents() when |move_hold_count_| goes to 0.
base::WeakPtrFactory<RootWindow> held_event_factory_;
} // namespace aura