blob: 7cd317b8b3869cc0665b2afd0b5cd640e50f3eb4 [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.
#ifndef UI_AURA_ROOT_WINDOW_H_
#define UI_AURA_ROOT_WINDOW_H_
#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/client/capture_delegate.h"
#include "ui/aura/root_window_host_delegate.h"
#include "ui/aura/window.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/events/event_constants.h"
#include "ui/base/events/event_dispatcher.h"
#include "ui/base/gestures/gesture_recognizer.h"
#include "ui/base/gestures/gesture_types.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
namespace gfx {
class Size;
}
namespace ui {
class GestureEvent;
class GestureRecognizer;
class KeyEvent;
class LayerAnimationSequence;
class MouseEvent;
class ScrollEvent;
class TouchEvent;
class Transform;
}
namespace aura {
class FocusManager;
class RootWindow;
class RootWindowHost;
class RootWindowObserver;
// This class represents a lock on the compositor, that can be used to prevent a
// compositing pass from happening while we're waiting for an asynchronous
// event. The typical use case is when waiting for a renderer to produce a frame
// at the right size. The caller keeps a reference on this object, and drops the
// reference once it desires to release the lock.
// Note however that the lock is canceled after a short timeout to ensure
// responsiveness of the UI, so the compositor tree should be kept in a
// "reasonable" state while the lock is held.
// Don't instantiate this class directly, use RootWindow::GetCompositorLock.
class AURA_EXPORT CompositorLock
: public base::RefCounted<CompositorLock>,
public base::SupportsWeakPtr<CompositorLock> {
private:
friend class base::RefCounted<CompositorLock>;
friend class RootWindow;
explicit CompositorLock(RootWindow* root_window);
~CompositorLock();
void CancelLock();
RootWindow* root_window_;
DISALLOW_COPY_AND_ASSIGN(CompositorLock);
};
// RootWindow is responsible for hosting a set of windows.
class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
public ui::CompositorObserver,
public Window,
public ui::EventDispatcher,
public ui::GestureEventHelper,
public ui::LayerAnimationObserver,
public aura::client::CaptureDelegate,
public aura::RootWindowHostDelegate {
public:
struct AURA_EXPORT CreateParams {
// CreateParams with initial_bounds and default host.
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();
static RootWindow* GetForAcceleratedWidget(gfx::AcceleratedWidget widget);
static void set_hide_host_cursor(bool hide) {
hide_host_cursor_ = hide;
}
static bool hide_host_cursor() {
return hide_host_cursor_;
}
ui::Compositor* compositor() { return compositor_.get(); }
gfx::NativeCursor last_cursor() const { return last_cursor_; }
Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
bool cursor_shown() const { return cursor_shown_; }
void set_focus_manager(FocusManager* focus_manager) {
focus_manager_ = focus_manager;
}
// Initializes the root window.
void Init();
// Shows the root window host.
void ShowRootWindow();
// Hides the root window host.
void HideRootWindow();
RootWindowHostDelegate* AsRootWindowHostDelegate();
// Sets the size of the root window.
void SetHostSize(const gfx::Size& size_in_pixel);
gfx::Size GetHostSize() const;
// Sets the bounds of the host window.
void SetHostBounds(const gfx::Rect& size_in_pixel);
// Returns where the RootWindow is on screen.
gfx::Point GetHostOrigin() const;
// 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);
// Shows or hides the cursor.
void ShowCursor(bool show);
// Moves the cursor to the specified location relative to the root window.
virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE;
// Clips the cursor movement to the root_window.
bool ConfineCursorToWindow();
// Draws the necessary set of windows.
void Draw();
// Draw the whole screen.
void ScheduleFullDraw();
// 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.
bool 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);
// Invoked when |window|'s visibility is 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);
// Posts |native_event| to the platform's event queue.
void PostNativeEvent(const base::NativeEvent& native_event);
// Converts |point| from the root window's coordinate system to native
// screen's.
void ConvertPointToNativeScreen(gfx::Point* point) const;
// Converts |point| from native screen coordinate system to the root window's.
void ConvertPointFromNativeScreen(gfx::Point* point) const;
// Gesture Recognition -------------------------------------------------------
// When a touch event is dispatched to a Window, it can notify the RootWindow
// to queue the touch event for asynchronous gesture recognition. These are
// the entry points for the asynchronous processing of the queued touch
// events.
// Process the next touch event for gesture recognition. |processed| indicates
// whether the queued event was processed by the window or not.
void AdvanceQueuedTouchEvent(Window* window, bool processed);
ui::GestureRecognizer* gesture_recognizer() const {
return gesture_recognizer_.get();
}
// Provided only for testing:
void SetGestureRecognizerForTesting(ui::GestureRecognizer* gr);
// Returns the accelerated widget from the RootWindowHost.
gfx::AcceleratedWidget GetAcceleratedWidget();
// Toggles the host's full screen state.
void ToggleFullScreen();
// These methods are used to defer the processing of mouse events related
// to resize. A client (typically a RenderWidgetHostViewAura) can call
// HoldMouseMoves when an resize is initiated and then ReleaseMouseMoves
// 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 HoldMouseMoves();
void ReleaseMouseMoves();
// Creates a compositor lock.
scoped_refptr<CompositorLock> GetCompositorLock();
// Sets if the window should be focused when shown.
void SetFocusWhenShown(bool focus_when_shown);
// Grabs the snapshot of the root window by using the platform-dependent APIs.
bool GrabSnapshot(const gfx::Rect& snapshot_bounds,
std::vector<unsigned char>* png_representation);
// 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;
// Overridden from Window:
virtual RootWindow* GetRootWindow() OVERRIDE;
virtual const RootWindow* GetRootWindow() const OVERRIDE;
virtual void SetTransform(const ui::Transform& transform) OVERRIDE;
// Overridden from ui::CompositorDelegate:
virtual void ScheduleDraw() OVERRIDE;
// Overridden from ui::CompositorObserver:
virtual void OnCompositingDidCommit(ui::Compositor*) OVERRIDE;
virtual void OnCompositingWillStart(ui::Compositor*) OVERRIDE;
virtual void OnCompositingStarted(ui::Compositor*) OVERRIDE;
virtual void OnCompositingEnded(ui::Compositor*) OVERRIDE;
virtual void OnCompositingAborted(ui::Compositor*) OVERRIDE;
// Overridden from ui::LayerDelegate:
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
// Overridden from Window:
virtual bool CanFocus() const OVERRIDE;
virtual bool CanReceiveEvents() const OVERRIDE;
virtual FocusManager* GetFocusManager() OVERRIDE;
// Overridden from aura::client::CaptureDelegate:
virtual void UpdateCapture(Window* old_capture, Window* new_capture) OVERRIDE;
virtual void SetNativeCapture() OVERRIDE;
virtual void ReleaseNativeCapture() OVERRIDE;
// Exposes RootWindowHost::QueryMouseLocation() for test purposes.
gfx::Point QueryMouseLocationForTest() const;
private:
friend class Window;
friend class CompositorLock;
// Called whenever the mouse moves, tracks the current |mouse_moved_handler_|,
// sending exited and entered events as its value changes.
void HandleMouseMoved(const ui::MouseEvent& event, Window* target);
bool ProcessMouseEvent(Window* target, ui::MouseEvent* event);
bool ProcessKeyEvent(Window* target, ui::KeyEvent* event);
ui::TouchStatus ProcessTouchEvent(Window* target, ui::TouchEvent* event);
ui::EventResult ProcessGestureEvent(Window* target,
ui::GestureEvent* event);
bool ProcessGestures(ui::GestureRecognizer::Gestures* gestures);
// Called when a Window is attached or detached from the RootWindow.
void OnWindowAddedToRootWindow(Window* window);
void OnWindowRemovedFromRootWindow(Window* window);
// Called when a window becomes invisible, either by being removed
// from root window hierachy, via SetVisible(false) or being destroyed.
// |destroyed| is set to true when the window is being destroyed.
void OnWindowHidden(Window* invisible, bool destroyed);
// Cleans up the gesture recognizer for all windows in |window| (including
// |window| itself).
void CleanupGestureRecognizerState(Window* window);
// Overridden from ui::EventDispatcher.
virtual bool CanDispatchToTarget(EventTarget* target) OVERRIDE;
virtual void ProcessPreTargetList(ui::EventHandlerList* list) OVERRIDE;
virtual void ProcessPostTargetList(ui::EventHandlerList* list) OVERRIDE;
// Overridden from ui::GestureEventHelper.
virtual bool DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual bool 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 OnHostLostCapture() OVERRIDE;
virtual void OnHostPaint() 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;
// We hold and aggregate mouse drags as a way of throttling resizes when
// HoldMouseMoves() is called. The following methods are used to dispatch held
// and newly incoming mouse events, typically when an event other than a mouse
// drag needs dispatching or a matching ReleaseMouseMoves() is called.
// NOTE: because these methods dispatch events from RootWindowHost the
// coordinates are in terms of the root.
bool DispatchMouseEventImpl(ui::MouseEvent* event);
bool DispatchMouseEventToTarget(ui::MouseEvent* event, Window* target);
void DispatchHeldMouseMove();
// Parses the switch describing the initial size for the host window and
// returns bounds for the window.
gfx::Rect GetInitialHostWindowBounds() const;
// Posts a task to send synthesized mouse move event if there
// is no a pending task.
void PostMouseMoveEventAfterWindowChange();
// Creates and dispatches synthesized mouse move event using the
// current mouse location.
void SynthesizeMouseMoveEvent();
// Called by CompositorLock.
void UnlockCompositor();
scoped_ptr<ui::Compositor> compositor_;
scoped_ptr<RootWindowHost> host_;
// If set before the RootWindow is created, the cursor will be drawn within
// the Aura root window but hidden outside of it, and it'll remain hidden
// after the Aura window is closed.
static bool hide_host_cursor_;
// Used to schedule painting.
base::WeakPtrFactory<RootWindow> schedule_paint_factory_;
// Use to post mouse move event.
base::WeakPtrFactory<RootWindow> event_factory_;
// ui::EventFlags containing the current state of the mouse buttons.
int mouse_button_flags_;
// Touch ids that are currently down.
uint32 touch_ids_down_;
// Last cursor set. Used for testing.
gfx::NativeCursor last_cursor_;
// Is the cursor currently shown? Used for testing.
bool cursor_shown_;
ObserverList<RootWindowObserver> observers_;
Window* mouse_pressed_handler_;
Window* mouse_moved_handler_;
Window* mouse_event_dispatch_target_;
Window* event_dispatch_target_;
FocusManager* focus_manager_;
// The gesture_recognizer_ for this.
scoped_ptr<ui::GestureRecognizer> gesture_recognizer_;
bool synthesize_mouse_move_;
bool waiting_on_compositing_end_;
bool draw_on_compositing_end_;
bool defer_draw_scheduling_;
// How many holds are outstanding. We try to defer dispatching mouse moves
// while the count is > 0.
int mouse_move_hold_count_;
scoped_ptr<ui::MouseEvent> held_mouse_move_;
// Used to schedule DispatchHeldMouseMove() when |mouse_move_hold_count_| goes
// to 0.
base::WeakPtrFactory<RootWindow> held_mouse_event_factory_;
CompositorLock* compositor_lock_;
bool draw_on_compositor_unlock_;
DISALLOW_COPY_AND_ASSIGN(RootWindow);
};
} // namespace aura
#endif // UI_AURA_ROOT_WINDOW_H_