diff options
Diffstat (limited to 'chromium/ash/shelf/shelf_layout_manager.h')
-rw-r--r-- | chromium/ash/shelf/shelf_layout_manager.h | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/chromium/ash/shelf/shelf_layout_manager.h b/chromium/ash/shelf/shelf_layout_manager.h new file mode 100644 index 00000000000..5d0496b8f9b --- /dev/null +++ b/chromium/ash/shelf/shelf_layout_manager.h @@ -0,0 +1,415 @@ +// 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 ASH_SHELF_SHELF_LAYOUT_MANAGER_H_ +#define ASH_SHELF_SHELF_LAYOUT_MANAGER_H_ + +#include <vector> + +#include "ash/ash_export.h" +#include "ash/launcher/launcher.h" +#include "ash/shelf/background_animator.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shell_observer.h" +#include "ash/system/status_area_widget.h" +#include "ash/wm/dock/docked_window_layout_manager_observer.h" +#include "ash/wm/lock_state_observer.h" +#include "ash/wm/workspace/workspace_types.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/observer_list.h" +#include "base/timer/timer.h" +#include "ui/aura/client/activation_change_observer.h" +#include "ui/aura/layout_manager.h" +#include "ui/gfx/insets.h" +#include "ui/gfx/rect.h" +#include "ui/keyboard/keyboard_controller.h" +#include "ui/keyboard/keyboard_controller_observer.h" + +namespace aura { +class RootWindow; +} + +namespace ui { +class GestureEvent; +class ImplicitAnimationObserver; +} + +namespace ash { +class ScreenAsh; +class ShelfLayoutManagerObserver; +class ShelfWidget; +FORWARD_DECLARE_TEST(WebNotificationTrayTest, PopupAndFullscreen); + +namespace internal { + +class PanelLayoutManagerTest; +class ShelfBezelEventFilter; +class ShelfLayoutManagerTest; +class StatusAreaWidget; +class WorkspaceController; + +// ShelfLayoutManager is the layout manager responsible for the launcher and +// status widgets. The launcher is given the total available width and told the +// width of the status area. This allows the launcher to draw the background and +// layout to the status area. +// To respond to bounds changes in the status area StatusAreaLayoutManager works +// closely with ShelfLayoutManager. +class ASH_EXPORT ShelfLayoutManager : + public aura::LayoutManager, + public ash::ShellObserver, + public aura::client::ActivationChangeObserver, + public DockedWindowLayoutManagerObserver, + public keyboard::KeyboardControllerObserver, + public LockStateObserver { + public: + + // We reserve a small area on the edge of the workspace area to ensure that + // the resize handle at the edge of the window can be hit. + static const int kWorkspaceAreaVisibleInset; + + // When autohidden we extend the touch hit target onto the screen so that the + // user can drag the shelf out. + static const int kWorkspaceAreaAutoHideInset; + + // Size of the shelf when auto-hidden. + static const int kAutoHideSize; + + // The size of the shelf when shown (currently only used in alternate + // settings see ash::switches::UseAlternateShelfLayout). + static const int kShelfSize; + + // Inset between the inner edge of the shelf (towards centre of screen), and + // the launcher items, notifications, status area etc. + static const int kShelfItemInset; + + // Returns the preferred size for the shelf (either kLauncherPreferredSize or + // kShelfSize). + static int GetPreferredShelfSize(); + + explicit ShelfLayoutManager(ShelfWidget* shelf); + virtual ~ShelfLayoutManager(); + + // Sets the ShelfAutoHideBehavior. See enum description for details. + void SetAutoHideBehavior(ShelfAutoHideBehavior behavior); + ShelfAutoHideBehavior auto_hide_behavior() const { + return auto_hide_behavior_; + } + + // Sets the alignment. Returns true if the alignment is changed. Otherwise, + // returns false. + bool SetAlignment(ShelfAlignment alignment); + // Returns the desired alignment for the current state, either the user's + // set alignment (alignment_) or SHELF_ALIGNMENT_BOTTOM when the screen + // is locked. + ShelfAlignment GetAlignment() const; + + void set_workspace_controller(WorkspaceController* controller) { + workspace_controller_ = controller; + } + + bool updating_bounds() const { return updating_bounds_; } + + // Clears internal data for shutdown process. + void PrepareForShutdown(); + + // Returns whether the shelf and its contents (launcher, status) are visible + // on the screen. + bool IsVisible() const; + + // Returns the ideal bounds of the shelf assuming it is visible. + gfx::Rect GetIdealBounds(); + + // Returns the docked area bounds. + const gfx::Rect& dock_bounds() const { return dock_bounds_; } + + // Stops any animations and sets the bounds of the launcher and status + // widgets. + void LayoutShelf(); + + // Returns shelf visibility state based on current value of auto hide + // behavior setting. + ShelfVisibilityState CalculateShelfVisibility(); + + // Updates the visibility state. + void UpdateVisibilityState(); + + // Invoked by the shelf/launcher when the auto-hide state may have changed. + void UpdateAutoHideState(); + + ShelfVisibilityState visibility_state() const { + return state_.visibility_state; + } + ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; } + + ShelfWidget* shelf_widget() { return shelf_; } + + // Sets whether any windows overlap the shelf. If a window overlaps the shelf + // the shelf renders slightly differently. + void SetWindowOverlapsShelf(bool value); + bool window_overlaps_shelf() const { return window_overlaps_shelf_; } + + void AddObserver(ShelfLayoutManagerObserver* observer); + void RemoveObserver(ShelfLayoutManagerObserver* observer); + + // Gesture dragging related functions: + void StartGestureDrag(const ui::GestureEvent& gesture); + enum DragState { + DRAG_SHELF, + DRAG_TRAY + }; + // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf. + // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from + // this point on. + DragState UpdateGestureDrag(const ui::GestureEvent& gesture); + void CompleteGestureDrag(const ui::GestureEvent& gesture); + void CancelGestureDrag(); + + // Overridden from aura::LayoutManager: + virtual void OnWindowResized() OVERRIDE; + virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; + virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; + virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; + virtual void OnChildWindowVisibilityChanged(aura::Window* child, + bool visible) OVERRIDE; + virtual void SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) OVERRIDE; + + // Overridden from ash::ShellObserver: + virtual void OnLockStateChanged(bool locked) OVERRIDE; + + // Overriden from aura::client::ActivationChangeObserver: + virtual void OnWindowActivated(aura::Window* gained_active, + aura::Window* lost_active) OVERRIDE; + + // Overridden from ash::LockStateObserver: + virtual void OnLockStateEvent(LockStateObserver::EventType event) OVERRIDE; + + // TODO(harrym|oshima): These templates will be moved to + // new Shelf class. + // A helper function that provides a shortcut for choosing + // values specific to a shelf alignment. + template<typename T> + T SelectValueForShelfAlignment(T bottom, T left, T right, T top) const { + switch (GetAlignment()) { + case SHELF_ALIGNMENT_BOTTOM: + return bottom; + case SHELF_ALIGNMENT_LEFT: + return left; + case SHELF_ALIGNMENT_RIGHT: + return right; + case SHELF_ALIGNMENT_TOP: + return top; + } + NOTREACHED(); + return right; + } + + template<typename T> + T PrimaryAxisValue(T horizontal, T vertical) const { + return IsHorizontalAlignment() ? horizontal : vertical; + } + + // Is the shelf's alignment horizontal? + bool IsHorizontalAlignment() const; + + // Returns a ShelfLayoutManager on the display which has a launcher for + // given |window|. See RootWindowController::ForLauncher for more info. + static ShelfLayoutManager* ForLauncher(aura::Window* window); + + private: + class AutoHideEventFilter; + class UpdateShelfObserver; + friend class ash::ScreenAsh; + friend class PanelLayoutManagerTest; + friend class ShelfLayoutManagerTest; + FRIEND_TEST_ALL_PREFIXES(ash::WebNotificationTrayTest, PopupAndFullscreen); + + struct TargetBounds { + TargetBounds(); + ~TargetBounds(); + + float opacity; + float status_opacity; + gfx::Rect shelf_bounds_in_root; + gfx::Rect launcher_bounds_in_shelf; + gfx::Rect status_bounds_in_shelf; + gfx::Insets work_area_insets; + }; + + struct State { + State() : visibility_state(SHELF_VISIBLE), + auto_hide_state(SHELF_AUTO_HIDE_HIDDEN), + window_state(WORKSPACE_WINDOW_STATE_DEFAULT), + is_screen_locked(false) {} + + // Returns true if the two states are considered equal. As + // |auto_hide_state| only matters if |visibility_state| is + // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as + // appropriate. + bool Equals(const State& other) const { + return other.visibility_state == visibility_state && + (visibility_state != SHELF_AUTO_HIDE || + other.auto_hide_state == auto_hide_state) && + other.window_state == window_state && + other.is_screen_locked == is_screen_locked; + } + + ShelfVisibilityState visibility_state; + ShelfAutoHideState auto_hide_state; + WorkspaceWindowState window_state; + bool is_screen_locked; + }; + + // Sets the visibility of the shelf to |state|. + void SetState(ShelfVisibilityState visibility_state); + + // Updates the bounds and opacity of the launcher and status widgets. + // If |observer| is specified, it will be called back when the animations, if + // any, are complete. + void UpdateBoundsAndOpacity(const TargetBounds& target_bounds, + bool animate, + ui::ImplicitAnimationObserver* observer); + + // Stops any animations and progresses them to the end. + void StopAnimating(); + + // Returns the width (if aligned to the side) or height (if aligned to the + // bottom). + void GetShelfSize(int* width, int* height); + + // Insets |bounds| by |inset| on the edge the shelf is aligned to. + void AdjustBoundsBasedOnAlignment(int inset, gfx::Rect* bounds) const; + + // Calculates the target bounds assuming visibility of |visible|. + void CalculateTargetBounds(const State& state, TargetBounds* target_bounds); + + // Updates the target bounds if a gesture-drag is in progress. This is only + // used by |CalculateTargetBounds()|. + void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const; + + // Updates the background of the shelf. + void UpdateShelfBackground(BackgroundAnimatorChangeType type); + + // Returns how the shelf background is painted. + ShelfBackgroundType GetShelfBackgroundType() const; + + // Updates the auto hide state immediately. + void UpdateAutoHideStateNow(); + + // Stops the auto hide timer and clears + // |mouse_over_shelf_when_auto_hide_timer_started_|. + void StopAutoHideTimer(); + + // Returns the bounds of an additional region which can trigger showing the + // shelf. This region exists to make it easier to trigger showing the shelf + // when the shelf is auto hidden and the shelf is on the boundary between + // two displays. + gfx::Rect GetAutoHideShowShelfRegionInScreen() const; + + // Returns the AutoHideState. This value is determined from the launcher and + // tray. + ShelfAutoHideState CalculateAutoHideState( + ShelfVisibilityState visibility_state) const; + + // Updates the hit test bounds override for launcher and status area. + void UpdateHitTestBounds(); + + // Returns true if |window| is a descendant of the shelf. + bool IsShelfWindow(aura::Window* window); + + int GetWorkAreaSize(const State& state, int size) const; + + // Return the bounds available in the parent, taking into account the bounds + // of the keyboard if necessary. + gfx::Rect GetAvailableBounds() const; + + // Overridden from keyboard::KeyboardControllerObserver: + virtual void OnKeyboardBoundsChanging( + const gfx::Rect& keyboard_bounds) OVERRIDE; + + // Overridden from DockedWindowLayoutManagerObserver: + virtual void OnDockBoundsChanging( + const gfx::Rect& dock_bounds, + DockedWindowLayoutManagerObserver::Reason reason) OVERRIDE; + + // Generates insets for inward edge based on the current shelf alignment. + gfx::Insets GetInsetsForAlignment(int distance) const; + + // The RootWindow is cached so that we don't invoke Shell::GetInstance() from + // our destructor. We avoid that as at the time we're deleted Shell is being + // deleted too. + aura::Window* root_window_; + + // True when inside UpdateBoundsAndOpacity() method. Used to prevent calling + // UpdateBoundsAndOpacity() again from SetChildBounds(). + bool updating_bounds_; + + // See description above setter. + ShelfAutoHideBehavior auto_hide_behavior_; + + // See description above getter. + ShelfAlignment alignment_; + + // Current state. + State state_; + + ShelfWidget* shelf_; + + WorkspaceController* workspace_controller_; + + // Do any windows overlap the shelf? This is maintained by WorkspaceManager. + bool window_overlaps_shelf_; + + base::OneShotTimer<ShelfLayoutManager> auto_hide_timer_; + + // Whether the mouse was over the shelf when the auto hide timer started. + // False when neither the auto hide timer nor the timer task are running. + bool mouse_over_shelf_when_auto_hide_timer_started_; + + // EventFilter used to detect when user moves the mouse over the launcher to + // trigger showing the launcher. + scoped_ptr<AutoHideEventFilter> auto_hide_event_filter_; + + // EventFilter used to detect when user issues a gesture on a bezel sensor. + scoped_ptr<ShelfBezelEventFilter> bezel_event_filter_; + + ObserverList<ShelfLayoutManagerObserver> observers_; + + // The shelf reacts to gesture-drags, and can be set to auto-hide for certain + // gestures. Some shelf behaviour (e.g. visibility state, background color + // etc.) are affected by various stages of the drag. The enum keeps track of + // the present status of the gesture drag. + enum GestureDragStatus { + GESTURE_DRAG_NONE, + GESTURE_DRAG_IN_PROGRESS, + GESTURE_DRAG_CANCEL_IN_PROGRESS, + GESTURE_DRAG_COMPLETE_IN_PROGRESS + }; + GestureDragStatus gesture_drag_status_; + + // Tracks the amount of the drag. The value is only valid when + // |gesture_drag_status_| is set to GESTURE_DRAG_IN_PROGRESS. + float gesture_drag_amount_; + + // Manage the auto-hide state during the gesture. + ShelfAutoHideState gesture_drag_auto_hide_state_; + + // Used to delay updating shelf background. + UpdateShelfObserver* update_shelf_observer_; + + // The bounds of the keyboard. + gfx::Rect keyboard_bounds_; + + // The bounds of the dock. + gfx::Rect dock_bounds_; + + DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_SHELF_SHELF_LAYOUT_MANAGER_H_ |