#include "ash/ash_switches.h"
#include "ash/focus_cycler.h"
-#include "ash/launcher/launcher_delegate.h"
-#include "ash/launcher/launcher_model.h"
#include "ash/root_window_controller.h"
#include "ash/session_state_delegate.h"
+#include "ash/shelf/shelf_constants.h"
+#include "ash/shelf/shelf_delegate.h"
#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_model.h"
#include "ash/shelf/shelf_navigator.h"
#include "ash/shelf/shelf_view.h"
#include "ash/shelf/shelf_widget.h"
#include "ui/views/accessible_pane_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
+#include "ui/wm/public/easy_resize_window_targeter.h"
namespace {
-// Size of black border at bottom (or side) of launcher.
+// Size of black border at bottom (or side) of shelf.
const int kNumBlackPixels = 3;
// Alpha to paint dimming image with.
const int kDimAlpha = 128;
// The time to dim and un-dim.
const int kTimeToDimMs = 3000; // Slow in dimming.
const int kTimeToUnDimMs = 200; // Fast in activating.
-const int kTimeToSwitchBackgroundMs = 1000;
// Class used to slightly dim shelf items when maximized and visible.
class DimmerView : public views::View,
int get_dimming_alpha_for_test() { return alpha_; }
private:
- // This class monitors mouse events to see if it is on top of the launcher.
+ // This class monitors mouse events to see if it is on top of the shelf.
class DimmerEventFilter : public ui::EventHandler {
public:
explicit DimmerEventFilter(DimmerView* owner);
// Make sure it is undimmed at the beginning and then fire off the dimming
// animation.
background_animator_.SetPaintsBackground(false,
- ash::internal::BackgroundAnimator::CHANGE_IMMEDIATE);
+ ash::BACKGROUND_CHANGE_IMMEDIATE);
SetHovered(false);
}
background_animator_.SetDuration(hovered ? kTimeToUnDimMs : kTimeToDimMs);
background_animator_.SetPaintsBackground(!hovered,
disable_dimming_animations_for_test_ ?
- ash::internal::BackgroundAnimator::CHANGE_IMMEDIATE :
- ash::internal::BackgroundAnimator::CHANGE_ANIMATE);
+ ash::BACKGROUND_CHANGE_IMMEDIATE : ash::BACKGROUND_CHANGE_ANIMATE);
}
void DimmerView::ForceUndimming(bool force) {
void DimmerView::OnPaintBackground(gfx::Canvas* canvas) {
SkPaint paint;
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- gfx::ImageSkia launcher_background =
+ gfx::ImageSkia shelf_background =
*rb.GetImageNamed(IDR_AURA_LAUNCHER_DIMMING).ToImageSkia();
if (shelf_->GetAlignment() != ash::SHELF_ALIGNMENT_BOTTOM) {
- launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage(
- launcher_background,
+ shelf_background = gfx::ImageSkiaOperations::CreateRotatedImage(
+ shelf_background,
shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
SkBitmapOperations::ROTATION_90_CW,
SkBitmapOperations::ROTATION_90_CW,
SkBitmapOperations::ROTATION_180_CW));
}
paint.setAlpha(alpha_);
- canvas->DrawImageInt(
- launcher_background,
- 0, 0, launcher_background.width(), launcher_background.height(),
- 0, 0, width(), height(),
- false,
- paint);
+ canvas->DrawImageInt(shelf_background,
+ 0,
+ 0,
+ shelf_background.width(),
+ shelf_background.height(),
+ 0,
+ 0,
+ width(),
+ height(),
+ false,
+ paint);
}
DimmerView::DimmerEventFilter::DimmerEventFilter(DimmerView* owner)
touch_inside_ = touch_inside;
}
+using ash::internal::ShelfLayoutManager;
+
+// ShelfWindowTargeter makes it easier to resize windows with the mouse when the
+// window-edge slightly overlaps with the shelf edge. The targeter also makes it
+// easier to drag the shelf out with touch while it is hidden.
+class ShelfWindowTargeter : public wm::EasyResizeWindowTargeter,
+ public ash::ShelfLayoutManagerObserver {
+ public:
+ ShelfWindowTargeter(aura::Window* container,
+ ShelfLayoutManager* shelf)
+ : wm::EasyResizeWindowTargeter(container, gfx::Insets(), gfx::Insets()),
+ shelf_(shelf) {
+ WillChangeVisibilityState(shelf_->visibility_state());
+ shelf_->AddObserver(this);
+ }
+
+ virtual ~ShelfWindowTargeter() {
+ // |shelf_| may have been destroyed by this time.
+ if (shelf_)
+ shelf_->RemoveObserver(this);
+ }
+
+ private:
+ gfx::Insets GetInsetsForAlignment(int distance,
+ ash::ShelfAlignment alignment) {
+ switch (alignment) {
+ case ash::SHELF_ALIGNMENT_BOTTOM:
+ return gfx::Insets(distance, 0, 0, 0);
+ case ash::SHELF_ALIGNMENT_LEFT:
+ return gfx::Insets(0, 0, 0, distance);
+ case ash::SHELF_ALIGNMENT_RIGHT:
+ return gfx::Insets(0, distance, 0, 0);
+ case ash::SHELF_ALIGNMENT_TOP:
+ return gfx::Insets(0, 0, distance, 0);
+ }
+ NOTREACHED();
+ return gfx::Insets();
+ }
+
+ // ash::ShelfLayoutManagerObserver:
+ virtual void WillDeleteShelf() OVERRIDE {
+ shelf_ = NULL;
+ }
+
+ virtual void WillChangeVisibilityState(
+ ash::ShelfVisibilityState new_state) OVERRIDE {
+ gfx::Insets mouse_insets;
+ gfx::Insets touch_insets;
+ if (new_state == ash::SHELF_VISIBLE) {
+ // Let clicks at the very top of the shelf through so windows can be
+ // resized with the bottom-right corner and bottom edge.
+ mouse_insets = GetInsetsForAlignment(
+ ShelfLayoutManager::kWorkspaceAreaVisibleInset,
+ shelf_->GetAlignment());
+ } else if (new_state == ash::SHELF_AUTO_HIDE) {
+ // Extend the touch hit target out a bit to allow users to drag shelf out
+ // while hidden.
+ touch_insets = GetInsetsForAlignment(
+ -ShelfLayoutManager::kWorkspaceAreaAutoHideInset,
+ shelf_->GetAlignment());
+ }
+
+ set_mouse_extend(mouse_insets);
+ set_touch_extend(touch_insets);
+ }
+
+ ShelfLayoutManager* shelf_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShelfWindowTargeter);
+};
+
} // namespace
namespace ash {
dimmer_->Init(params);
dimmer_->GetNativeWindow()->SetName("ShelfDimmer");
dimmer_->SetBounds(shelf_->GetWindowBoundsInScreen());
- // The launcher should not take focus when it is initially shown.
+ // The shelf should not take focus when it is initially shown.
dimmer_->set_focus_on_creation(false);
dimmer_view_ = new DimmerView(shelf_, disable_dimming_animations_for_test_);
dimmer_->SetContentsView(dimmer_view_);
void ShelfWidget::DelegateView::OnPaintBackground(gfx::Canvas* canvas) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- gfx::ImageSkia launcher_background =
+ gfx::ImageSkia shelf_background =
*rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND);
if (SHELF_ALIGNMENT_BOTTOM != shelf_->GetAlignment())
- launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage(
- launcher_background,
+ shelf_background = gfx::ImageSkiaOperations::CreateRotatedImage(
+ shelf_background,
shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
SkBitmapOperations::ROTATION_90_CW,
SkBitmapOperations::ROTATION_90_CW,
SkBitmapOperations::ROTATION_270_CW,
SkBitmapOperations::ROTATION_180_CW));
-
+ const gfx::Rect dock_bounds(shelf_->shelf_layout_manager()->dock_bounds());
+ SkPaint paint;
+ paint.setAlpha(alpha_);
+ canvas->DrawImageInt(shelf_background,
+ 0,
+ 0,
+ shelf_background.width(),
+ shelf_background.height(),
+ (SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() &&
+ dock_bounds.x() == 0 && dock_bounds.width() > 0)
+ ? dock_bounds.width()
+ : 0,
+ 0,
+ SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment()
+ ? width() - dock_bounds.width()
+ : width(),
+ height(),
+ false,
+ paint);
+ if (SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() &&
+ dock_bounds.width() > 0) {
+ // The part of the shelf background that is in the corner below the docked
+ // windows close to the work area is an arched gradient that blends
+ // vertically oriented docked background and horizontal shelf.
+ gfx::ImageSkia shelf_corner =
+ *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_CORNER);
+ if (dock_bounds.x() == 0) {
+ shelf_corner = gfx::ImageSkiaOperations::CreateRotatedImage(
+ shelf_corner, SkBitmapOperations::ROTATION_90_CW);
+ }
+ canvas->DrawImageInt(
+ shelf_corner,
+ 0,
+ 0,
+ shelf_corner.width(),
+ shelf_corner.height(),
+ dock_bounds.x() > 0 ? dock_bounds.x() : dock_bounds.width() - height(),
+ 0,
+ height(),
+ height(),
+ false,
+ paint);
+ // The part of the shelf background that is just below the docked windows
+ // is drawn using the last (lowest) 1-pixel tall strip of the image asset.
+ // This avoids showing the border 3D shadow between the shelf and the dock.
+ canvas->DrawImageInt(shelf_background,
+ 0,
+ shelf_background.height() - 1,
+ shelf_background.width(),
+ 1,
+ dock_bounds.x() > 0 ? dock_bounds.x() + height() : 0,
+ 0,
+ dock_bounds.width() - height(),
+ height(),
+ false,
+ paint);
+ }
gfx::Rect black_rect =
shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
gfx::Rect(0, height() - kNumBlackPixels, width(), kNumBlackPixels),
gfx::Rect(0, 0, kNumBlackPixels, height()),
gfx::Rect(width() - kNumBlackPixels, 0, kNumBlackPixels, height()),
gfx::Rect(0, 0, width(), kNumBlackPixels));
-
- SkPaint paint;
- paint.setAlpha(alpha_);
- canvas->DrawImageInt(
- launcher_background,
- 0, 0, launcher_background.width(), launcher_background.height(),
- 0, 0, width(), height(),
- false,
- paint);
canvas->FillRect(black_rect, SK_ColorBLACK);
}
aura::Window* status_container,
internal::WorkspaceController* workspace_controller)
: delegate_view_(new DelegateView(this)),
- background_animator_(delegate_view_, 0, kLauncherBackgroundAlpha),
+ background_animator_(delegate_view_, 0, kShelfBackgroundAlpha),
activating_as_fallback_(false),
window_container_(shelf_container) {
views::Widget::InitParams params(
Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_);
shelf_layout_manager_ = new internal::ShelfLayoutManager(this);
+ shelf_layout_manager_->AddObserver(this);
shelf_container->SetLayoutManager(shelf_layout_manager_);
shelf_layout_manager_->set_workspace_controller(workspace_controller);
workspace_controller->SetShelf(shelf_layout_manager_);
status_container->SetLayoutManager(
new internal::StatusAreaLayoutManager(this));
+ shelf_container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(new
+ ShelfWindowTargeter(shelf_container, shelf_layout_manager_)));
+ status_container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(new
+ ShelfWindowTargeter(status_container, shelf_layout_manager_)));
+
views::Widget::AddObserver(this);
}
void ShelfWidget::SetPaintsBackground(
ShelfBackgroundType background_type,
- internal::BackgroundAnimator::ChangeType change_type) {
+ BackgroundAnimatorChangeType change_type) {
ui::Layer* opaque_background = delegate_view_->opaque_background();
float target_opacity =
(background_type == SHELF_BACKGROUND_MAXIMIZED) ? 1.0f : 0.0f;
scoped_ptr<ui::ScopedLayerAnimationSettings> opaque_background_animation;
- if (change_type != internal::BackgroundAnimator::CHANGE_IMMEDIATE) {
+ if (change_type != BACKGROUND_CHANGE_IMMEDIATE) {
opaque_background_animation.reset(new ui::ScopedLayerAnimationSettings(
opaque_background->GetAnimator()));
opaque_background_animation->SetTransitionDuration(
// TODO(mukai): use ui::Layer on both opaque_background and normal background
// retire background_animator_ at all. It would be simpler.
+ // See also DockedBackgroundWidget::SetPaintsBackground.
background_animator_.SetPaintsBackground(
background_type != SHELF_BACKGROUND_DEFAULT,
change_type);
+ delegate_view_->SchedulePaint();
}
ShelfBackgroundType ShelfWidget::GetBackgroundType() const {
}
void ShelfWidget::SetAlignment(ShelfAlignment alignment) {
- if (launcher_)
- launcher_->SetAlignment(alignment);
+ if (shelf_)
+ shelf_->SetAlignment(alignment);
status_area_widget_->SetShelfAlignment(alignment);
delegate_view_->SchedulePaint();
}
delegate_view_->SetDimmed(dimming);
// Repaint all children, allowing updates to reflect dimmed state eg:
// status area background, app list button and overflow button.
- if (launcher_)
- launcher_->SchedulePaint();
+ if (shelf_)
+ shelf_->SchedulePaint();
status_area_widget_->GetContentsView()->SchedulePaint();
}
return delegate_view_->GetDimmed();
}
-void ShelfWidget::CreateLauncher() {
- if (launcher_)
+void ShelfWidget::CreateShelf() {
+ if (shelf_)
return;
Shell* shell = Shell::GetInstance();
- // This needs to be called before launcher_model().
- LauncherDelegate* launcher_delegate = shell->GetLauncherDelegate();
- if (!launcher_delegate)
- return; // Not ready to create Launcher
-
- launcher_.reset(new Launcher(shell->launcher_model(),
- shell->GetLauncherDelegate(),
- this));
+ // This needs to be called before shelf_model().
+ ShelfDelegate* shelf_delegate = shell->GetShelfDelegate();
+ if (!shelf_delegate)
+ return; // Not ready to create Shelf.
+
+ shelf_.reset(
+ new Shelf(shell->shelf_model(), shell->GetShelfDelegate(), this));
SetFocusCycler(shell->focus_cycler());
// Inform the root window controller.
- internal::RootWindowController::ForWindow(window_container_)->
- OnLauncherCreated();
+ internal::RootWindowController::ForWindow(window_container_)
+ ->OnShelfCreated();
- launcher_->SetVisible(
+ shelf_->SetVisible(
shell->session_state_delegate()->IsActiveUserSessionStarted());
shelf_layout_manager_->LayoutShelf();
Show();
}
-bool ShelfWidget::IsLauncherVisible() const {
- return launcher_.get() && launcher_->IsVisible();
+bool ShelfWidget::IsShelfVisible() const {
+ return shelf_.get() && shelf_->IsVisible();
}
-void ShelfWidget::SetLauncherVisibility(bool visible) {
- if (launcher_)
- launcher_->SetVisible(visible);
+void ShelfWidget::SetShelfVisibility(bool visible) {
+ if (shelf_)
+ shelf_->SetVisible(visible);
}
void ShelfWidget::SetFocusCycler(internal::FocusCycler* focus_cycler) {
return delegate_view_->disable_dimming_animations_for_test();
}
+void ShelfWidget::WillDeleteShelf() {
+ shelf_layout_manager_->RemoveObserver(this);
+ shelf_layout_manager_ = NULL;
+}
+
} // namespace ash