summaryrefslogtreecommitdiff
path: root/chromium/ash/shelf/shelf_layout_manager.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/shelf/shelf_layout_manager.h')
-rw-r--r--chromium/ash/shelf/shelf_layout_manager.h415
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_