| Index: ash/wm/panel_layout_manager.cc
|
| diff --git a/ash/wm/panel_layout_manager.cc b/ash/wm/panel_layout_manager.cc
|
| index 997271d5bc686c06c6caf471a47cc493721f82f9..f97d614c633186f15c47434a960f574c5903a62d 100644
|
| --- a/ash/wm/panel_layout_manager.cc
|
| +++ b/ash/wm/panel_layout_manager.cc
|
| @@ -8,16 +8,26 @@
|
|
|
| #include "ash/launcher/launcher.h"
|
| #include "ash/shell.h"
|
| +#include "ash/wm/frame_painter.h"
|
| #include "ash/wm/property_util.h"
|
| #include "base/auto_reset.h"
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "third_party/skia/include/core/SkColor.h"
|
| +#include "third_party/skia/include/core/SkPaint.h"
|
| +#include "third_party/skia/include/core/SkPath.h"
|
| #include "ui/aura/client/activation_client.h"
|
| #include "ui/aura/client/aura_constants.h"
|
| #include "ui/aura/root_window.h"
|
| #include "ui/aura/window.h"
|
| +#include "ui/gfx/canvas.h"
|
| #include "ui/gfx/rect.h"
|
| -#include "ui/gfx/size.h"
|
| +#include "ui/views/background.h"
|
| #include "ui/views/widget/widget.h"
|
|
|
| +namespace ash {
|
| +namespace internal {
|
| +
|
| namespace {
|
| const int kPanelMarginEdge = 4;
|
| const int kPanelMarginMiddle = 8;
|
| @@ -26,10 +36,34 @@ const int kMinimizedHeight = 24;
|
|
|
| const float kMaxHeightFactor = .80f;
|
| const float kMaxWidthFactor = .50f;
|
| -}
|
|
|
| -namespace ash {
|
| -namespace internal {
|
| +// Callout arrow dimensions.
|
| +const int kArrowWidth = 20;
|
| +const int kArrowHeight = 10;
|
| +
|
| +class CalloutWidgetBackground : public views::Background {
|
| + public:
|
| + CalloutWidgetBackground() {}
|
| + virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE {
|
| + SkPath path;
|
| + // TODO(dcheng): Verify if this results in off by one errors.
|
| + path.moveTo(SkIntToScalar(0), SkIntToScalar(0));
|
| + path.lineTo(SkIntToScalar(kArrowWidth / 2), SkIntToScalar(kArrowHeight));
|
| + path.lineTo(SkIntToScalar(kArrowWidth), SkIntToScalar(0));
|
| +
|
| + // Use the same opacity and colors as the header for now.
|
| + SkPaint paint;
|
| + paint.setStyle(SkPaint::kFill_Style);
|
| + paint.setColor(
|
| + SkColorSetARGB(FramePainter::kActiveWindowOpacity, 189, 189, 189));
|
| + canvas->DrawPath(path, paint);
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(CalloutWidgetBackground);
|
| +};
|
| +
|
| +} // namespace
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // PanelLayoutManager public implementation:
|
| @@ -38,8 +72,26 @@ PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container)
|
| in_layout_(false),
|
| dragged_panel_(NULL),
|
| launcher_(NULL),
|
| - last_active_panel_(NULL) {
|
| + last_active_panel_(NULL),
|
| + callout_widget_(new views::Widget),
|
| + weak_factory_(this) {
|
| DCHECK(panel_container);
|
| + views::Widget::InitParams params;
|
| + params.type = views::Widget::InitParams::TYPE_POPUP;
|
| + params.transparent = true;
|
| + params.can_activate = false;
|
| + params.keep_on_top = true;
|
| + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
| + params.parent = panel_container_;
|
| + params.bounds.set_width(kArrowWidth);
|
| + params.bounds.set_height(kArrowHeight);
|
| + // Why do we need this and can_activate = false?
|
| + callout_widget_->set_focus_on_creation(false);
|
| + callout_widget_->Init(params);
|
| + views::View* content_view = new views::View;
|
| + content_view->set_background(new CalloutWidgetBackground);
|
| + callout_widget_->SetContentsView(content_view);
|
| + callout_widget_->Show();
|
| Shell::GetRootWindow()->AddObserver(this);
|
| }
|
|
|
| @@ -101,6 +153,8 @@ void PanelLayoutManager::OnWindowResized() {
|
| }
|
|
|
| void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
|
| + if (child == callout_widget_->GetNativeWindow())
|
| + return;
|
| panel_windows_.push_back(child);
|
| Relayout();
|
| }
|
| @@ -175,8 +229,12 @@ void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window,
|
| if (key == aura::client::kRootWindowActiveWindowKey) {
|
| aura::Window* active = window->GetProperty(
|
| aura::client::kRootWindowActiveWindowKey);
|
| - if (active && active->type() == aura::client::WINDOW_TYPE_PANEL)
|
| + if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) {
|
| UpdateStacking(active);
|
| + UpdateCallout(active);
|
| + } else {
|
| + UpdateCallout(NULL);
|
| + }
|
| }
|
| }
|
|
|
| @@ -188,6 +246,7 @@ void PanelLayoutManager::Relayout() {
|
| return;
|
| AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
|
|
|
| + int launcher_top = launcher_->widget()->GetWindowScreenBounds().y();
|
| aura::Window* active_panel = NULL;
|
| for (PanelList::iterator iter = panel_windows_.begin();
|
| iter != panel_windows_.end(); ++iter) {
|
| @@ -218,11 +277,12 @@ void PanelLayoutManager::Relayout() {
|
| gfx::Rect bounds = panel->bounds();
|
| bounds.set_x(
|
| icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2);
|
| - bounds.set_y(icon_origin.y() - bounds.height());
|
| + bounds.set_y(launcher_top - bounds.height());
|
| SetChildBoundsDirect(panel, bounds);
|
| }
|
|
|
| UpdateStacking(active_panel);
|
| + UpdateCallout(active_panel);
|
| }
|
|
|
| void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) {
|
| @@ -271,5 +331,35 @@ void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) {
|
| last_active_panel_ = active_panel;
|
| }
|
|
|
| +void PanelLayoutManager::UpdateCallout(aura::Window* active_panel) {
|
| + weak_factory_.InvalidateWeakPtrs();
|
| + // TODO(dcheng): This doesn't account for panels in overflow. They should have
|
| + // a callout as well.
|
| + // This also doesn't work well for windows that are TYPE_PANEL but don't get
|
| + // added to the list of panel_windows_ for whatever reason.
|
| + if (!active_panel ||
|
| + launcher_->GetScreenBoundsOfItemIconForWindow(active_panel).IsEmpty()) {
|
| + callout_widget_->Hide();
|
| + return;
|
| + }
|
| + MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&PanelLayoutManager::ShowCalloutHelper,
|
| + weak_factory_.GetWeakPtr(),
|
| + active_panel));
|
| +}
|
| +
|
| +void PanelLayoutManager::ShowCalloutHelper(aura::Window* active_panel) {
|
| + DCHECK(active_panel);
|
| + gfx::Rect bounds = active_panel->GetBoundsInRootWindow();
|
| + gfx::Rect callout_bounds = callout_widget_->GetWindowScreenBounds();
|
| + callout_bounds.set_x(
|
| + bounds.x() + (bounds.width() - callout_bounds.width()) / 2);
|
| + callout_bounds.set_y(bounds.bottom());
|
| + SetChildBoundsDirect(callout_widget_->GetNativeWindow(), callout_bounds);
|
| + panel_container_->StackChildAtTop(callout_widget_->GetNativeWindow());
|
| + callout_widget_->Show();
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace ash
|
|
|