Index: ash/wm/panel_layout_manager.cc |
diff --git a/ash/wm/panel_layout_manager.cc b/ash/wm/panel_layout_manager.cc |
index 4080a4e044312ff1feb57b64ccb6d16bf3436a21..1dd770173870e38af7dec1f10742a1e4b59c0590 100644 |
--- a/ash/wm/panel_layout_manager.cc |
+++ b/ash/wm/panel_layout_manager.cc |
@@ -10,14 +10,22 @@ |
#include "ash/shell.h" |
#include "ash/wm/property_util.h" |
#include "base/auto_reset.h" |
+#include "third_party/skia/include/core/SkCanvas.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 +34,38 @@ 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{ |
sky
2012/04/26 15:41:16
nit: space after Background
dcheng
2012/04/27 01:11:35
Done.
|
+ 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)); |
+ |
+ // TODO(dcheng): get real colors, and port this over to use gfx::Canvas |
+ // instead. |
+ SkPaint paint; |
+ paint.setStyle(SkPaint::kFill_Style); |
+ paint.setColor(SK_ColorBLUE); |
+ canvas->sk_canvas()->drawPath(path, paint); |
+ |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ paint.setColor(SK_ColorRED); |
+ canvas->sk_canvas()->drawPath(path, paint); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(CalloutWidgetBackground); |
+}; |
+ |
+} // namespace |
//////////////////////////////////////////////////////////////////////////////// |
// PanelLayoutManager public implementation: |
@@ -38,8 +74,25 @@ 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) { |
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); |
} |
@@ -100,6 +153,8 @@ void PanelLayoutManager::OnWindowResized() { |
} |
void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { |
+ if (child == callout_widget_->GetNativeWindow()) |
+ return; |
panel_windows_.push_back(child); |
Relayout(); |
} |
@@ -174,8 +229,10 @@ 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); |
+ } |
} |
} |
@@ -219,11 +276,15 @@ 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()); |
+ // TODO(dcheng): This is just a random constant so panels don't sit right |
+ // on top of the launcher. We should be using the same padding that normal |
+ // windows use. |
+ bounds.set_y(icon_origin.y() - bounds.height() - 10); |
sky
2012/04/26 15:41:16
Normal windows can sit flush to the launcher.
dcheng
2012/04/27 01:11:35
Right now, we're lining things up to the top of th
|
SetChildBoundsDirect(panel, bounds); |
} |
UpdateStacking(active_panel); |
+ UpdateCallout(active_panel); |
sky
2012/04/26 15:41:16
UpdateStacking might use last_active_panel_, does
dcheng
2012/04/27 01:11:35
No, we only want to decorate a panel with the call
|
} |
void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { |
@@ -270,5 +331,20 @@ void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { |
last_active_panel_ = active_panel; |
} |
+void PanelLayoutManager::UpdateCallout(aura::Window* active_panel) { |
+ if (!active_panel) { |
+ callout_widget_->Hide(); |
+ return; |
+ } |
+ 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); |
+ callout_widget_->Show(); |
+ panel_container_->StackChildAtTop(callout_widget_->GetNativeWindow()); |
sky
2012/04/26 15:41:16
I would stack at top first, then show.
dcheng
2012/04/27 01:11:35
Done.
|
+} |
+ |
} // namespace internal |
} // namespace ash |