summaryrefslogtreecommitdiffstats
path: root/mash
diff options
context:
space:
mode:
authorsky <sky@chromium.org>2015-11-18 18:42:05 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-19 02:42:46 +0000
commitafeecbf9c6549bdfb0e00492d206f47a3088b40f (patch)
treec19dcf2c2d2ffe18da87be55b7febf2cccb55a9c /mash
parent42ef946ac829db450d131ad06a399a85f9fe207f (diff)
downloadchromium_src-afeecbf9c6549bdfb0e00492d206f47a3088b40f.zip
chromium_src-afeecbf9c6549bdfb0e00492d206f47a3088b40f.tar.gz
chromium_src-afeecbf9c6549bdfb0e00492d206f47a3088b40f.tar.bz2
Gets mustash frames looking like that of ash
This is basically a fork of various portions of ash frame code. I left parts we have no support for yet out, but kept some things that we'll need to support eventually. BUG=548426 TEST=none R=ben@chromium.org Review URL: https://codereview.chromium.org/1459653002 Cr-Commit-Position: refs/heads/master@{#360501}
Diffstat (limited to 'mash')
-rw-r--r--mash/wm/BUILD.gn51
-rw-r--r--mash/wm/DEPS3
-rw-r--r--mash/wm/frame/caption_buttons/caption_button_types.h27
-rw-r--r--mash/wm/frame/caption_buttons/frame_caption_button.cc195
-rw-r--r--mash/wm/frame/caption_buttons/frame_caption_button.h102
-rw-r--r--mash/wm/frame/caption_buttons/frame_caption_button_container_view.cc353
-rw-r--r--mash/wm/frame/caption_buttons/frame_caption_button_container_view.h135
-rw-r--r--mash/wm/frame/default_header_painter.cc352
-rw-r--r--mash/wm/frame/default_header_painter.h122
-rw-r--r--mash/wm/frame/frame_border_hit_test_controller.cc82
-rw-r--r--mash/wm/frame/frame_border_hit_test_controller.h40
-rw-r--r--mash/wm/frame/header_painter.h52
-rw-r--r--mash/wm/frame/header_painter_util.cc80
-rw-r--r--mash/wm/frame/header_painter_util.h56
-rw-r--r--mash/wm/frame/move_loop.cc (renamed from mash/wm/move_loop.cc)8
-rw-r--r--mash/wm/frame/move_loop.h (renamed from mash/wm/move_loop.h)12
-rw-r--r--mash/wm/frame/move_loop_unittest.cc (renamed from mash/wm/move_loop_unittest.cc)8
-rw-r--r--mash/wm/frame/non_client_frame_view_mash.cc351
-rw-r--r--mash/wm/frame/non_client_frame_view_mash.h107
-rw-r--r--mash/wm/non_client_frame_controller.cc14
-rw-r--r--mash/wm/non_client_frame_controller.h7
-rw-r--r--mash/wm/non_client_frame_view_impl.cc101
-rw-r--r--mash/wm/non_client_frame_view_impl.h49
-rw-r--r--mash/wm/window_manager_application.cc2
-rw-r--r--mash/wm/window_manager_impl.cc17
25 files changed, 2147 insertions, 179 deletions
diff --git a/mash/wm/BUILD.gn b/mash/wm/BUILD.gn
index 373ef7a..fc8d2e86 100644
--- a/mash/wm/BUILD.gn
+++ b/mash/wm/BUILD.gn
@@ -5,6 +5,7 @@
import("//build/config/ui.gni")
import("//mojo/public/mojo_application.gni")
import("//mojo/public/tools/bindings/mojom.gni")
+import("//tools/grit/repack.gni")
group("wm") {
testonly = true
@@ -18,14 +19,26 @@ source_set("example_wm_lib") {
sources = [
"background_layout.cc",
"background_layout.h",
+ "frame/caption_buttons/caption_button_types.h",
+ "frame/caption_buttons/frame_caption_button.cc",
+ "frame/caption_buttons/frame_caption_button.h",
+ "frame/caption_buttons/frame_caption_button_container_view.cc",
+ "frame/caption_buttons/frame_caption_button_container_view.h",
+ "frame/default_header_painter.cc",
+ "frame/default_header_painter.h",
+ "frame/frame_border_hit_test_controller.cc",
+ "frame/frame_border_hit_test_controller.h",
+ "frame/header_painter.h",
+ "frame/header_painter_util.cc",
+ "frame/header_painter_util.h",
+ "frame/move_loop.cc",
+ "frame/move_loop.h",
+ "frame/non_client_frame_view_mash.cc",
+ "frame/non_client_frame_view_mash.h",
"layout_manager.cc",
"layout_manager.h",
- "move_loop.cc",
- "move_loop.h",
"non_client_frame_controller.cc",
"non_client_frame_controller.h",
- "non_client_frame_view_impl.cc",
- "non_client_frame_view_impl.h",
"property_util.cc",
"property_util.h",
"shelf_layout.cc",
@@ -44,13 +57,19 @@ source_set("example_wm_lib") {
"//components/mus/public/cpp",
"//components/mus/public/interfaces",
"//mash/wm/public/interfaces",
+ "//mash/wm/resources",
"//mojo/application/public/cpp",
"//mojo/common:common_base",
"//mojo/converters/geometry",
"//mojo/converters/input_events",
"//mojo/services/tracing/public/cpp",
"//skia",
+ "//ui/aura",
+ "//ui/events",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
"//ui/mojo/init",
+ "//ui/strings",
"//ui/views",
"//ui/views/mus:for_mojo_application",
]
@@ -63,15 +82,33 @@ mojo_native_application("example_wm") {
deps = [
":example_wm_lib",
+ ":resources",
"//mojo/application/public/cpp",
- "//ui/views/mus:resources",
]
data_deps = [
"//components/mus",
]
- resources = [ "$root_out_dir/views_mus_resources.pak" ]
+ resources = [ "$root_out_dir/mash_wm_resources.pak" ]
+}
+
+repack("resources") {
+ sources = [
+ "$root_gen_dir/mash/wm/resources/mash_wm_resources_100_percent.pak",
+ "$root_gen_dir/ui/resources/ui_resources_100_percent.pak",
+ "$root_gen_dir/ui/strings/app_locale_settings_en-US.pak",
+ "$root_gen_dir/ui/strings/ui_strings_en-US.pak",
+ "$root_gen_dir/ui/views/resources/views_resources_100_percent.pak",
+ ]
+ output = "$root_out_dir/mash_wm_resources.pak"
+ deps = [
+ "//mash/wm/resources",
+ "//ui/resources",
+ "//ui/strings",
+ "//ui/views/mus:resources",
+ "//ui/views/resources",
+ ]
}
mojo_native_application("apptests") {
@@ -105,7 +142,7 @@ source_set("unittests") {
testonly = true
sources = [
- "move_loop_unittest.cc",
+ "frame/move_loop_unittest.cc",
]
deps = [
diff --git a/mash/wm/DEPS b/mash/wm/DEPS
new file mode 100644
index 0000000..810a46a
--- /dev/null
+++ b/mash/wm/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+grit/mash_wm_resources.h",
+]
diff --git a/mash/wm/frame/caption_buttons/caption_button_types.h b/mash/wm/frame/caption_buttons/caption_button_types.h
new file mode 100644
index 0000000..3bda201
--- /dev/null
+++ b/mash/wm/frame/caption_buttons/caption_button_types.h
@@ -0,0 +1,27 @@
+// Copyright 2015 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 MASH_WM_FRAME_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_
+#define MASH_WM_FRAME_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_
+
+namespace mash {
+namespace wm {
+
+// These are the icon types that a caption button can have. The size button's
+// action (SnapType) can be different from its icon.
+enum CaptionButtonIcon {
+ CAPTION_BUTTON_ICON_MINIMIZE,
+ CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
+ CAPTION_BUTTON_ICON_CLOSE,
+ CAPTION_BUTTON_ICON_LEFT_SNAPPED,
+ CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
+ CAPTION_BUTTON_ICON_BACK,
+ CAPTION_BUTTON_ICON_LOCATION,
+ CAPTION_BUTTON_ICON_COUNT
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_
diff --git a/mash/wm/frame/caption_buttons/frame_caption_button.cc b/mash/wm/frame/caption_buttons/frame_caption_button.cc
new file mode 100644
index 0000000..ca1501f
--- /dev/null
+++ b/mash/wm/frame/caption_buttons/frame_caption_button.cc
@@ -0,0 +1,195 @@
+// Copyright 2015 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.
+
+#include "mash/wm/frame/caption_buttons/frame_caption_button.h"
+
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/animation/throb_animation.h"
+#include "ui/gfx/canvas.h"
+
+namespace mash {
+namespace wm {
+
+namespace {
+
+// The duration of the crossfade animation when swapping the button's images.
+const int kSwapImagesAnimationDurationMs = 200;
+
+// The duration of the fade out animation of the old icon during a crossfade
+// animation as a ratio of |kSwapImagesAnimationDurationMs|.
+const float kFadeOutRatio = 0.5f;
+
+// The alpha to draw inactive icons with.
+const float kInactiveIconAlpha = 0.2f;
+
+} // namespace
+
+// static
+const char FrameCaptionButton::kViewClassName[] = "FrameCaptionButton";
+
+FrameCaptionButton::FrameCaptionButton(views::ButtonListener* listener,
+ CaptionButtonIcon icon)
+ : CustomButton(listener),
+ icon_(icon),
+ paint_as_active_(false),
+ alpha_(255),
+ icon_image_id_(-1),
+ hovered_background_image_id_(-1),
+ pressed_background_image_id_(-1),
+ swap_images_animation_(new gfx::SlideAnimation(this)) {
+ swap_images_animation_->Reset(1);
+
+ // Do not flip the gfx::Canvas passed to the OnPaint() method. The snap left
+ // and snap right button icons should not be flipped. The other icons are
+ // horizontally symmetrical.
+}
+
+FrameCaptionButton::~FrameCaptionButton() {}
+
+void FrameCaptionButton::SetImages(CaptionButtonIcon icon,
+ Animate animate,
+ int icon_image_id,
+ int hovered_background_image_id,
+ int pressed_background_image_id) {
+ // The early return is dependant on |animate| because callers use SetImages()
+ // with ANIMATE_NO to progress the crossfade animation to the end.
+ if (icon == icon_ &&
+ (animate == ANIMATE_YES || !swap_images_animation_->is_animating()) &&
+ icon_image_id == icon_image_id_ &&
+ hovered_background_image_id == hovered_background_image_id_ &&
+ pressed_background_image_id == pressed_background_image_id_) {
+ return;
+ }
+
+ if (animate == ANIMATE_YES)
+ crossfade_icon_image_ = icon_image_;
+
+ icon_ = icon;
+ icon_image_id_ = icon_image_id;
+ // TODO(sky): it doesn't seem like these are used.
+ hovered_background_image_id_ = hovered_background_image_id;
+ pressed_background_image_id_ = pressed_background_image_id;
+
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ icon_image_ = *rb.GetImageSkiaNamed(icon_image_id);
+ hovered_background_image_ =
+ *rb.GetImageSkiaNamed(hovered_background_image_id);
+ pressed_background_image_ =
+ *rb.GetImageSkiaNamed(pressed_background_image_id);
+
+ if (animate == ANIMATE_YES) {
+ swap_images_animation_->Reset(0);
+ swap_images_animation_->SetSlideDuration(kSwapImagesAnimationDurationMs);
+ swap_images_animation_->Show();
+ } else {
+ swap_images_animation_->Reset(1);
+ }
+ PreferredSizeChanged();
+ SchedulePaint();
+}
+
+bool FrameCaptionButton::IsAnimatingImageSwap() const {
+ return swap_images_animation_->is_animating();
+}
+
+void FrameCaptionButton::SetAlpha(int alpha) {
+ if (alpha_ != alpha) {
+ alpha_ = alpha;
+ SchedulePaint();
+ }
+}
+
+gfx::Size FrameCaptionButton::GetPreferredSize() const {
+ return hovered_background_image_.isNull() ? gfx::Size()
+ : hovered_background_image_.size();
+}
+
+const char* FrameCaptionButton::GetClassName() const {
+ return kViewClassName;
+}
+
+void FrameCaptionButton::OnPaint(gfx::Canvas* canvas) {
+ if (hover_animation_->is_animating() || state() == STATE_HOVERED) {
+ int hovered_background_alpha =
+ hover_animation_->is_animating()
+ ? hover_animation_->CurrentValueBetween(0, 255)
+ : 255;
+ SkPaint paint;
+ paint.setAlpha(hovered_background_alpha);
+ canvas->DrawImageInt(hovered_background_image_, 0, 0, paint);
+ } else if (state() == STATE_PRESSED) {
+ canvas->DrawImageInt(pressed_background_image_, 0, 0);
+ }
+
+ int icon_alpha = swap_images_animation_->CurrentValueBetween(0, 255);
+ int crossfade_icon_alpha = 0;
+ if (icon_alpha < static_cast<int>(kFadeOutRatio * 255))
+ crossfade_icon_alpha = static_cast<int>(255 - icon_alpha / kFadeOutRatio);
+
+ if (crossfade_icon_alpha > 0 && !crossfade_icon_image_.isNull()) {
+ gfx::Canvas icon_canvas(icon_image_.size(), canvas->image_scale(), false);
+ SkPaint paint;
+ paint.setAlpha(icon_alpha);
+ icon_canvas.DrawImageInt(icon_image_, 0, 0, paint);
+
+ paint.setAlpha(crossfade_icon_alpha);
+ paint.setXfermodeMode(SkXfermode::kPlus_Mode);
+ icon_canvas.DrawImageInt(crossfade_icon_image_, 0, 0, paint);
+
+ PaintCentered(canvas, gfx::ImageSkia(icon_canvas.ExtractImageRep()),
+ alpha_);
+ } else {
+ if (!swap_images_animation_->is_animating())
+ icon_alpha = alpha_;
+ PaintCentered(canvas, icon_image_, icon_alpha);
+ }
+}
+
+void FrameCaptionButton::OnGestureEvent(ui::GestureEvent* event) {
+ // CustomButton does not become pressed when the user drags off and then back
+ // onto the button. Make FrameCaptionButton pressed in this case because this
+ // behavior is more consistent with AlternateFrameSizeButton.
+ if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
+ event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
+ if (HitTestPoint(event->location())) {
+ SetState(STATE_PRESSED);
+ RequestFocus();
+ event->StopPropagation();
+ } else {
+ SetState(STATE_NORMAL);
+ }
+ } else if (event->type() == ui::ET_GESTURE_SCROLL_END) {
+ if (HitTestPoint(event->location())) {
+ SetState(STATE_HOVERED);
+ NotifyClick(*event);
+ event->StopPropagation();
+ }
+ }
+ CustomButton::OnGestureEvent(event);
+}
+
+void FrameCaptionButton::PaintCentered(gfx::Canvas* canvas,
+ const gfx::ImageSkia& to_center,
+ int alpha) {
+ if (!paint_as_active_) {
+ // Paint icons as active when they are hovered over or pressed.
+ double inactive_alpha = kInactiveIconAlpha;
+ if (hover_animation_->is_animating()) {
+ inactive_alpha =
+ hover_animation_->CurrentValueBetween(inactive_alpha, 1.0f);
+ } else if (state() == STATE_PRESSED || state() == STATE_HOVERED) {
+ inactive_alpha = 1.0f;
+ }
+ alpha *= inactive_alpha;
+ }
+
+ SkPaint paint;
+ paint.setAlpha(alpha);
+ canvas->DrawImageInt(to_center, (width() - to_center.width()) / 2,
+ (height() - to_center.height()) / 2, paint);
+}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/frame/caption_buttons/frame_caption_button.h b/mash/wm/frame/caption_buttons/frame_caption_button.h
new file mode 100644
index 0000000..6708327
--- /dev/null
+++ b/mash/wm/frame/caption_buttons/frame_caption_button.h
@@ -0,0 +1,102 @@
+// Copyright 2015 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 MASH_WM_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_
+#define MASH_WM_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "mash/wm/frame/caption_buttons/caption_button_types.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/views/controls/button/custom_button.h"
+
+namespace gfx {
+class SlideAnimation;
+}
+
+namespace mash {
+namespace wm {
+
+// Base class for the window caption buttons (minimize, maximize, restore,
+// close).
+class FrameCaptionButton : public views::CustomButton {
+ public:
+ enum Animate { ANIMATE_YES, ANIMATE_NO };
+
+ static const char kViewClassName[];
+
+ FrameCaptionButton(views::ButtonListener* listener, CaptionButtonIcon icon);
+ ~FrameCaptionButton() override;
+
+ // Sets the images to use to paint the button. If |animate| is ANIMATE_YES,
+ // the button crossfades to the new visuals. If the image ids match those
+ // currently used by the button and |animate| is ANIMATE_NO the crossfade
+ // animation is progressed to the end.
+ void SetImages(CaptionButtonIcon icon,
+ Animate animate,
+ int icon_image_id,
+ int hovered_background_image_id,
+ int pressed_background_image_id);
+
+ // Returns true if the button is crossfading to new visuals set in
+ // SetImages().
+ bool IsAnimatingImageSwap() const;
+
+ // Sets the alpha to use for painting. Used to animate visibility changes.
+ void SetAlpha(int alpha);
+
+ // views::View overrides:
+ gfx::Size GetPreferredSize() const override;
+ const char* GetClassName() const override;
+ void OnPaint(gfx::Canvas* canvas) override;
+
+ void set_paint_as_active(bool paint_as_active) {
+ paint_as_active_ = paint_as_active;
+ }
+
+ CaptionButtonIcon icon() const { return icon_; }
+
+ int icon_image_id() const { return icon_image_id_; }
+
+ protected:
+ // views::CustomButton override:
+ void OnGestureEvent(ui::GestureEvent* event) override;
+
+ private:
+ // Paints |to_center| centered within the button with |alpha|.
+ void PaintCentered(gfx::Canvas* canvas,
+ const gfx::ImageSkia& to_center,
+ int alpha);
+
+ // The button's current icon.
+ CaptionButtonIcon icon_;
+
+ // Whether the button should be painted as active.
+ bool paint_as_active_;
+
+ // Current alpha to use for painting.
+ int alpha_;
+
+ // The images and image ids used to paint the button.
+ int icon_image_id_;
+ int hovered_background_image_id_;
+ int pressed_background_image_id_;
+ gfx::ImageSkia icon_image_;
+ gfx::ImageSkia hovered_background_image_;
+ gfx::ImageSkia pressed_background_image_;
+
+ // The icon image to crossfade from.
+ gfx::ImageSkia crossfade_icon_image_;
+
+ // Crossfade animation started when the button's images are changed by
+ // SetImages().
+ scoped_ptr<gfx::SlideAnimation> swap_images_animation_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameCaptionButton);
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_
diff --git a/mash/wm/frame/caption_buttons/frame_caption_button_container_view.cc b/mash/wm/frame/caption_buttons/frame_caption_button_container_view.cc
new file mode 100644
index 0000000..3bd443b
--- /dev/null
+++ b/mash/wm/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -0,0 +1,353 @@
+// Copyright 2015 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.
+
+#include "mash/wm/frame/caption_buttons/frame_caption_button_container_view.h"
+
+#include <cmath>
+#include <map>
+
+#include "mash/wm/frame/caption_buttons/frame_caption_button.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/strings/grit/ui_strings.h" // Accessibility names
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace mash {
+namespace wm {
+
+namespace {
+
+// Duration of the animation of the position of |minimize_button_|.
+const int kPositionAnimationDurationMs = 500;
+
+// Duration of the animation of the alpha of |size_button_|.
+const int kAlphaAnimationDurationMs = 250;
+
+// Delay during |maximize_mode_animation_| hide to wait before beginning to
+// animate the position of |minimize_button_|.
+const int kHidePositionDelayMs = 100;
+
+// Duration of |maximize_mode_animation_| hiding.
+// Hiding size button 250
+// |------------------------|
+// Delay 100 Slide minimize button 500
+// |---------|-------------------------------------------------|
+const int kHideAnimationDurationMs =
+ kHidePositionDelayMs + kPositionAnimationDurationMs;
+
+// Delay during |maximize_mode_animation_| show to wait before beginning to
+// animate the alpha of |size_button_|.
+const int kShowAnimationAlphaDelayMs = 100;
+
+// Duration of |maximize_mode_animation_| showing.
+// Slide minimize button 500
+// |-------------------------------------------------|
+// Delay 100 Show size button 250
+// |---------|-----------------------|
+const int kShowAnimationDurationMs = kPositionAnimationDurationMs;
+
+// Value of |maximize_mode_animation_| showing to begin animating alpha of
+// |size_button_|.
+float SizeButtonShowStartValue() {
+ return static_cast<float>(kShowAnimationAlphaDelayMs) /
+ kShowAnimationDurationMs;
+}
+
+// Amount of |maximize_mode_animation_| showing to animate the alpha of
+// |size_button_|.
+float SizeButtonShowDuration() {
+ return static_cast<float>(kAlphaAnimationDurationMs) /
+ kShowAnimationDurationMs;
+}
+
+// Amount of |maximize_mode_animation_| hiding to animate the alpha of
+// |size_button_|.
+float SizeButtonHideDuration() {
+ return static_cast<float>(kAlphaAnimationDurationMs) /
+ kHideAnimationDurationMs;
+}
+
+// Value of |maximize_mode_animation_| hiding to begin animating the position of
+// |minimize_button_|.
+float HidePositionStartValue() {
+ return 1.0f -
+ static_cast<float>(kHidePositionDelayMs) / kHideAnimationDurationMs;
+}
+
+// Converts |point| from |src| to |dst| and hittests against |dst|.
+bool ConvertPointToViewAndHitTest(const views::View* src,
+ const views::View* dst,
+ const gfx::Point& point) {
+ gfx::Point converted(point);
+ views::View::ConvertPointToTarget(src, dst, &converted);
+ return dst->HitTestPoint(converted);
+}
+
+// Bounds animation values to the range 0.0 - 1.0. Allows for mapping of offset
+// animations to the expected range so that gfx::Tween::CalculateValue() can be
+// used.
+double CapAnimationValue(double value) {
+ return std::min(1.0, std::max(0.0, value));
+}
+
+} // namespace
+
+// static
+const char FrameCaptionButtonContainerView::kViewClassName[] =
+ "FrameCaptionButtonContainerView";
+
+FrameCaptionButtonContainerView::FrameCaptionButtonContainerView(
+ views::Widget* frame)
+ : frame_(frame),
+ minimize_button_(NULL),
+ size_button_(NULL),
+ close_button_(NULL) {
+ const bool size_button_visibility = ShouldSizeButtonBeVisible();
+ maximize_mode_animation_.reset(new gfx::SlideAnimation(this));
+ maximize_mode_animation_->SetTweenType(gfx::Tween::LINEAR);
+
+ // Ensure animation tracks visibility of size button.
+ if (size_button_visibility)
+ maximize_mode_animation_->Reset(1.0f);
+
+ // Insert the buttons left to right.
+ minimize_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MINIMIZE);
+ minimize_button_->SetAccessibleName(
+ l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE));
+ minimize_button_->SetVisible(frame_->widget_delegate()->CanMinimize());
+ AddChildView(minimize_button_);
+
+ size_button_ =
+ new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE);
+ size_button_->SetAccessibleName(
+ l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE));
+ size_button_->SetVisible(size_button_visibility);
+ AddChildView(size_button_);
+
+ close_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_CLOSE);
+ close_button_->SetAccessibleName(
+ l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
+ AddChildView(close_button_);
+}
+
+FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() {}
+
+void FrameCaptionButtonContainerView::SetButtonImages(
+ CaptionButtonIcon icon,
+ int icon_image_id,
+ int hovered_background_image_id,
+ int pressed_background_image_id) {
+ button_icon_id_map_[icon] = ButtonIconIds(
+ icon_image_id, hovered_background_image_id, pressed_background_image_id);
+ FrameCaptionButton* buttons[] = {minimize_button_, size_button_,
+ close_button_};
+ for (size_t i = 0; i < arraysize(buttons); ++i) {
+ if (buttons[i]->icon() == icon) {
+ buttons[i]->SetImages(icon, FrameCaptionButton::ANIMATE_NO, icon_image_id,
+ hovered_background_image_id,
+ pressed_background_image_id);
+ }
+ }
+}
+
+void FrameCaptionButtonContainerView::SetPaintAsActive(bool paint_as_active) {
+ minimize_button_->set_paint_as_active(paint_as_active);
+ size_button_->set_paint_as_active(paint_as_active);
+ close_button_->set_paint_as_active(paint_as_active);
+}
+
+void FrameCaptionButtonContainerView::ResetWindowControls() {
+ SetButtonsToNormal(ANIMATE_NO);
+}
+
+int FrameCaptionButtonContainerView::NonClientHitTest(
+ const gfx::Point& point) const {
+ if (close_button_->visible() &&
+ ConvertPointToViewAndHitTest(this, close_button_, point)) {
+ return HTCLOSE;
+ } else if (size_button_->visible() &&
+ ConvertPointToViewAndHitTest(this, size_button_, point)) {
+ return HTMAXBUTTON;
+ } else if (minimize_button_->visible() &&
+ ConvertPointToViewAndHitTest(this, minimize_button_, point)) {
+ return HTMINBUTTON;
+ }
+ return HTNOWHERE;
+}
+
+void FrameCaptionButtonContainerView::UpdateSizeButtonVisibility() {
+ bool visible = ShouldSizeButtonBeVisible();
+ if (visible) {
+ size_button_->SetVisible(true);
+ maximize_mode_animation_->SetSlideDuration(kShowAnimationDurationMs);
+ maximize_mode_animation_->Show();
+ } else {
+ maximize_mode_animation_->SetSlideDuration(kHideAnimationDurationMs);
+ maximize_mode_animation_->Hide();
+ }
+}
+
+gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() const {
+ int width = 0;
+ for (int i = 0; i < child_count(); ++i) {
+ const views::View* child = child_at(i);
+ if (child->visible())
+ width += child_at(i)->GetPreferredSize().width();
+ }
+ return gfx::Size(width, close_button_->GetPreferredSize().height());
+}
+
+void FrameCaptionButtonContainerView::Layout() {
+ int x = 0;
+ for (int i = 0; i < child_count(); ++i) {
+ views::View* child = child_at(i);
+ if (!child->visible())
+ continue;
+
+ gfx::Size size = child->GetPreferredSize();
+ child->SetBounds(x, 0, size.width(), size.height());
+ x += size.width();
+ }
+ if (maximize_mode_animation_->is_animating()) {
+ AnimationProgressed(maximize_mode_animation_.get());
+ }
+}
+
+const char* FrameCaptionButtonContainerView::GetClassName() const {
+ return kViewClassName;
+}
+
+void FrameCaptionButtonContainerView::AnimationEnded(
+ const gfx::Animation* animation) {
+ // Ensure that position is calculated at least once.
+ AnimationProgressed(animation);
+
+ double current_value = maximize_mode_animation_->GetCurrentValue();
+ if (current_value == 0.0) {
+ size_button_->SetVisible(false);
+ PreferredSizeChanged();
+ }
+}
+
+void FrameCaptionButtonContainerView::AnimationProgressed(
+ const gfx::Animation* animation) {
+ double current_value = animation->GetCurrentValue();
+ int size_alpha = 0;
+ int minimize_x = 0;
+ if (maximize_mode_animation_->IsShowing()) {
+ double scaled_value =
+ CapAnimationValue((current_value - SizeButtonShowStartValue()) /
+ SizeButtonShowDuration());
+ double tweened_value_alpha =
+ gfx::Tween::CalculateValue(gfx::Tween::EASE_OUT, scaled_value);
+ size_alpha = gfx::Tween::LinearIntValueBetween(tweened_value_alpha, 0, 255);
+
+ double tweened_value_slide =
+ gfx::Tween::CalculateValue(gfx::Tween::EASE_OUT, current_value);
+ minimize_x = gfx::Tween::LinearIntValueBetween(tweened_value_slide,
+ size_button_->x(), 0);
+ } else {
+ double scaled_value_alpha =
+ CapAnimationValue((1.0f - current_value) / SizeButtonHideDuration());
+ double tweened_value_alpha =
+ gfx::Tween::CalculateValue(gfx::Tween::EASE_IN, scaled_value_alpha);
+ size_alpha = gfx::Tween::LinearIntValueBetween(tweened_value_alpha, 255, 0);
+
+ double scaled_value_position = CapAnimationValue(
+ (HidePositionStartValue() - current_value) / HidePositionStartValue());
+ double tweened_value_position =
+ gfx::Tween::CalculateValue(gfx::Tween::EASE_OUT, scaled_value_position);
+ minimize_x = gfx::Tween::LinearIntValueBetween(tweened_value_position, 0,
+ size_button_->x());
+ }
+ size_button_->SetAlpha(size_alpha);
+ minimize_button_->SetX(minimize_x);
+}
+
+void FrameCaptionButtonContainerView::SetButtonIcon(FrameCaptionButton* button,
+ CaptionButtonIcon icon,
+ Animate animate) {
+ // The early return is dependant on |animate| because callers use
+ // SetButtonIcon() with ANIMATE_NO to progress |button|'s crossfade animation
+ // to the end.
+ if (button->icon() == icon &&
+ (animate == ANIMATE_YES || !button->IsAnimatingImageSwap())) {
+ return;
+ }
+
+ FrameCaptionButton::Animate fcb_animate =
+ (animate == ANIMATE_YES) ? FrameCaptionButton::ANIMATE_YES
+ : FrameCaptionButton::ANIMATE_NO;
+ std::map<CaptionButtonIcon, ButtonIconIds>::const_iterator it =
+ button_icon_id_map_.find(icon);
+ if (it != button_icon_id_map_.end()) {
+ button->SetImages(icon, fcb_animate, it->second.icon_image_id,
+ it->second.hovered_background_image_id,
+ it->second.pressed_background_image_id);
+ }
+}
+
+bool FrameCaptionButtonContainerView::ShouldSizeButtonBeVisible() const {
+ return frame_->widget_delegate()->CanMaximize();
+}
+
+void FrameCaptionButtonContainerView::SetButtonsToNormal(Animate animate) {
+ SetButtonIcons(CAPTION_BUTTON_ICON_MINIMIZE, CAPTION_BUTTON_ICON_CLOSE,
+ animate);
+ minimize_button_->SetState(views::Button::STATE_NORMAL);
+ size_button_->SetState(views::Button::STATE_NORMAL);
+ close_button_->SetState(views::Button::STATE_NORMAL);
+}
+
+void FrameCaptionButtonContainerView::SetButtonIcons(
+ CaptionButtonIcon minimize_button_icon,
+ CaptionButtonIcon close_button_icon,
+ Animate animate) {
+ SetButtonIcon(minimize_button_, minimize_button_icon, animate);
+ SetButtonIcon(close_button_, close_button_icon, animate);
+}
+
+void FrameCaptionButtonContainerView::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ // Abort any animations of the button icons.
+ SetButtonsToNormal(ANIMATE_NO);
+
+ if (sender == minimize_button_) {
+ frame_->Minimize();
+ } else if (sender == size_button_) {
+ if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen.
+ frame_->Restore();
+ } else if (frame_->IsMaximized()) {
+ frame_->Restore();
+ } else {
+ frame_->Maximize();
+ }
+ } else if (sender == close_button_) {
+ frame_->Close();
+ }
+}
+
+FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds()
+ : icon_image_id(-1),
+ hovered_background_image_id(-1),
+ pressed_background_image_id(-1) {}
+
+FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds(
+ int icon_id,
+ int hovered_background_id,
+ int pressed_background_id)
+ : icon_image_id(icon_id),
+ hovered_background_image_id(hovered_background_id),
+ pressed_background_image_id(pressed_background_id) {}
+
+FrameCaptionButtonContainerView::ButtonIconIds::~ButtonIconIds() {}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/frame/caption_buttons/frame_caption_button_container_view.h b/mash/wm/frame/caption_buttons/frame_caption_button_container_view.h
new file mode 100644
index 0000000..73ae6a8
--- /dev/null
+++ b/mash/wm/frame/caption_buttons/frame_caption_button_container_view.h
@@ -0,0 +1,135 @@
+// Copyright 2015 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 MASH_WM_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
+#define MASH_WM_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
+
+#include <map>
+
+#include "base/macros.h"
+#include "mash/wm/frame/caption_buttons/caption_button_types.h"
+#include "ui/gfx/animation/animation_delegate.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+namespace gfx {
+class SlideAnimation;
+}
+
+namespace views {
+class Widget;
+}
+
+namespace mash {
+namespace wm {
+
+class FrameCaptionButton;
+
+// Container view for the frame caption buttons. It performs the appropriate
+// action when a caption button is clicked.
+class FrameCaptionButtonContainerView : public views::View,
+ public views::ButtonListener,
+ public gfx::AnimationDelegate {
+ public:
+ enum Animate { ANIMATE_YES, ANIMATE_NO };
+
+ static const char kViewClassName[];
+
+ // |frame| is the views::Widget that the caption buttons act on.
+ explicit FrameCaptionButtonContainerView(views::Widget* frame);
+ ~FrameCaptionButtonContainerView() override;
+
+ // Sets the resource ids of the images to paint the button for |icon|. The
+ // FrameCaptionButtonContainerView will keep track of the images to use for
+ // |icon| even if none of the buttons currently use |icon|.
+ void SetButtonImages(CaptionButtonIcon icon,
+ int icon_image_id,
+ int hovered_background_image_id,
+ int pressed_background_image_id);
+
+ // Sets whether the buttons should be painted as active. Does not schedule
+ // a repaint.
+ void SetPaintAsActive(bool paint_as_active);
+
+ // Tell the window controls to reset themselves to the normal state.
+ void ResetWindowControls();
+
+ // Determines the window HT* code for the caption button at |point|. Returns
+ // HTNOWHERE if |point| is not over any of the caption buttons. |point| must
+ // be in the coordinates of the FrameCaptionButtonContainerView.
+ int NonClientHitTest(const gfx::Point& point) const;
+
+ // Updates the size button's visibility based on whether |frame_| can be
+ // maximized and if maximize mode is enabled. A parent view should relayout
+ // to reflect the change in visibility.
+ void UpdateSizeButtonVisibility();
+
+ // views::View:
+ gfx::Size GetPreferredSize() const override;
+ void Layout() override;
+ const char* GetClassName() const override;
+
+ // Overridden from gfx::AnimationDelegate:
+ void AnimationEnded(const gfx::Animation* animation) override;
+ void AnimationProgressed(const gfx::Animation* animation) override;
+
+ private:
+ friend class FrameCaptionButtonContainerViewTest;
+
+ struct ButtonIconIds {
+ ButtonIconIds();
+ ButtonIconIds(int icon_id,
+ int hovered_background_id,
+ int pressed_background_id);
+ ~ButtonIconIds();
+
+ int icon_image_id;
+ int hovered_background_image_id;
+ int pressed_background_image_id;
+ };
+
+ // Sets |button|'s icon to |icon|. If |animate| is ANIMATE_YES, the button
+ // will crossfade to the new icon. If |animate| is ANIMATE_NO and
+ // |icon| == |button|->icon(), the crossfade animation is progressed to the
+ // end.
+ void SetButtonIcon(FrameCaptionButton* button,
+ CaptionButtonIcon icon,
+ Animate animate);
+
+ // Returns true if maximize mode is not enabled, and |frame_| widget delegate
+ // can be maximized.
+ bool ShouldSizeButtonBeVisible() const;
+
+ void SetButtonsToNormal(Animate animate);
+ void SetButtonIcons(CaptionButtonIcon minimize_button_icon,
+ CaptionButtonIcon close_button_icon,
+ Animate animate);
+
+ // views::ButtonListener:
+ void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
+ // The widget that the buttons act on.
+ views::Widget* frame_;
+
+ // The buttons. In the normal button style, at most one of |minimize_button_|
+ // and |size_button_| is visible.
+ FrameCaptionButton* minimize_button_;
+ FrameCaptionButton* size_button_;
+ FrameCaptionButton* close_button_;
+
+ // Mapping of the images needed to paint a button for each of the values of
+ // CaptionButtonIcon.
+ std::map<CaptionButtonIcon, ButtonIconIds> button_icon_id_map_;
+
+ // Animation that affects the position of |minimize_button_| and the
+ // visibility of |size_button_|.
+ scoped_ptr<gfx::SlideAnimation> maximize_mode_animation_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerView);
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
diff --git a/mash/wm/frame/default_header_painter.cc b/mash/wm/frame/default_header_painter.cc
new file mode 100644
index 0000000..755ad7f
--- /dev/null
+++ b/mash/wm/frame/default_header_painter.cc
@@ -0,0 +1,352 @@
+// Copyright 2015 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.
+
+#include "mash/wm/frame/default_header_painter.h"
+
+#include "base/debug/leak_annotations.h"
+#include "base/logging.h"
+#include "grit/mash_wm_resources.h"
+#include "mash/wm/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "mash/wm/frame/header_painter_util.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/scoped_canvas.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/native_widget_aura.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+using views::Widget;
+
+namespace {
+
+// Color for the window title text.
+const SkColor kTitleTextColor = SkColorSetRGB(40, 40, 40);
+// Color of the active window header/content separator line.
+const SkColor kHeaderContentSeparatorColor = SkColorSetRGB(150, 150, 152);
+// Color of the inactive window header/content separator line.
+const SkColor kHeaderContentSeparatorInactiveColor =
+ SkColorSetRGB(180, 180, 182);
+// The default color of the frame.
+const SkColor kDefaultFrameColor = SkColorSetRGB(242, 242, 242);
+// Duration of crossfade animation for activating and deactivating frame.
+const int kActivationCrossfadeDurationMs = 200;
+// Luminance below which to use white caption buttons.
+const int kMaxLuminanceForLightButtons = 125;
+
+// Tiles an image into an area, rounding the top corners.
+void TileRoundRect(gfx::Canvas* canvas,
+ const SkPaint& paint,
+ const gfx::Rect& bounds,
+ int corner_radius) {
+ SkRect rect = gfx::RectToSkRect(bounds);
+ const SkScalar corner_radius_scalar = SkIntToScalar(corner_radius);
+ SkScalar radii[8] = {corner_radius_scalar,
+ corner_radius_scalar, // top-left
+ corner_radius_scalar,
+ corner_radius_scalar, // top-right
+ 0,
+ 0, // bottom-right
+ 0,
+ 0}; // bottom-left
+ SkPath path;
+ path.addRoundRect(rect, radii, SkPath::kCW_Direction);
+ canvas->DrawPath(path, paint);
+}
+
+// Returns the FontList to use for the title.
+const gfx::FontList& GetTitleFontList() {
+ static const gfx::FontList* title_font_list =
+ new gfx::FontList(views::NativeWidgetAura::GetWindowTitleFontList());
+ ANNOTATE_LEAKING_OBJECT_PTR(title_font_list);
+ return *title_font_list;
+}
+
+} // namespace
+
+namespace mash {
+namespace wm {
+
+///////////////////////////////////////////////////////////////////////////////
+// DefaultHeaderPainter, public:
+
+DefaultHeaderPainter::DefaultHeaderPainter()
+ : frame_(NULL),
+ view_(NULL),
+ left_header_view_(NULL),
+ left_view_x_inset_(HeaderPainterUtil::GetDefaultLeftViewXInset()),
+ active_frame_color_(kDefaultFrameColor),
+ inactive_frame_color_(kDefaultFrameColor),
+ caption_button_container_(NULL),
+ painted_height_(0),
+ mode_(MODE_INACTIVE),
+ initial_paint_(true),
+ activation_animation_(new gfx::SlideAnimation(this)) {}
+
+DefaultHeaderPainter::~DefaultHeaderPainter() {}
+
+void DefaultHeaderPainter::Init(
+ views::Widget* frame,
+ views::View* header_view,
+ FrameCaptionButtonContainerView* caption_button_container) {
+ DCHECK(frame);
+ DCHECK(header_view);
+ DCHECK(caption_button_container);
+ frame_ = frame;
+ view_ = header_view;
+ caption_button_container_ = caption_button_container;
+ UpdateAllButtonImages();
+}
+
+int DefaultHeaderPainter::GetMinimumHeaderWidth() const {
+ // Ensure we have enough space for the window icon and buttons. We allow
+ // the title string to collapse to zero width.
+ return GetTitleBounds().x() +
+ caption_button_container_->GetMinimumSize().width();
+}
+
+void DefaultHeaderPainter::PaintHeader(gfx::Canvas* canvas, Mode mode) {
+ Mode old_mode = mode_;
+ mode_ = mode;
+
+ if (mode_ != old_mode) {
+ UpdateAllButtonImages();
+ if (!initial_paint_ && HeaderPainterUtil::CanAnimateActivation(frame_)) {
+ activation_animation_->SetSlideDuration(kActivationCrossfadeDurationMs);
+ if (mode_ == MODE_ACTIVE)
+ activation_animation_->Show();
+ else
+ activation_animation_->Hide();
+ } else {
+ if (mode_ == MODE_ACTIVE)
+ activation_animation_->Reset(1);
+ else
+ activation_animation_->Reset(0);
+ }
+ initial_paint_ = false;
+ }
+
+ int corner_radius = (frame_->IsMaximized() || frame_->IsFullscreen())
+ ? 0
+ : HeaderPainterUtil::GetTopCornerRadiusWhenRestored();
+
+ SkPaint paint;
+ int active_alpha = activation_animation_->CurrentValueBetween(0, 255);
+ paint.setColor(color_utils::AlphaBlend(active_frame_color_,
+ inactive_frame_color_, active_alpha));
+
+ TileRoundRect(canvas, paint, GetLocalBounds(), corner_radius);
+
+ if (!frame_->IsMaximized() && !frame_->IsFullscreen() &&
+ mode_ == MODE_INACTIVE && !UsesCustomFrameColors()) {
+ PaintHighlightForInactiveRestoredWindow(canvas);
+ }
+ if (frame_->widget_delegate() &&
+ frame_->widget_delegate()->ShouldShowWindowTitle()) {
+ PaintTitleBar(canvas);
+ }
+ if (!UsesCustomFrameColors())
+ PaintHeaderContentSeparator(canvas);
+}
+
+void DefaultHeaderPainter::LayoutHeader() {
+ UpdateSizeButtonImages(ShouldUseLightImages());
+ caption_button_container_->Layout();
+
+ gfx::Size caption_button_container_size =
+ caption_button_container_->GetPreferredSize();
+ caption_button_container_->SetBounds(
+ view_->width() - caption_button_container_size.width(), 0,
+ caption_button_container_size.width(),
+ caption_button_container_size.height());
+
+ LayoutLeftHeaderView();
+
+ // The header/content separator line overlays the caption buttons.
+ SetHeaderHeightForPainting(caption_button_container_->height());
+}
+
+int DefaultHeaderPainter::GetHeaderHeight() const {
+ return caption_button_container_->height();
+}
+
+int DefaultHeaderPainter::GetHeaderHeightForPainting() const {
+ return painted_height_;
+}
+
+void DefaultHeaderPainter::SetHeaderHeightForPainting(int height) {
+ painted_height_ = height;
+}
+
+void DefaultHeaderPainter::SchedulePaintForTitle() {
+ view_->SchedulePaintInRect(GetTitleBounds());
+}
+
+void DefaultHeaderPainter::UpdateLeftViewXInset(int left_view_x_inset) {
+ if (left_view_x_inset_ != left_view_x_inset) {
+ left_view_x_inset_ = left_view_x_inset;
+ LayoutLeftHeaderView();
+ }
+}
+
+void DefaultHeaderPainter::SetFrameColors(SkColor active_frame_color,
+ SkColor inactive_frame_color) {
+ active_frame_color_ = active_frame_color;
+ inactive_frame_color_ = inactive_frame_color;
+ UpdateAllButtonImages();
+}
+
+void DefaultHeaderPainter::UpdateLeftHeaderView(views::View* left_header_view) {
+ left_header_view_ = left_header_view;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// gfx::AnimationDelegate overrides:
+
+void DefaultHeaderPainter::AnimationProgressed(
+ const gfx::Animation* animation) {
+ view_->SchedulePaintInRect(GetLocalBounds());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DefaultHeaderPainter, private:
+
+void DefaultHeaderPainter::PaintHighlightForInactiveRestoredWindow(
+ gfx::Canvas* canvas) {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ gfx::ImageSkia top_edge =
+ *rb.GetImageSkiaNamed(IDR_MASH_WM_WINDOW_HEADER_SHADE_INACTIVE_TOP);
+ gfx::ImageSkia left_edge =
+ *rb.GetImageSkiaNamed(IDR_MASH_WM_WINDOW_HEADER_SHADE_INACTIVE_LEFT);
+ gfx::ImageSkia right_edge =
+ *rb.GetImageSkiaNamed(IDR_MASH_WM_WINDOW_HEADER_SHADE_INACTIVE_RIGHT);
+ gfx::ImageSkia bottom_edge =
+ *rb.GetImageSkiaNamed(IDR_MASH_WM_WINDOW_HEADER_SHADE_INACTIVE_BOTTOM);
+
+ int left_edge_width = left_edge.width();
+ int right_edge_width = right_edge.width();
+ canvas->DrawImageInt(left_edge, 0, 0);
+ canvas->DrawImageInt(right_edge, view_->width() - right_edge_width, 0);
+ canvas->TileImageInt(top_edge, left_edge_width, 0,
+ view_->width() - left_edge_width - right_edge_width,
+ top_edge.height());
+
+ DCHECK_EQ(left_edge.height(), right_edge.height());
+ int bottom = left_edge.height();
+ int bottom_height = bottom_edge.height();
+ canvas->TileImageInt(bottom_edge, left_edge_width, bottom - bottom_height,
+ view_->width() - left_edge_width - right_edge_width,
+ bottom_height);
+}
+
+void DefaultHeaderPainter::PaintTitleBar(gfx::Canvas* canvas) {
+ // The window icon is painted by its own views::View.
+ gfx::Rect title_bounds = GetTitleBounds();
+ title_bounds.set_x(view_->GetMirroredXForRect(title_bounds));
+ canvas->DrawStringRectWithFlags(
+ frame_->widget_delegate()->GetWindowTitle(), GetTitleFontList(),
+ kTitleTextColor, title_bounds, gfx::Canvas::NO_SUBPIXEL_RENDERING);
+}
+
+void DefaultHeaderPainter::PaintHeaderContentSeparator(gfx::Canvas* canvas) {
+ gfx::ScopedCanvas scoped_canvas(canvas);
+ const float scale = canvas->UndoDeviceScaleFactor();
+ gfx::RectF rect(0, painted_height_ * scale - 1, view_->width() * scale, 1);
+ SkPaint paint;
+ paint.setColor((mode_ == MODE_ACTIVE) ? kHeaderContentSeparatorColor
+ : kHeaderContentSeparatorInactiveColor);
+ canvas->sk_canvas()->drawRect(gfx::RectFToSkRect(rect), paint);
+}
+
+void DefaultHeaderPainter::LayoutLeftHeaderView() {
+ if (left_header_view_) {
+ // Vertically center the left header view with respect to the caption button
+ // container.
+ // Floor when computing the center of |caption_button_container_|.
+ gfx::Size size = left_header_view_->GetPreferredSize();
+ int icon_offset_y =
+ caption_button_container_->height() / 2 - size.height() / 2;
+ left_header_view_->SetBounds(left_view_x_inset_, icon_offset_y,
+ size.width(), size.height());
+ }
+}
+
+bool DefaultHeaderPainter::ShouldUseLightImages() {
+ int luminance = color_utils::GetLuminanceForColor(
+ mode_ == MODE_INACTIVE ? inactive_frame_color_ : active_frame_color_);
+ return luminance < kMaxLuminanceForLightButtons;
+}
+
+void DefaultHeaderPainter::UpdateAllButtonImages() {
+ bool use_light_images = ShouldUseLightImages();
+ caption_button_container_->SetButtonImages(
+ CAPTION_BUTTON_ICON_MINIMIZE,
+ use_light_images ? IDR_MASH_WM_WINDOW_CONTROL_ICON_MINIMIZE_WHITE
+ : IDR_MASH_WM_WINDOW_CONTROL_ICON_MINIMIZE,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_H,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_P);
+
+ UpdateSizeButtonImages(use_light_images);
+
+ caption_button_container_->SetButtonImages(
+ CAPTION_BUTTON_ICON_CLOSE,
+ use_light_images ? IDR_MASH_WM_WINDOW_CONTROL_ICON_CLOSE_WHITE
+ : IDR_MASH_WM_WINDOW_CONTROL_ICON_CLOSE,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_H,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_P);
+
+ caption_button_container_->SetButtonImages(
+ CAPTION_BUTTON_ICON_LEFT_SNAPPED,
+ use_light_images ? IDR_MASH_WM_WINDOW_CONTROL_ICON_LEFT_SNAPPED_WHITE
+ : IDR_MASH_WM_WINDOW_CONTROL_ICON_LEFT_SNAPPED,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_H,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_P);
+
+ caption_button_container_->SetButtonImages(
+ CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
+ use_light_images ? IDR_MASH_WM_WINDOW_CONTROL_ICON_RIGHT_SNAPPED_WHITE
+ : IDR_MASH_WM_WINDOW_CONTROL_ICON_RIGHT_SNAPPED,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_H,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_P);
+}
+
+void DefaultHeaderPainter::UpdateSizeButtonImages(bool use_light_images) {
+ int icon_id = 0;
+ if (frame_->IsMaximized() || frame_->IsFullscreen()) {
+ icon_id = use_light_images ? IDR_MASH_WM_WINDOW_CONTROL_ICON_RESTORE_WHITE
+ : IDR_MASH_WM_WINDOW_CONTROL_ICON_RESTORE;
+ } else {
+ icon_id = use_light_images ? IDR_MASH_WM_WINDOW_CONTROL_ICON_MAXIMIZE_WHITE
+ : IDR_MASH_WM_WINDOW_CONTROL_ICON_MAXIMIZE;
+ }
+ caption_button_container_->SetButtonImages(
+ CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, icon_id,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_H,
+ IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_P);
+}
+
+gfx::Rect DefaultHeaderPainter::GetLocalBounds() const {
+ return gfx::Rect(view_->width(), painted_height_);
+}
+
+gfx::Rect DefaultHeaderPainter::GetTitleBounds() const {
+ return HeaderPainterUtil::GetTitleBounds(
+ left_header_view_, caption_button_container_, GetTitleFontList());
+}
+
+bool DefaultHeaderPainter::UsesCustomFrameColors() const {
+ return active_frame_color_ != kDefaultFrameColor ||
+ inactive_frame_color_ != kDefaultFrameColor;
+}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/frame/default_header_painter.h b/mash/wm/frame/default_header_painter.h
new file mode 100644
index 0000000..5e59cb8
--- /dev/null
+++ b/mash/wm/frame/default_header_painter.h
@@ -0,0 +1,122 @@
+// Copyright 2015 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 MASH_WM_FRAME_DEFAULT_HEADER_PAINTER_H_
+#define MASH_WM_FRAME_DEFAULT_HEADER_PAINTER_H_
+
+#include "base/basictypes.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "mash/wm/frame/header_painter.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/animation/animation_delegate.h"
+
+namespace gfx {
+class ImageSkia;
+class Rect;
+class SlideAnimation;
+}
+namespace views {
+class View;
+class Widget;
+}
+
+namespace mash {
+namespace wm {
+
+class FrameCaptionButtonContainerView;
+
+// Helper class for painting the default window header.
+class DefaultHeaderPainter : public HeaderPainter,
+ public gfx::AnimationDelegate {
+ public:
+ DefaultHeaderPainter();
+ ~DefaultHeaderPainter() override;
+
+ // DefaultHeaderPainter does not take ownership of any of the parameters.
+ void Init(views::Widget* frame,
+ views::View* header_view,
+ FrameCaptionButtonContainerView* caption_button_container);
+
+ // HeaderPainter overrides:
+ int GetMinimumHeaderWidth() const override;
+ void PaintHeader(gfx::Canvas* canvas, Mode mode) override;
+ void LayoutHeader() override;
+ int GetHeaderHeight() const override;
+ int GetHeaderHeightForPainting() const override;
+ void SetHeaderHeightForPainting(int height) override;
+ void SchedulePaintForTitle() override;
+ void UpdateLeftViewXInset(int left_view_x_inset) override;
+
+ // Sets the left header view for the header. Passing NULL removes the view.
+ void UpdateLeftHeaderView(views::View* left_header_view);
+
+ // Sets the active and inactive frame colors. Note the inactive frame color
+ // will have some transparency added when the frame is drawn.
+ void SetFrameColors(SkColor active_frame_color, SkColor inactive_frame_color);
+
+ private:
+ // gfx::AnimationDelegate override:
+ void AnimationProgressed(const gfx::Animation* animation) override;
+
+ // Paints highlight around the edge of the header for inactive restored
+ // windows.
+ void PaintHighlightForInactiveRestoredWindow(gfx::Canvas* canvas);
+
+ // Paints the title bar, primarily the title string.
+ void PaintTitleBar(gfx::Canvas* canvas);
+
+ // Paints the header/content separator.
+ void PaintHeaderContentSeparator(gfx::Canvas* canvas);
+
+ // Layout the left header view.
+ void LayoutLeftHeaderView();
+
+ // Whether light caption images should be used. This is the case when the
+ // background of the frame is dark.
+ bool ShouldUseLightImages();
+
+ // Update all the images in the caption buttons.
+ void UpdateAllButtonImages();
+
+ // Updates the size button's images.
+ void UpdateSizeButtonImages(bool use_light_images);
+
+ // Returns the header bounds in the coordinates of |view_|. The header is
+ // assumed to be positioned at the top left corner of |view_| and to have the
+ // same width as |view_|.
+ gfx::Rect GetLocalBounds() const;
+
+ // Returns the bounds for the title.
+ gfx::Rect GetTitleBounds() const;
+
+ // Returns whether the frame uses custom frame coloring.
+ bool UsesCustomFrameColors() const;
+
+ views::Widget* frame_;
+ views::View* view_;
+ views::View* left_header_view_; // May be NULL.
+ int left_view_x_inset_;
+ SkColor active_frame_color_;
+ SkColor inactive_frame_color_;
+ FrameCaptionButtonContainerView* caption_button_container_;
+
+ // The height of the header to paint.
+ int painted_height_;
+
+ // Whether the header should be painted as active.
+ Mode mode_;
+
+ // Whether the header is painted for the first time.
+ bool initial_paint_;
+
+ scoped_ptr<gfx::SlideAnimation> activation_animation_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultHeaderPainter);
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_DEFAULT_HEADER_PAINTER_H_
diff --git a/mash/wm/frame/frame_border_hit_test_controller.cc b/mash/wm/frame/frame_border_hit_test_controller.cc
new file mode 100644
index 0000000..cd233f8
--- /dev/null
+++ b/mash/wm/frame/frame_border_hit_test_controller.cc
@@ -0,0 +1,82 @@
+// Copyright 2015 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.
+
+#include "mash/wm/frame/frame_border_hit_test_controller.h"
+
+#include "mash/wm/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/base/hit_test.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/window/non_client_view.h"
+
+namespace mash {
+namespace wm {
+
+// In the window corners, the resize areas don't actually expand bigger, but the
+// 16 px at the end of each edge triggers diagonal resizing.
+const int kResizeAreaCornerSize = 16;
+
+// Windows do not have a traditional visible window frame. Window content
+// extends to the edge of the window. We consider a small region outside the
+// window bounds and an even smaller region overlapping the window to be the
+// "non-client" area and use it for resizing.
+const int kResizeOutsideBoundsSize = 6;
+const int kResizeOutsideBoundsScaleForTouch = 5;
+const int kResizeInsideBoundsSize = 1;
+
+// static
+int FrameBorderHitTestController::NonClientHitTest(
+ views::NonClientFrameView* view,
+ FrameCaptionButtonContainerView* caption_button_container,
+ const gfx::Point& point_in_widget) {
+ gfx::Rect expanded_bounds = view->bounds();
+ int outside_bounds = kResizeOutsideBoundsSize;
+
+ if (aura::Env::GetInstance()->is_touch_down())
+ outside_bounds *= kResizeOutsideBoundsScaleForTouch;
+ expanded_bounds.Inset(-outside_bounds, -outside_bounds);
+
+ if (!expanded_bounds.Contains(point_in_widget))
+ return HTNOWHERE;
+
+ // Check the frame first, as we allow a small area overlapping the contents
+ // to be used for resize handles.
+ views::Widget* frame = view->GetWidget();
+ bool can_ever_resize = frame->widget_delegate()->CanResize();
+ // Don't allow overlapping resize handles when the window is maximized or
+ // fullscreen, as it can't be resized in those states.
+ int resize_border = kResizeInsideBoundsSize;
+ if (frame->IsMaximized() || frame->IsFullscreen()) {
+ resize_border = 0;
+ can_ever_resize = false;
+ }
+ int frame_component = view->GetHTComponentForFrame(
+ point_in_widget, resize_border, resize_border, kResizeAreaCornerSize,
+ kResizeAreaCornerSize, can_ever_resize);
+ if (frame_component != HTNOWHERE)
+ return frame_component;
+
+ int client_component =
+ frame->client_view()->NonClientHitTest(point_in_widget);
+ if (client_component != HTNOWHERE)
+ return client_component;
+
+ if (caption_button_container->visible()) {
+ gfx::Point point_in_caption_button_container(point_in_widget);
+ views::View::ConvertPointFromWidget(caption_button_container,
+ &point_in_caption_button_container);
+ int caption_button_component = caption_button_container->NonClientHitTest(
+ point_in_caption_button_container);
+ if (caption_button_component != HTNOWHERE)
+ return caption_button_component;
+ }
+
+ // Caption is a safe default.
+ return HTCAPTION;
+}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/frame/frame_border_hit_test_controller.h b/mash/wm/frame/frame_border_hit_test_controller.h
new file mode 100644
index 0000000..bcfbb77
--- /dev/null
+++ b/mash/wm/frame/frame_border_hit_test_controller.h
@@ -0,0 +1,40 @@
+// Copyright 2015 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 MASH_WM_FRAME_FRAME_BORDER_HITTEST_CONTROLLER_H_
+#define MASH_WM_FRAME_FRAME_BORDER_HITTEST_CONTROLLER_H_
+
+#include "base/macros.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace views {
+class NonClientFrameView;
+class Widget;
+}
+
+namespace mash {
+namespace wm {
+class FrameCaptionButtonContainerView;
+
+// Class which manages the hittest override bounds for |frame|.
+class FrameBorderHitTestController {
+ public:
+ // Does the non client hit test on behalf of |view|. |point_in_widget| must be
+ // in the coordinates of |view|'s widget.
+ static int NonClientHitTest(
+ views::NonClientFrameView* view,
+ FrameCaptionButtonContainerView* caption_button_container,
+ const gfx::Point& point_in_widget);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FrameBorderHitTestController);
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_FRAME_BORDER_HITTEST_CONTROLLER_H_
diff --git a/mash/wm/frame/header_painter.h b/mash/wm/frame/header_painter.h
new file mode 100644
index 0000000..84eef20
--- /dev/null
+++ b/mash/wm/frame/header_painter.h
@@ -0,0 +1,52 @@
+// Copyright 2015 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 MASH_WM_FRAME_HEADER_PAINTER_H_
+#define MASH_WM_FRAME_HEADER_PAINTER_H_
+
+namespace gfx {
+class Canvas;
+}
+
+namespace mash {
+namespace wm {
+
+// Helper class for painting the window header.
+// TODO(sky): keep this only if we're going to actually need different
+// subclasses.
+class HeaderPainter {
+ public:
+ enum Mode { MODE_ACTIVE, MODE_INACTIVE };
+
+ virtual ~HeaderPainter() {}
+
+ // Returns the header's minimum width.
+ virtual int GetMinimumHeaderWidth() const = 0;
+
+ // Paints the header.
+ virtual void PaintHeader(gfx::Canvas* canvas, Mode mode) = 0;
+
+ // Performs layout for the header.
+ virtual void LayoutHeader() = 0;
+
+ // Get the height of the header.
+ virtual int GetHeaderHeight() const = 0;
+
+ // Gets / sets how much of the header is painted. This allows the header to
+ // paint under things (like the tabstrip) which have transparent /
+ // non-painting sections. This height does not affect LayoutHeader().
+ virtual int GetHeaderHeightForPainting() const = 0;
+ virtual void SetHeaderHeightForPainting(int height_for_painting) = 0;
+
+ // Schedule a re-paint of the entire title.
+ virtual void SchedulePaintForTitle() = 0;
+
+ // Updates the x inset of the leftmost view in the header.
+ virtual void UpdateLeftViewXInset(int left_view_x_inset) = 0;
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_HEADER_PAINTER_H_
diff --git a/mash/wm/frame/header_painter_util.cc b/mash/wm/frame/header_painter_util.cc
new file mode 100644
index 0000000..a658d16
--- /dev/null
+++ b/mash/wm/frame/header_painter_util.cc
@@ -0,0 +1,80 @@
+// Copyright 2015 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.
+
+#include "mash/wm/frame/header_painter_util.h"
+
+#include <algorithm>
+
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace {
+
+// Radius of the header's top corners when the window is restored.
+const int kTopCornerRadiusWhenRestored = 2;
+
+// Distance between left edge of the window and the leftmost view.
+const int kDefaultLeftViewXInset = 9;
+
+// Space between the title text and the caption buttons.
+const int kTitleCaptionButtonSpacing = 5;
+
+// Space between window icon and title text.
+const int kTitleIconOffsetX = 5;
+
+// Space between window edge and title text, when there is no icon.
+const int kTitleNoIconOffsetX = 8;
+
+// In the pre-Ash era the web content area had a frame along the left edge, so
+// user-generated theme images for the new tab page assume they are shifted
+// right relative to the header. Now that we have removed the left edge frame
+// we need to copy the theme image for the window header from a few pixels
+// inset to preserve alignment with the NTP image, or else we'll break a bunch
+// of existing themes. We do something similar on OS X for the same reason.
+const int kThemeFrameImageInsetX = 5;
+
+} // namespace
+
+namespace mash {
+namespace wm {
+
+// static
+int HeaderPainterUtil::GetTopCornerRadiusWhenRestored() {
+ return kTopCornerRadiusWhenRestored;
+}
+
+// static
+int HeaderPainterUtil::GetDefaultLeftViewXInset() {
+ return kDefaultLeftViewXInset;
+}
+
+// static
+int HeaderPainterUtil::GetThemeBackgroundXInset() {
+ return kThemeFrameImageInsetX;
+}
+
+// static
+gfx::Rect HeaderPainterUtil::GetTitleBounds(
+ const views::View* left_view,
+ const views::View* right_view,
+ const gfx::FontList& title_font_list) {
+ int x = left_view ? left_view->bounds().right() + kTitleIconOffsetX
+ : kTitleNoIconOffsetX;
+ int height = title_font_list.GetHeight();
+ // Floor when computing the center of |caption_button_container| and when
+ // computing the center of the text.
+ int y = std::max(0, (right_view->height() / 2) - (height / 2));
+ int width = std::max(0, right_view->x() - kTitleCaptionButtonSpacing - x);
+ return gfx::Rect(x, y, width, height);
+}
+
+// static
+bool HeaderPainterUtil::CanAnimateActivation(views::Widget* widget) {
+ return true;
+}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/frame/header_painter_util.h b/mash/wm/frame/header_painter_util.h
new file mode 100644
index 0000000..230c832
--- /dev/null
+++ b/mash/wm/frame/header_painter_util.h
@@ -0,0 +1,56 @@
+// Copyright 2015 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 MASH_WM_FRAME_HEADER_PAINTER_UTIL_H_
+#define MASH_WM_FRAME_HEADER_PAINTER_UTIL_H_
+
+#include "base/macros.h"
+
+namespace gfx {
+class FontList;
+class Rect;
+}
+namespace views {
+class View;
+class Widget;
+}
+
+namespace mash {
+namespace wm {
+
+// Static-only helper class for functionality used accross multiple
+// implementations of HeaderPainter.
+class HeaderPainterUtil {
+ public:
+ // Returns the radius of the header's corners when the window is restored.
+ static int GetTopCornerRadiusWhenRestored();
+
+ // Returns the default distance between the left edge of the window and the
+ // leftmost view in the header.
+ static int GetDefaultLeftViewXInset();
+
+ // Returns the amount that the frame background is inset from the left edge of
+ // the window.
+ static int GetThemeBackgroundXInset();
+
+ // Returns the bounds for the header's title given the views to the left and
+ // right of the title, and the font used.
+ // |left_view| should be NULL if there is no view to the left of the title.
+ static gfx::Rect GetTitleBounds(const views::View* left_view,
+ const views::View* right_view,
+ const gfx::FontList& title_font_list);
+
+ // Returns true if the header for |widget| can animate to new visuals when the
+ // widget's activation changes. Returns false if the header should switch to
+ // new visuals instantaneously.
+ static bool CanAnimateActivation(views::Widget* widget);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(HeaderPainterUtil);
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_HEADER_PAINTER_UTIL_H_
diff --git a/mash/wm/move_loop.cc b/mash/wm/frame/move_loop.cc
index 6c3ee7d..786ff76 100644
--- a/mash/wm/move_loop.cc
+++ b/mash/wm/frame/move_loop.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mash/wm/move_loop.h"
+#include "mash/wm/frame/move_loop.h"
#include "base/auto_reset.h"
#include "components/mus/public/cpp/window.h"
@@ -11,6 +11,9 @@
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect.h"
+namespace mash {
+namespace wm {
+
namespace {
gfx::Point EventLocationToPoint(const mus::mojom::Event& event) {
@@ -221,3 +224,6 @@ void MoveLoop::OnWindowVisibilityChanged(mus::Window* window) {
DCHECK_EQ(window, target_);
Cancel();
}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/move_loop.h b/mash/wm/frame/move_loop.h
index fd1a3e7..12ca46e 100644
--- a/mash/wm/move_loop.h
+++ b/mash/wm/frame/move_loop.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MASH_WM_MOVE_LOOP_H_
-#define MASH_WM_MOVE_LOOP_H_
+#ifndef MASH_WM_FRAME_MOVE_LOOP_H_
+#define MASH_WM_FRAME_MOVE_LOOP_H_
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
@@ -12,6 +12,9 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
+namespace mash {
+namespace wm {
+
// MoveLoop is responsible for moving/resizing windows.
class MoveLoop : public mus::WindowObserver {
public:
@@ -112,4 +115,7 @@ class MoveLoop : public mus::WindowObserver {
DISALLOW_COPY_AND_ASSIGN(MoveLoop);
};
-#endif // MASH_WM_MOVE_LOOP_H_
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_MOVE_LOOP_H_
diff --git a/mash/wm/move_loop_unittest.cc b/mash/wm/frame/move_loop_unittest.cc
index 462c7df7..86ca32c 100644
--- a/mash/wm/move_loop_unittest.cc
+++ b/mash/wm/frame/move_loop_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mash/wm/move_loop.h"
+#include "mash/wm/frame/move_loop.h"
#include "components/mus/public/cpp/tests/test_window.h"
#include "mojo/converters/input_events/input_events_type_converters.h"
@@ -13,6 +13,9 @@
using MoveLoopTest = testing::Test;
+namespace mash {
+namespace wm {
+
namespace {
// Sets the client area for |window|. Padding is provided on the top so that
@@ -177,3 +180,6 @@ TEST_F(MoveLoopTest, Move) {
ASSERT_EQ(data[i].expected_bounds, window.bounds());
}
}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/frame/non_client_frame_view_mash.cc b/mash/wm/frame/non_client_frame_view_mash.cc
new file mode 100644
index 0000000..f3bee2d
--- /dev/null
+++ b/mash/wm/frame/non_client_frame_view_mash.cc
@@ -0,0 +1,351 @@
+// Copyright 2015 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.
+
+#include "mash/wm/frame/non_client_frame_view_mash.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "components/mus/public/cpp/window.h"
+#include "grit/mash_wm_resources.h"
+#include "mash/wm/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "mash/wm/frame/default_header_painter.h"
+#include "mash/wm/frame/frame_border_hit_test_controller.h"
+#include "mash/wm/frame/header_painter.h"
+#include "mash/wm/frame/move_loop.h"
+#include "mojo/converters/input_events/input_events_type_converters.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/paint_recorder.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace mash {
+namespace wm {
+
+///////////////////////////////////////////////////////////////////////////////
+// NonClientFrameViewMash::HeaderView
+
+// View which paints the header.
+class NonClientFrameViewMash::HeaderView : public views::View {
+ public:
+ // |frame| is the widget that the caption buttons act on.
+ explicit HeaderView(views::Widget* frame);
+ ~HeaderView() override;
+
+ // Schedules a repaint for the entire title.
+ void SchedulePaintForTitle();
+
+ // Tells the window controls to reset themselves to the normal state.
+ void ResetWindowControls();
+
+ // Returns the view's preferred height.
+ int GetPreferredHeight() const;
+
+ // Returns the view's minimum width.
+ int GetMinimumWidth() const;
+
+ void SizeConstraintsChanged();
+
+ void SetFrameColors(SkColor active_frame_color, SkColor inactive_frame_color);
+
+ // views::View:
+ void Layout() override;
+ void OnPaint(gfx::Canvas* canvas) override;
+ void ChildPreferredSizeChanged(views::View* child) override;
+
+ FrameCaptionButtonContainerView* caption_button_container() {
+ return caption_button_container_;
+ }
+
+ private:
+ // The widget that the caption buttons act on.
+ views::Widget* frame_;
+
+ // Helper for painting the header.
+ scoped_ptr<DefaultHeaderPainter> header_painter_;
+
+ // View which contains the window caption buttons.
+ FrameCaptionButtonContainerView* caption_button_container_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeaderView);
+};
+
+NonClientFrameViewMash::HeaderView::HeaderView(views::Widget* frame)
+ : frame_(frame),
+ header_painter_(new DefaultHeaderPainter),
+ caption_button_container_(nullptr) {
+ caption_button_container_ = new FrameCaptionButtonContainerView(frame_);
+ caption_button_container_->UpdateSizeButtonVisibility();
+ AddChildView(caption_button_container_);
+
+ header_painter_->Init(frame_, this, caption_button_container_);
+}
+
+NonClientFrameViewMash::HeaderView::~HeaderView() {}
+
+void NonClientFrameViewMash::HeaderView::SchedulePaintForTitle() {
+ header_painter_->SchedulePaintForTitle();
+}
+
+void NonClientFrameViewMash::HeaderView::ResetWindowControls() {
+ caption_button_container_->ResetWindowControls();
+}
+
+int NonClientFrameViewMash::HeaderView::GetPreferredHeight() const {
+ return header_painter_->GetHeaderHeightForPainting();
+}
+
+int NonClientFrameViewMash::HeaderView::GetMinimumWidth() const {
+ return header_painter_->GetMinimumHeaderWidth();
+}
+
+void NonClientFrameViewMash::HeaderView::SizeConstraintsChanged() {
+ caption_button_container_->ResetWindowControls();
+ caption_button_container_->UpdateSizeButtonVisibility();
+ Layout();
+}
+
+void NonClientFrameViewMash::HeaderView::SetFrameColors(
+ SkColor active_frame_color,
+ SkColor inactive_frame_color) {
+ header_painter_->SetFrameColors(active_frame_color, inactive_frame_color);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// NonClientFrameViewMash::HeaderView, views::View overrides:
+
+void NonClientFrameViewMash::HeaderView::Layout() {
+ header_painter_->LayoutHeader();
+}
+
+void NonClientFrameViewMash::HeaderView::OnPaint(gfx::Canvas* canvas) {
+ bool paint_as_active =
+ frame_->non_client_view()->frame_view()->ShouldPaintAsActive();
+ caption_button_container_->SetPaintAsActive(paint_as_active);
+
+ HeaderPainter::Mode header_mode = paint_as_active
+ ? HeaderPainter::MODE_ACTIVE
+ : HeaderPainter::MODE_INACTIVE;
+ header_painter_->PaintHeader(canvas, header_mode);
+}
+
+void NonClientFrameViewMash::HeaderView::ChildPreferredSizeChanged(
+ views::View* child) {
+ // FrameCaptionButtonContainerView animates the visibility changes in
+ // UpdateSizeButtonVisibility(false). Due to this a new size is not available
+ // until the completion of the animation. Layout in response to the preferred
+ // size changes.
+ if (child != caption_button_container_)
+ return;
+ parent()->Layout();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameViewMash, public:
+
+// static
+const char NonClientFrameViewMash::kViewClassName[] = "NonClientFrameViewMash";
+
+NonClientFrameViewMash::NonClientFrameViewMash(views::Widget* frame,
+ mus::Window* window)
+ : frame_(frame), window_(window), header_view_(new HeaderView(frame)) {
+ // |header_view_| is set as the non client view's overlay view so that it can
+ // overlay the web contents in immersive fullscreen.
+ AddChildView(header_view_);
+ window_->AddObserver(this);
+}
+
+NonClientFrameViewMash::~NonClientFrameViewMash() {
+ if (window_)
+ window_->RemoveObserver(this);
+}
+
+// static
+gfx::Insets NonClientFrameViewMash::GetPreferredClientAreaInsets() {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ const int header_height =
+ rb.GetImageSkiaNamed(IDR_MASH_WM_WINDOW_CONTROL_BACKGROUND_P)
+ ->size()
+ .height();
+ return gfx::Insets(header_height, 0, 0, 0);
+}
+
+void NonClientFrameViewMash::SetFrameColors(SkColor active_frame_color,
+ SkColor inactive_frame_color) {
+ header_view_->SetFrameColors(active_frame_color, inactive_frame_color);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameViewMash, views::NonClientFrameView overrides:
+
+gfx::Rect NonClientFrameViewMash::GetBoundsForClientView() const {
+ gfx::Rect result(GetLocalBounds());
+ result.Inset(window_->client_area());
+ return result;
+}
+
+gfx::Rect NonClientFrameViewMash::GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const {
+ gfx::Rect window_bounds = client_bounds;
+ window_bounds.Inset(
+ window_->client_area().left(), window_->client_area().top(),
+ window_->client_area().right(), window_->client_area().bottom());
+ return window_bounds;
+}
+
+int NonClientFrameViewMash::NonClientHitTest(const gfx::Point& point) {
+ return FrameBorderHitTestController::NonClientHitTest(
+ this, header_view_->caption_button_container(), point);
+}
+
+void NonClientFrameViewMash::GetWindowMask(const gfx::Size& size,
+ gfx::Path* window_mask) {}
+
+void NonClientFrameViewMash::ResetWindowControls() {
+ header_view_->ResetWindowControls();
+}
+
+void NonClientFrameViewMash::UpdateWindowIcon() {}
+
+void NonClientFrameViewMash::UpdateWindowTitle() {
+ header_view_->SchedulePaintForTitle();
+}
+
+void NonClientFrameViewMash::SizeConstraintsChanged() {
+ header_view_->SizeConstraintsChanged();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameViewMash, views::View overrides:
+
+void NonClientFrameViewMash::Layout() {
+ header_view_->SetBounds(0, 0, width(), header_view_->GetPreferredHeight());
+ header_view_->Layout();
+}
+
+gfx::Size NonClientFrameViewMash::GetPreferredSize() const {
+ gfx::Size pref = frame_->client_view()->GetPreferredSize();
+ return frame_->non_client_view()
+ ->GetWindowBoundsForClientBounds(gfx::Rect(pref))
+ .size();
+}
+
+const char* NonClientFrameViewMash::GetClassName() const {
+ return kViewClassName;
+}
+
+gfx::Size NonClientFrameViewMash::GetMinimumSize() const {
+ gfx::Size min_client_view_size(frame_->client_view()->GetMinimumSize());
+ return gfx::Size(
+ std::max(header_view_->GetMinimumWidth(), min_client_view_size.width()),
+ NonClientTopBorderHeight() + min_client_view_size.height());
+}
+
+gfx::Size NonClientFrameViewMash::GetMaximumSize() const {
+ gfx::Size max_client_size(frame_->client_view()->GetMaximumSize());
+ int width = 0;
+ int height = 0;
+
+ if (max_client_size.width() > 0)
+ width = std::max(header_view_->GetMinimumWidth(), max_client_size.width());
+ if (max_client_size.height() > 0)
+ height = NonClientTopBorderHeight() + max_client_size.height();
+
+ return gfx::Size(width, height);
+}
+
+void NonClientFrameViewMash::OnPaint(gfx::Canvas* canvas) {
+ canvas->Save();
+ NonClientFrameView::OnPaint(canvas);
+ canvas->Restore();
+
+ // The client app draws the client area. Make ours totally transparent so
+ // we only see the client apps client area.
+ canvas->FillRect(GetBoundsForClientView(), SK_ColorBLACK,
+ SkXfermode::kSrc_Mode);
+}
+
+void NonClientFrameViewMash::PaintChildren(const ui::PaintContext& context) {
+ NonClientFrameView::PaintChildren(context);
+
+ // The client app draws the client area. Make ours totally transparent so
+ // we only see the client apps client area.
+ ui::PaintRecorder recorder(context, size(), &paint_cache_);
+ recorder.canvas()->FillRect(GetBoundsForClientView(), SK_ColorBLACK,
+ SkXfermode::kSrc_Mode);
+}
+
+bool NonClientFrameViewMash::OnMousePressed(const ui::MouseEvent& event) {
+ return StartMoveLoopIfNecessary(event);
+}
+
+bool NonClientFrameViewMash::OnMouseDragged(const ui::MouseEvent& event) {
+ ContinueMove(event);
+ return move_loop_.get() != nullptr;
+}
+
+void NonClientFrameViewMash::OnMouseReleased(const ui::MouseEvent& event) {
+ ContinueMove(event);
+}
+
+void NonClientFrameViewMash::OnMouseCaptureLost() {
+ StopMove();
+}
+
+void NonClientFrameViewMash::OnWindowClientAreaChanged(
+ mus::Window* window,
+ const gfx::Insets& old_client_area) {
+ Layout();
+ // NonClientView (our parent) positions the client view based on bounds from
+ // us. We need to layout from parent to trigger a layout of the client view.
+ if (parent())
+ parent()->Layout();
+ SchedulePaint();
+}
+
+void NonClientFrameViewMash::OnWindowDestroyed(mus::Window* window) {
+ window_->RemoveObserver(this);
+ window_ = nullptr;
+}
+
+bool NonClientFrameViewMash::StartMoveLoopIfNecessary(const ui::Event& event) {
+ if (move_loop_)
+ return false;
+ // TODO(sky): convert MoveLoop to take ui::Event.
+ // TODO(sky): pass in hit test result.
+ move_loop_ = MoveLoop::Create(window_, *mus::mojom::Event::From(event));
+ return true;
+}
+
+void NonClientFrameViewMash::ContinueMove(const ui::Event& event) {
+ // TODO(sky): convert MoveLoop to take ui::Event.
+ if (move_loop_ &&
+ move_loop_->Move(*mus::mojom::Event::From(event)) == MoveLoop::DONE) {
+ move_loop_.reset();
+ }
+}
+
+void NonClientFrameViewMash::StopMove() {
+ move_loop_.reset();
+}
+
+views::View* NonClientFrameViewMash::GetHeaderView() {
+ return header_view_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameViewMash, private:
+
+int NonClientFrameViewMash::NonClientTopBorderHeight() const {
+ return header_view_->GetPreferredHeight();
+}
+
+} // namespace wm
+} // namespace mash
diff --git a/mash/wm/frame/non_client_frame_view_mash.h b/mash/wm/frame/non_client_frame_view_mash.h
new file mode 100644
index 0000000..31b6880
--- /dev/null
+++ b/mash/wm/frame/non_client_frame_view_mash.h
@@ -0,0 +1,107 @@
+// Copyright 2015 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 MASH_WM_FRAME_NON_CLIENT_FRAME_VIEW_MASH_H_
+#define MASH_WM_FRAME_NON_CLIENT_FRAME_VIEW_MASH_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "components/mus/public/cpp/window_observer.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/paint_cache.h"
+#include "ui/views/window/non_client_view.h"
+
+namespace gfx {
+class Insets;
+}
+
+namespace mus {
+class Window;
+}
+
+namespace views {
+class Widget;
+}
+
+namespace mash {
+namespace wm {
+
+class FrameCaptionButtonContainerView;
+class MoveLoop;
+
+class NonClientFrameViewMash : public views::NonClientFrameView,
+ public mus::WindowObserver {
+ public:
+ // Internal class name.
+ static const char kViewClassName[];
+
+ NonClientFrameViewMash(views::Widget* frame, mus::Window* window);
+ ~NonClientFrameViewMash() override;
+
+ static gfx::Insets GetPreferredClientAreaInsets();
+
+ // Sets the active and inactive frame colors. Note the inactive frame color
+ // will have some transparency added when the frame is drawn.
+ void SetFrameColors(SkColor active_frame_color, SkColor inactive_frame_color);
+
+ // views::NonClientFrameView:
+ gfx::Rect GetBoundsForClientView() const override;
+ gfx::Rect GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const override;
+ int NonClientHitTest(const gfx::Point& point) override;
+ void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) override;
+ void ResetWindowControls() override;
+ void UpdateWindowIcon() override;
+ void UpdateWindowTitle() override;
+ void SizeConstraintsChanged() override;
+
+ // views::View:
+ void Layout() override;
+ gfx::Size GetPreferredSize() const override;
+ const char* GetClassName() const override;
+ gfx::Size GetMinimumSize() const override;
+ gfx::Size GetMaximumSize() const override;
+ void OnPaint(gfx::Canvas* canvas) override;
+ void PaintChildren(const ui::PaintContext& context) override;
+ bool OnMousePressed(const ui::MouseEvent& event) override;
+ bool OnMouseDragged(const ui::MouseEvent& event) override;
+ void OnMouseReleased(const ui::MouseEvent& event) override;
+ void OnMouseCaptureLost() override;
+
+ // mus::WindowObserver:
+ void OnWindowClientAreaChanged(mus::Window* window,
+ const gfx::Insets& old_client_area) override;
+ void OnWindowDestroyed(mus::Window* window) override;
+
+ // Get the view of the header.
+ views::View* GetHeaderView();
+
+ private:
+ class OverlayView;
+
+ // Height from top of window to top of client area.
+ int NonClientTopBorderHeight() const;
+
+ bool StartMoveLoopIfNecessary(const ui::Event& event);
+ void ContinueMove(const ui::Event& event);
+ void StopMove();
+
+ // Not owned.
+ views::Widget* frame_;
+
+ mus::Window* window_;
+ ui::PaintCache paint_cache_;
+ scoped_ptr<MoveLoop> move_loop_;
+
+ // View which contains the title and window controls.
+ class HeaderView;
+ HeaderView* header_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonClientFrameViewMash);
+};
+
+} // namespace wm
+} // namespace mash
+
+#endif // MASH_WM_FRAME_NON_CLIENT_FRAME_VIEW_MASH_H_
diff --git a/mash/wm/non_client_frame_controller.cc b/mash/wm/non_client_frame_controller.cc
index b9a95ed..b0eef4e 100644
--- a/mash/wm/non_client_frame_controller.cc
+++ b/mash/wm/non_client_frame_controller.cc
@@ -5,7 +5,7 @@
#include "mash/wm/non_client_frame_controller.h"
#include "components/mus/public/cpp/window.h"
-#include "mash/wm/non_client_frame_view_impl.h"
+#include "mash/wm/frame/non_client_frame_view_mash.h"
#include "mash/wm/property_util.h"
#include "ui/views/mus/native_widget_mus.h"
#include "ui/views/widget/widget.h"
@@ -25,9 +25,10 @@ class WmNativeWidgetMus : public views::NativeWidgetMus {
// NativeWidgetMus:
views::NonClientFrameView* CreateNonClientFrameView() override {
- NonClientFrameViewImpl* frame_view = new NonClientFrameViewImpl(window());
- frame_view->Init(
- static_cast<views::internal::NativeWidgetPrivate*>(this)->GetWidget());
+ views::Widget* widget =
+ static_cast<views::internal::NativeWidgetPrivate*>(this)->GetWidget();
+ mash::wm::NonClientFrameViewMash* frame_view =
+ new mash::wm::NonClientFrameViewMash(widget, window());
return frame_view;
}
void CenterWindow(const gfx::Size& size) override {
@@ -56,6 +57,11 @@ NonClientFrameController::NonClientFrameController(mojo::Shell* shell,
widget_->Show();
}
+// static
+gfx::Insets NonClientFrameController::GetPreferredClientAreaInsets() {
+ return mash::wm::NonClientFrameViewMash::GetPreferredClientAreaInsets();
+}
+
NonClientFrameController::~NonClientFrameController() {
if (window_)
window_->RemoveObserver(this);
diff --git a/mash/wm/non_client_frame_controller.h b/mash/wm/non_client_frame_controller.h
index dfedd07..5e5918c 100644
--- a/mash/wm/non_client_frame_controller.h
+++ b/mash/wm/non_client_frame_controller.h
@@ -9,6 +9,10 @@
#include "components/mus/public/cpp/window_observer.h"
#include "ui/views/widget/widget_delegate.h"
+namespace gfx {
+class Insets;
+}
+
namespace mojo {
class Shell;
}
@@ -24,6 +28,9 @@ class NonClientFrameController : public views::WidgetDelegateView,
// NonClientFrameController deletes itself when |window| is destroyed.
NonClientFrameController(mojo::Shell* shell, mus::Window* window);
+ // Returns the preferred client area insets.
+ static gfx::Insets GetPreferredClientAreaInsets();
+
private:
~NonClientFrameController() override;
diff --git a/mash/wm/non_client_frame_view_impl.cc b/mash/wm/non_client_frame_view_impl.cc
deleted file mode 100644
index 976143b..0000000
--- a/mash/wm/non_client_frame_view_impl.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2015 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.
-
-#include "mash/wm/non_client_frame_view_impl.h"
-
-#include "components/mus/public/cpp/window.h"
-#include "mash/wm/move_loop.h"
-#include "mojo/converters/input_events/input_events_type_converters.h"
-#include "ui/compositor/paint_recorder.h"
-#include "ui/gfx/canvas.h"
-
-NonClientFrameViewImpl::NonClientFrameViewImpl(mus::Window* window)
- : window_(window) {
- window_->AddObserver(this);
-}
-
-NonClientFrameViewImpl::~NonClientFrameViewImpl() {
- if (window_)
- window_->RemoveObserver(this);
-}
-
-gfx::Rect NonClientFrameViewImpl::GetBoundsForClientView() const {
- gfx::Rect result(GetLocalBounds());
- result.Inset(window_->client_area());
- return result;
-}
-
-void NonClientFrameViewImpl::OnPaint(gfx::Canvas* canvas) {
- canvas->Save();
- CustomFrameView::OnPaint(canvas);
- canvas->Restore();
-
- // The client app draws the client area. Make ours totally transparent so
- // we only see the client apps client area.
- canvas->FillRect(GetBoundsForClientView(), SK_ColorBLACK,
- SkXfermode::kSrc_Mode);
-}
-
-void NonClientFrameViewImpl::PaintChildren(const ui::PaintContext& context) {
- CustomFrameView::PaintChildren(context);
-
- // The client app draws the client area. Make ours totally transparent so
- // we only see the client apps client area.
- ui::PaintRecorder recorder(context, size(), &paint_cache_);
- recorder.canvas()->FillRect(GetBoundsForClientView(), SK_ColorBLACK,
- SkXfermode::kSrc_Mode);
-}
-
-bool NonClientFrameViewImpl::OnMousePressed(const ui::MouseEvent& event) {
- return StartMoveLoopIfNecessary(event);
-}
-
-bool NonClientFrameViewImpl::OnMouseDragged(const ui::MouseEvent& event) {
- ContinueMove(event);
- return move_loop_.get() != nullptr;
-}
-
-void NonClientFrameViewImpl::OnMouseReleased(const ui::MouseEvent& event) {
- ContinueMove(event);
-}
-
-void NonClientFrameViewImpl::OnMouseCaptureLost() {
- StopMove();
-}
-
-void NonClientFrameViewImpl::OnWindowClientAreaChanged(
- mus::Window* window,
- const gfx::Insets& old_client_area) {
- Layout();
- // NonClientView (our parent) positions the client view based on bounds from
- // us. We need to layout from parent to trigger a layout of the client view.
- if (parent())
- parent()->Layout();
- SchedulePaint();
-}
-
-void NonClientFrameViewImpl::OnWindowDestroyed(mus::Window* window) {
- window_->RemoveObserver(this);
- window_ = nullptr;
-}
-
-bool NonClientFrameViewImpl::StartMoveLoopIfNecessary(const ui::Event& event) {
- if (move_loop_)
- return false;
- // TODO(sky): convert MoveLoop to take ui::Event.
- move_loop_ = MoveLoop::Create(window_, *mus::mojom::Event::From(event));
- return true;
-}
-
-void NonClientFrameViewImpl::ContinueMove(const ui::Event& event) {
- // TODO(sky): convert MoveLoop to take ui::Event.
- if (move_loop_ &&
- move_loop_->Move(*mus::mojom::Event::From(event)) == MoveLoop::DONE) {
- move_loop_.reset();
- }
-}
-
-void NonClientFrameViewImpl::StopMove() {
- move_loop_.reset();
-}
diff --git a/mash/wm/non_client_frame_view_impl.h b/mash/wm/non_client_frame_view_impl.h
deleted file mode 100644
index e7e3eef..0000000
--- a/mash/wm/non_client_frame_view_impl.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 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 MASH_WM_NON_CLIENT_FRAME_VIEW_IMPL_H_
-#define MASH_WM_NON_CLIENT_FRAME_VIEW_IMPL_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "components/mus/public/cpp/window_observer.h"
-#include "ui/compositor/paint_cache.h"
-#include "ui/views/window/custom_frame_view.h"
-
-class MoveLoop;
-
-class NonClientFrameViewImpl : public views::CustomFrameView,
- public mus::WindowObserver {
- public:
- explicit NonClientFrameViewImpl(mus::Window* window);
- ~NonClientFrameViewImpl() override;
-
- private:
- // CustomFrameView:
- gfx::Rect GetBoundsForClientView() const override;
- void OnPaint(gfx::Canvas* canvas) override;
- void PaintChildren(const ui::PaintContext& context) override;
- bool OnMousePressed(const ui::MouseEvent& event) override;
- bool OnMouseDragged(const ui::MouseEvent& event) override;
- void OnMouseReleased(const ui::MouseEvent& event) override;
- void OnMouseCaptureLost() override;
-
- // mus::WindowObserver:
- void OnWindowClientAreaChanged(mus::Window* window,
- const gfx::Insets& old_client_area) override;
- void OnWindowDestroyed(mus::Window* window) override;
-
- private:
- bool StartMoveLoopIfNecessary(const ui::Event& event);
- void ContinueMove(const ui::Event& event);
- void StopMove();
-
- mus::Window* window_;
- ui::PaintCache paint_cache_;
- scoped_ptr<MoveLoop> move_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(NonClientFrameViewImpl);
-};
-
-#endif // MASH_WM_NON_CLIENT_FRAME_VIEW_IMPL_H_
diff --git a/mash/wm/window_manager_application.cc b/mash/wm/window_manager_application.cc
index 65ec47c..bf58d79 100644
--- a/mash/wm/window_manager_application.cc
+++ b/mash/wm/window_manager_application.cc
@@ -63,7 +63,7 @@ void WindowManagerApplication::OnEmbed(mus::Window* root) {
window_manager_.reset(new WindowManagerImpl(this));
ui_init_.reset(new ui::mojo::UIInit(views::GetDisplaysFromWindow(root)));
- aura_init_.reset(new views::AuraInit(app_, "views_mus_resources.pak"));
+ aura_init_.reset(new views::AuraInit(app_, "mash_wm_resources.pak"));
for (auto request : requests_)
window_manager_binding_.AddBinding(window_manager_.get(), request->Pass());
diff --git a/mash/wm/window_manager_impl.cc b/mash/wm/window_manager_impl.cc
index b5c2b09..46919aa 100644
--- a/mash/wm/window_manager_impl.cc
+++ b/mash/wm/window_manager_impl.cc
@@ -10,7 +10,6 @@
#include "components/mus/public/cpp/window_property.h"
#include "components/mus/public/cpp/window_tree_connection.h"
#include "components/mus/public/interfaces/input_events.mojom.h"
-#include "mash/wm/move_loop.h"
#include "mash/wm/non_client_frame_controller.h"
#include "mash/wm/property_util.h"
#include "mash/wm/public/interfaces/container.mojom.h"
@@ -102,17 +101,11 @@ void WindowManagerImpl::GetConfig(const GetConfigCallback& callback) {
// The insets are roughly what is needed by CustomFrameView. The expectation
// is at some point we'll write our own NonClientFrameView and get the insets
// from it.
- config->normal_client_area_insets = mojo::Insets::New();
- config->normal_client_area_insets->top = 23;
- config->normal_client_area_insets->left = 5;
- config->normal_client_area_insets->right = 5;
- config->normal_client_area_insets->bottom = 5;
-
- config->maximized_client_area_insets = mojo::Insets::New();
- config->maximized_client_area_insets->top = 21;
- config->maximized_client_area_insets->left = 0;
- config->maximized_client_area_insets->right = 0;
- config->maximized_client_area_insets->bottom = 0;
+ const gfx::Insets client_area_insets =
+ NonClientFrameController::GetPreferredClientAreaInsets();
+ config->normal_client_area_insets = mojo::Insets::From(client_area_insets);
+
+ config->maximized_client_area_insets = mojo::Insets::From(client_area_insets);
callback.Run(config.Pass());
}