diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-13 19:40:23 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-13 19:40:23 +0000 |
commit | 400a61c5463c029125d6c854c9eee773b9be302b (patch) | |
tree | 2322ca5fffc23cd90393c3096a882c42e105c792 /ash/wm | |
parent | 5009ee278b587d7d42bb84203566b1a471b92974 (diff) | |
download | chromium_src-400a61c5463c029125d6c854c9eee773b9be302b.zip chromium_src-400a61c5463c029125d6c854c9eee773b9be302b.tar.gz chromium_src-400a61c5463c029125d6c854c9eee773b9be302b.tar.bz2 |
Move frame related code to ash/frame, plus add OWNERS file.
An attempt to reduce and reorg files in ash/wm as it has too many files.
BUG=None
R=pkotwicz@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/196653008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@256891 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/wm')
31 files changed, 4 insertions, 6816 deletions
diff --git a/ash/wm/caption_buttons/alternate_frame_size_button.cc b/ash/wm/caption_buttons/alternate_frame_size_button.cc deleted file mode 100644 index b8396f1..0000000 --- a/ash/wm/caption_buttons/alternate_frame_size_button.cc +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/alternate_frame_size_button.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/screen_util.h" -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/wm_event.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "base/i18n/rtl.h" -#include "ui/gfx/vector2d.h" -#include "ui/views/widget/widget.h" - -namespace { - -// The default delay between the user pressing the size button and the buttons -// adjacent to the size button morphing into buttons for snapping left and -// right. -const int kSetButtonsToSnapModeDelayMs = 150; - -// The amount that a user can overshoot one of the caption buttons while in -// "snap mode" and keep the button hovered/pressed. -const int kMaxOvershootX = 200; -const int kMaxOvershootY = 50; - -// Returns true if a mouse drag while in "snap mode" at |location_in_screen| -// would hover/press |button| or keep it hovered/pressed. -bool HitTestButton(const ash::FrameCaptionButton* button, - const gfx::Point& location_in_screen) { - gfx::Rect expanded_bounds_in_screen = button->GetBoundsInScreen(); - if (button->state() == views::Button::STATE_HOVERED || - button->state() == views::Button::STATE_PRESSED) { - expanded_bounds_in_screen.Inset(-kMaxOvershootX, -kMaxOvershootY); - } - return expanded_bounds_in_screen.Contains(location_in_screen); -} - -} // namespace - -namespace ash { - -AlternateFrameSizeButton::AlternateFrameSizeButton( - views::ButtonListener* listener, - views::Widget* frame, - AlternateFrameSizeButtonDelegate* delegate) - : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE), - frame_(frame), - delegate_(delegate), - set_buttons_to_snap_mode_delay_ms_(kSetButtonsToSnapModeDelayMs), - in_snap_mode_(false), - snap_type_(SNAP_NONE) { -} - -AlternateFrameSizeButton::~AlternateFrameSizeButton() { -} - -bool AlternateFrameSizeButton::OnMousePressed(const ui::MouseEvent& event) { - // The minimize and close buttons are set to snap left and right when snapping - // is enabled. Do not enable snapping if the minimize button is not visible. - // The close button is always visible. - if (IsTriggerableEvent(event) && - !in_snap_mode_ && - delegate_->IsMinimizeButtonVisible()) { - StartSetButtonsToSnapModeTimer(event); - } - FrameCaptionButton::OnMousePressed(event); - return true; -} - -bool AlternateFrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) { - UpdateSnapType(event); - // By default a FrameCaptionButton reverts to STATE_NORMAL once the mouse - // leaves its bounds. Skip FrameCaptionButton's handling when - // |in_snap_mode_| == true because we want different behavior. - if (!in_snap_mode_) - FrameCaptionButton::OnMouseDragged(event); - return true; -} - -void AlternateFrameSizeButton::OnMouseReleased(const ui::MouseEvent& event) { - if (!IsTriggerableEvent(event) || !CommitSnap(event)) - FrameCaptionButton::OnMouseReleased(event); -} - -void AlternateFrameSizeButton::OnMouseCaptureLost() { - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); - FrameCaptionButton::OnMouseCaptureLost(); -} - -void AlternateFrameSizeButton::OnMouseMoved(const ui::MouseEvent& event) { - // Ignore any synthetic mouse moves during a drag. - if (!in_snap_mode_) - FrameCaptionButton::OnMouseMoved(event); -} - -void AlternateFrameSizeButton::OnGestureEvent(ui::GestureEvent* event) { - if (event->details().touch_points() > 1) { - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); - return; - } - - if (event->type() == ui::ET_GESTURE_TAP_DOWN) { - StartSetButtonsToSnapModeTimer(*event); - // Go through FrameCaptionButton's handling so that the button gets pressed. - FrameCaptionButton::OnGestureEvent(event); - return; - } - - if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || - event->type() == ui::ET_GESTURE_SCROLL_UPDATE) { - UpdateSnapType(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_TAP || - event->type() == ui::ET_GESTURE_SCROLL_END || - event->type() == ui::ET_SCROLL_FLING_START || - event->type() == ui::ET_GESTURE_END) { - if (CommitSnap(*event)) { - if (event->type() == ui::ET_GESTURE_TAP) { - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_FRAMEMAXIMIZE_TAP); - } - event->SetHandled(); - return; - } - } - - FrameCaptionButton::OnGestureEvent(event); -} - -void AlternateFrameSizeButton::StartSetButtonsToSnapModeTimer( - const ui::LocatedEvent& event) { - set_buttons_to_snap_mode_timer_event_location_ = event.location(); - if (set_buttons_to_snap_mode_delay_ms_ == 0) { - AnimateButtonsToSnapMode(); - } else { - set_buttons_to_snap_mode_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(set_buttons_to_snap_mode_delay_ms_), - this, - &AlternateFrameSizeButton::AnimateButtonsToSnapMode); - } -} - -void AlternateFrameSizeButton::AnimateButtonsToSnapMode() { - SetButtonsToSnapMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); -} - -void AlternateFrameSizeButton::SetButtonsToSnapMode( - AlternateFrameSizeButtonDelegate::Animate animate) { - in_snap_mode_ = true; - - // When using a right-to-left layout the close button is left of the size - // button and the minimize button is right of the size button. - if (base::i18n::IsRTL()) { - delegate_->SetButtonIcons(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - CAPTION_BUTTON_ICON_LEFT_SNAPPED, - animate); - } else { - delegate_->SetButtonIcons(CAPTION_BUTTON_ICON_LEFT_SNAPPED, - CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - animate); - } -} - -void AlternateFrameSizeButton::UpdateSnapType(const ui::LocatedEvent& event) { - if (!in_snap_mode_) { - // Set the buttons adjacent to the size button to snap left and right early - // if the user drags past the drag threshold. - // |set_buttons_to_snap_mode_timer_| is checked to avoid entering the snap - // mode as a result of an unsupported drag type (e.g. only the right mouse - // button is pressed). - gfx::Vector2d delta( - event.location() - set_buttons_to_snap_mode_timer_event_location_); - if (!set_buttons_to_snap_mode_timer_.IsRunning() || - !views::View::ExceededDragThreshold(delta)) { - return; - } - AnimateButtonsToSnapMode(); - } - - gfx::Point event_location_in_screen(event.location()); - views::View::ConvertPointToScreen(this, &event_location_in_screen); - const FrameCaptionButton* to_hover = - GetButtonToHover(event_location_in_screen); - bool press_size_button = - to_hover || HitTestButton(this, event_location_in_screen); - - if (to_hover) { - // Progress the minimize and close icon morph animations to the end if they - // are in progress. - SetButtonsToSnapMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO); - } - - delegate_->SetHoveredAndPressedButtons( - to_hover, press_size_button ? this : NULL); - - snap_type_ = SNAP_NONE; - if (to_hover) { - switch (to_hover->icon()) { - case CAPTION_BUTTON_ICON_LEFT_SNAPPED: - snap_type_ = SNAP_LEFT; - break; - case CAPTION_BUTTON_ICON_RIGHT_SNAPPED: - snap_type_ = SNAP_RIGHT; - break; - case CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE: - case CAPTION_BUTTON_ICON_MINIMIZE: - case CAPTION_BUTTON_ICON_CLOSE: - case CAPTION_BUTTON_ICON_COUNT: - NOTREACHED(); - break; - } - } - - if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { - aura::Window* window = frame_->GetNativeWindow(); - if (!phantom_window_controller_.get()) { - phantom_window_controller_.reset( - new internal::PhantomWindowController(window)); - } - gfx::Rect phantom_bounds_in_parent = (snap_type_ == SNAP_LEFT) ? - wm::GetDefaultLeftSnappedWindowBoundsInParent(window) : - wm::GetDefaultRightSnappedWindowBoundsInParent(window); - phantom_window_controller_->Show(ScreenUtil::ConvertRectToScreen( - window->parent(), phantom_bounds_in_parent)); - } else { - phantom_window_controller_.reset(); - } -} - -const FrameCaptionButton* AlternateFrameSizeButton::GetButtonToHover( - const gfx::Point& event_location_in_screen) const { - const FrameCaptionButton* closest_button = delegate_->GetButtonClosestTo( - event_location_in_screen); - if ((closest_button->icon() == CAPTION_BUTTON_ICON_LEFT_SNAPPED || - closest_button->icon() == CAPTION_BUTTON_ICON_RIGHT_SNAPPED) && - HitTestButton(closest_button, event_location_in_screen)) { - return closest_button; - } - return NULL; -} - -bool AlternateFrameSizeButton::CommitSnap(const ui::LocatedEvent& event) { - // The position of |event| may be different than the position of the previous - // event. - UpdateSnapType(event); - - if (in_snap_mode_ && - (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { - wm::WindowState* window_state = - wm::GetWindowState(frame_->GetNativeWindow()); - UserMetricsRecorder* metrics = Shell::GetInstance()->metrics(); - const wm::WMEvent snap_event( - snap_type_ == SNAP_LEFT ? - wm::WM_EVENT_SNAP_LEFT : wm::WM_EVENT_SNAP_RIGHT); - window_state->OnWMEvent(&snap_event); - metrics->RecordUserMetricsAction( - snap_type_ == SNAP_LEFT ? - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT : - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT); - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO); - return true; - } - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); - return false; -} - -void AlternateFrameSizeButton::SetButtonsToNormalMode( - AlternateFrameSizeButtonDelegate::Animate animate) { - in_snap_mode_ = false; - snap_type_ = SNAP_NONE; - set_buttons_to_snap_mode_timer_.Stop(); - delegate_->SetButtonsToNormal(animate); - phantom_window_controller_.reset(); -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/alternate_frame_size_button.h b/ash/wm/caption_buttons/alternate_frame_size_button.h deleted file mode 100644 index 43eafca..0000000 --- a/ash/wm/caption_buttons/alternate_frame_size_button.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ -#define ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/alternate_frame_size_button_delegate.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/timer/timer.h" - -namespace views { -class Widget; -} - -namespace ash { -class AlternateFrameSizeButtonDelegate; - -namespace internal { -class PhantomWindowController; -} - -// The maximize/restore button when using the alternate button style. -// When the mouse is pressed over the size button or the size button is touched: -// - The minimize and close buttons are set to snap left and snap right -// respectively. -// - The size button stays pressed while the mouse is over the buttons to snap -// left and to snap right. The button underneath the mouse is hovered. -// When the drag terminates, the action for the button underneath the mouse -// is executed. For the sake of simplicity, the size button is the event -// handler for a click starting on the size button and the entire drag. -class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { - public: - AlternateFrameSizeButton(views::ButtonListener* listener, - views::Widget* frame, - AlternateFrameSizeButtonDelegate* delegate); - - virtual ~AlternateFrameSizeButton(); - - // views::CustomButton overrides: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseCaptureLost() OVERRIDE; - virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - void set_delay_to_set_buttons_to_snap_mode(int delay_ms) { - set_buttons_to_snap_mode_delay_ms_ = delay_ms; - } - - private: - // Starts |set_buttons_to_snap_mode_timer_|. - void StartSetButtonsToSnapModeTimer(const ui::LocatedEvent& event); - - // Animates the buttons adjacent to the size button to snap left and right. - void AnimateButtonsToSnapMode(); - - // Sets the buttons adjacent to the size button to snap left and right. - // Passing in ANIMATE_NO progresses the animation (if any) to the end. - void SetButtonsToSnapMode( - AlternateFrameSizeButtonDelegate::Animate animate); - - // Updates |snap_type_|, whether the size button is pressed and whether any - // other buttons are hovered. - void UpdateSnapType(const ui::LocatedEvent& event); - - // Returns the button which should be hovered (if any) while in "snap mode" - // for |event_location_in_screen|. - const FrameCaptionButton* GetButtonToHover( - const gfx::Point& event_location_in_screen) const; - - // Snaps |frame_| according to |snap_type_|. Returns true if |frame_| was - // snapped. - bool CommitSnap(const ui::LocatedEvent& event); - - // Sets the buttons adjacent to the size button to minimize and close again. - // Clears any state set while snapping was enabled. |animate| indicates - // whether the buttons should animate back to their original icons. - void SetButtonsToNormalMode( - AlternateFrameSizeButtonDelegate::Animate animate); - - // Widget that the size button acts on. - views::Widget* frame_; - - // Not owned. - AlternateFrameSizeButtonDelegate* delegate_; - - // Location of the event which started |set_buttons_to_snap_mode_timer_| in - // view coordinates. - gfx::Point set_buttons_to_snap_mode_timer_event_location_; - - // The delay between the user pressing the size button and the buttons - // adjacent to the size button morphing into buttons for snapping left and - // right. - int set_buttons_to_snap_mode_delay_ms_; - - base::OneShotTimer<AlternateFrameSizeButton> set_buttons_to_snap_mode_timer_; - - // Whether the buttons adjacent to the size button snap the window left and - // right. - bool in_snap_mode_; - - // The action to execute when the drag/click is ended. If - // |snap_type_| == SNAP_NONE, the size button's default action is run when the - // drag/click is ended. - SnapType snap_type_; - - // Displays a preview of how the window's bounds will change as a result of - // snapping the window left or right. The preview is only visible if the snap - // left or snap right button is pressed. - scoped_ptr<internal::PhantomWindowController> phantom_window_controller_; - - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButton); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ diff --git a/ash/wm/caption_buttons/alternate_frame_size_button_delegate.h b/ash/wm/caption_buttons/alternate_frame_size_button_delegate.h deleted file mode 100644 index e3ff85f..0000000 --- a/ash/wm/caption_buttons/alternate_frame_size_button_delegate.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ -#define ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" - -namespace gfx { -class Insets; -class Point; -class Vector2d; -} - -namespace ash { -class FrameCaptionButton; - -// Delegate interface for AlternateFrameSizeButton. -class ASH_EXPORT AlternateFrameSizeButtonDelegate { - public: - enum Animate { - ANIMATE_YES, - ANIMATE_NO - }; - - // Returns whether the minimize button is visible. - virtual bool IsMinimizeButtonVisible() const = 0; - - // Reset the caption button views::Button::ButtonState back to normal. If - // |animate| is ANIMATE_YES, the buttons will crossfade back to their - // original icons. - virtual void SetButtonsToNormal(Animate animate) = 0; - - // Sets the minimize and close button icons. The buttons will crossfade to - // their new icons if |animate| is ANIMATE_YES. - virtual void SetButtonIcons(CaptionButtonIcon minimize_button_icon, - CaptionButtonIcon close_button_icon, - Animate animate) = 0; - - // Returns the button closest to |position_in_screen|. - virtual const FrameCaptionButton* GetButtonClosestTo( - const gfx::Point& position_in_screen) const = 0; - - // Sets |to_hover| and |to_pressed| to STATE_HOVERED and STATE_PRESSED - // respectively. All other buttons are to set to STATE_NORMAL. - virtual void SetHoveredAndPressedButtons( - const FrameCaptionButton* to_hover, - const FrameCaptionButton* to_press) = 0; - - protected: - virtual ~AlternateFrameSizeButtonDelegate() {} -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ diff --git a/ash/wm/caption_buttons/alternate_frame_size_button_unittest.cc b/ash/wm/caption_buttons/alternate_frame_size_button_unittest.cc deleted file mode 100644 index c79fe28..0000000 --- a/ash/wm/caption_buttons/alternate_frame_size_button_unittest.cc +++ /dev/null @@ -1,478 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/alternate_frame_size_button.h" - -#include "ash/ash_switches.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/window_state.h" -#include "base/command_line.h" -#include "base/i18n/rtl.h" -#include "grit/ash_resources.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/events/gestures/gesture_configuration.h" -#include "ui/gfx/display.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate() {} - virtual ~TestWidgetDelegate() {} - - // Overridden from views::WidgetDelegate: - virtual views::View* GetContentsView() OVERRIDE { - return this; - } - virtual bool CanResize() const OVERRIDE { - return true; - } - virtual bool CanMaximize() const OVERRIDE { - return true; - } - - ash::FrameCaptionButtonContainerView* caption_button_container() { - return caption_button_container_; - } - - private: - // Overridden from views::View: - virtual void Layout() OVERRIDE { - caption_button_container_->Layout(); - - // Right align the caption button container. - gfx::Size preferred_size = caption_button_container_->GetPreferredSize(); - caption_button_container_->SetBounds(width() - preferred_size.width(), 0, - preferred_size.width(), preferred_size.height()); - } - - virtual void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) OVERRIDE { - if (details.is_add && details.child == this) { - caption_button_container_ = new FrameCaptionButtonContainerView( - GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - - // Set arbitrary images for the container's buttons so that the buttons - // have non-empty sizes. - for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) { - caption_button_container_->SetButtonImages( - static_cast<CaptionButtonIcon>(icon), - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE, - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - } - - AddChildView(caption_button_container_); - } - } - - // Not owned. - ash::FrameCaptionButtonContainerView* caption_button_container_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -class AlternateFrameSizeButtonTest : public AshTestBase { - public: - AlternateFrameSizeButtonTest() {} - virtual ~AlternateFrameSizeButtonTest() {} - - // Returns the center point of |view| in screen coordinates. - gfx::Point CenterPointInScreen(views::View* view) { - return view->GetBoundsInScreen().CenterPoint(); - } - - // Returns true if the window has |state_type|. - bool HasStateType(wm::WindowStateType state_type) const { - return window_state()->GetStateType() == state_type; - } - - // Returns true if all three buttons are in the normal state. - bool AllButtonsInNormalState() const { - return minimize_button_->state() == views::Button::STATE_NORMAL && - size_button_->state() == views::Button::STATE_NORMAL && - close_button_->state() == views::Button::STATE_NORMAL; - } - - // Creates a widget with |delegate|. The returned widget takes ownership of - // |delegate|. - views::Widget* CreateWidget(views::WidgetDelegate* delegate) { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.context = CurrentContext(); - params.delegate = delegate; - params.bounds = gfx::Rect(10, 10, 100, 100); - widget->Init(params); - widget->Show(); - return widget; - } - - // AshTestBase overrides: - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - - CommandLine* command_line = CommandLine::ForCurrentProcess(); - command_line->AppendSwitch( - switches::kAshEnableAlternateFrameCaptionButtonStyle); - - TestWidgetDelegate* delegate = new TestWidgetDelegate(); - window_state_ = ash::wm::GetWindowState( - CreateWidget(delegate)->GetNativeWindow()); - - FrameCaptionButtonContainerView::TestApi test( - delegate->caption_button_container()); - - minimize_button_ = test.minimize_button(); - size_button_ = test.size_button(); - static_cast<AlternateFrameSizeButton*>( - size_button_)->set_delay_to_set_buttons_to_snap_mode(0); - close_button_ = test.close_button(); - } - - ash::wm::WindowState* window_state() { return window_state_; } - const ash::wm::WindowState* window_state() const { return window_state_; } - - FrameCaptionButton* minimize_button() { return minimize_button_; } - FrameCaptionButton* size_button() { return size_button_; } - FrameCaptionButton* close_button() { return close_button_; } - - private: - // Not owned. - ash::wm::WindowState* window_state_; - FrameCaptionButton* minimize_button_; - FrameCaptionButton* size_button_; - FrameCaptionButton* close_button_; - - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButtonTest); -}; - -// Tests that pressing the left mouse button or tapping down on the size button -// puts the button into the pressed state. -TEST_F(AlternateFrameSizeButtonTest, PressedState) { - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state()); - - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressTouchId(3); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - generator.ReleaseTouchId(3); - RunAllPendingInMessageLoop(); - EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state()); -} - -// Tests that clicking on the size button toggles between the maximized and -// normal state. -TEST_F(AlternateFrameSizeButtonTest, ClickSizeButtonTogglesMaximize) { - EXPECT_FALSE(window_state()->IsMaximized()); - - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state()->IsMaximized()); - - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state()->IsMaximized()); - - generator.GestureTapAt(CenterPointInScreen(size_button())); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state()->IsMaximized()); - - generator.GestureTapAt(CenterPointInScreen(size_button())); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state()->IsMaximized()); -} - -// Test that clicking + dragging to a button adjacent to the size button snaps -// the window left or right. -TEST_F(AlternateFrameSizeButtonTest, ButtonDrag) { - EXPECT_TRUE(window_state()->IsNormalStateType()); - - // 1) Test by dragging the mouse. - // Snap right. - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - generator.MoveMouseTo(CenterPointInScreen(close_button())); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED)); - - // Snap left. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED)); - - // 2) Test with scroll gestures. - // Snap right. - generator.GestureScrollSequence( - CenterPointInScreen(size_button()), - CenterPointInScreen(close_button()), - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED)); - - // Snap left. - generator.GestureScrollSequence( - CenterPointInScreen(size_button()), - CenterPointInScreen(minimize_button()), - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED)); - - // 3) Test with tap gestures. - const int touch_default_radius = - ui::GestureConfiguration::default_radius(); - ui::GestureConfiguration::set_default_radius(0); - // Snap right. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressMoveAndReleaseTouchTo(CenterPointInScreen(close_button())); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED)); - // Snap left. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressMoveAndReleaseTouchTo(CenterPointInScreen(minimize_button())); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED)); - ui::GestureConfiguration::set_default_radius(touch_default_radius); -} - -// Test that clicking, dragging, and overshooting the minimize button a bit -// horizontally still snaps the window left. -TEST_F(AlternateFrameSizeButtonTest, SnapLeftOvershootMinimize) { - EXPECT_TRUE(window_state()->IsNormalStateType()); - - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - - generator.PressLeftButton(); - // Move to the minimize button. - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - // Overshoot the minimize button. - generator.MoveMouseBy(-minimize_button()->width(), 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED)); -} - -// Test that right clicking the size button has no effect. -TEST_F(AlternateFrameSizeButtonTest, RightMouseButton) { - EXPECT_TRUE(window_state()->IsNormalStateType()); - - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressRightButton(); - generator.ReleaseRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state()->IsNormalStateType()); -} - -// Test that upon releasing the mouse button after having pressed the size -// button -// - The state of all the caption buttons is reset. -// - The icon displayed by all of the caption buttons is reset. -TEST_F(AlternateFrameSizeButtonTest, ResetButtonsAfterClick) { - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); - EXPECT_TRUE(AllButtonsInNormalState()); - - // Pressing the size button should result in the size button being pressed and - // the minimize and close button icons changing. - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - // Dragging the mouse over the minimize button should hover the minimize - // button and the minimize and close button icons should stay changed. - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - EXPECT_EQ(views::Button::STATE_HOVERED, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - // Release the mouse, snapping the window left. - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED)); - - // None of the buttons should stay pressed and the buttons should have their - // regular icons. - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); - - // Repeat test but release button where it does not affect the window's state - // because the code path is different. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - const gfx::Rect& kWorkAreaBoundsInScreen = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - generator.MoveMouseTo(kWorkAreaBoundsInScreen.bottom_left()); - - // None of the buttons should be pressed because we are really far away from - // any of the caption buttons. The minimize and close button icons should - // be changed because the mouse is pressed. - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - // Release the mouse. The window should stay snapped left. - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED)); - - // The buttons should stay unpressed and the buttons should now have their - // regular icons. - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); -} - -// Test that the size button is pressed whenever the snap left/right buttons -// are hovered. -TEST_F(AlternateFrameSizeButtonTest, SizeButtonPressedWhenSnapButtonHovered) { - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); - EXPECT_TRUE(AllButtonsInNormalState()); - - // Pressing the size button should result in the size button being pressed and - // the minimize and close button icons changing. - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - // Dragging the mouse over the minimize button (snap left button) should hover - // the minimize button and keep the size button pressed. - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - EXPECT_EQ(views::Button::STATE_HOVERED, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - - // Moving the mouse far away from the caption buttons and then moving it over - // the close button (snap right button) should hover the close button and - // keep the size button pressed. - const gfx::Rect& kWorkAreaBoundsInScreen = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - generator.MoveMouseTo(kWorkAreaBoundsInScreen.bottom_left()); - EXPECT_TRUE(AllButtonsInNormalState()); - generator.MoveMouseTo(CenterPointInScreen(close_button())); - EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_HOVERED, close_button()->state()); -} - -class AlternateFrameSizeButtonTestRTL : public AlternateFrameSizeButtonTest { - public: - AlternateFrameSizeButtonTestRTL() {} - virtual ~AlternateFrameSizeButtonTestRTL() {} - - virtual void SetUp() OVERRIDE { - original_locale_ = l10n_util::GetApplicationLocale(std::string()); - base::i18n::SetICUDefaultLocale("he"); - - AlternateFrameSizeButtonTest::SetUp(); - } - - virtual void TearDown() OVERRIDE { - AlternateFrameSizeButtonTest::TearDown(); - base::i18n::SetICUDefaultLocale(original_locale_); - } - - private: - std::string original_locale_; - - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButtonTestRTL); -}; - -// Test that clicking + dragging to a button adjacent to the size button presses -// the correct button and snaps the window to the correct side. -TEST_F(AlternateFrameSizeButtonTestRTL, ButtonDrag) { - // In RTL the close button should be left of the size button and the minimize - // button should be right of the size button. - ASSERT_LT(close_button()->GetBoundsInScreen().x(), - size_button()->GetBoundsInScreen().x()); - ASSERT_LT(size_button()->GetBoundsInScreen().x(), - minimize_button()->GetBoundsInScreen().x()); - - // Test initial state. - EXPECT_TRUE(window_state()->IsNormalStateType()); - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); - - // Pressing the size button should swap the icons of the minimize and close - // buttons to icons for snapping right and for snapping left respectively. - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, close_button()->icon()); - - // Dragging over to the minimize button should press it. - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - EXPECT_EQ(views::Button::STATE_HOVERED, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - - // Releasing should snap the window right. - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(HasStateType(wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED)); - - // None of the buttons should stay pressed and the buttons should have their - // regular icons. - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); -} - -} // namespace test -} // namespace ash diff --git a/ash/wm/caption_buttons/bubble_contents_button_row.cc b/ash/wm/caption_buttons/bubble_contents_button_row.cc deleted file mode 100644 index 6eb9062..0000000 --- a/ash/wm/caption_buttons/bubble_contents_button_row.cc +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/bubble_contents_button_row.h" - -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller_bubble.h" -#include "grit/ash_resources.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/layout/box_layout.h" - - -namespace ash { - -// BubbleDialogButton --------------------------------------------------------- - -// The image button gets overridden to be able to capture mouse hover events. -// The constructor also assigns all button states and adds |this| as a child of -// |button_row|. -class BubbleDialogButton : public views::ImageButton { - public: - explicit BubbleDialogButton(BubbleContentsButtonRow* button_row, - int normal_image, - int hovered_image, - int pressed_image); - virtual ~BubbleDialogButton(); - - // views::ImageButton: - virtual void OnMouseCaptureLost() OVERRIDE; - virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - - private: - // The creating class which needs to get notified in case of a hover event. - BubbleContentsButtonRow* button_row_; - - DISALLOW_COPY_AND_ASSIGN(BubbleDialogButton); -}; - -BubbleDialogButton::BubbleDialogButton( - BubbleContentsButtonRow* button_row, - int normal_image, - int hovered_image, - int pressed_image) - : views::ImageButton(button_row), - button_row_(button_row) { - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - SetImage(views::CustomButton::STATE_NORMAL, - rb.GetImageSkiaNamed(normal_image)); - SetImage(views::CustomButton::STATE_HOVERED, - rb.GetImageSkiaNamed(hovered_image)); - SetImage(views::CustomButton::STATE_PRESSED, - rb.GetImageSkiaNamed(pressed_image)); - button_row->AddChildView(this); -} - -BubbleDialogButton::~BubbleDialogButton() { -} - -void BubbleDialogButton::OnMouseCaptureLost() { - button_row_->ButtonHovered(NULL); - views::ImageButton::OnMouseCaptureLost(); -} - -void BubbleDialogButton::OnMouseEntered(const ui::MouseEvent& event) { - button_row_->ButtonHovered(this); - views::ImageButton::OnMouseEntered(event); -} - -void BubbleDialogButton::OnMouseExited(const ui::MouseEvent& event) { - button_row_->ButtonHovered(NULL); - views::ImageButton::OnMouseExited(event); -} - -bool BubbleDialogButton::OnMouseDragged(const ui::MouseEvent& event) { - if (!button_row_->bubble()->controller()) - return false; - - // Remove the phantom window when we leave the button. - gfx::Point screen_location(event.location()); - View::ConvertPointToScreen(this, &screen_location); - if (!GetBoundsInScreen().Contains(screen_location)) - button_row_->ButtonHovered(NULL); - else - button_row_->ButtonHovered(this); - - // Pass the event on to the normal handler. - return views::ImageButton::OnMouseDragged(event); -} - - -// BubbleContentsButtonRow ---------------------------------------------------- - -BubbleContentsButtonRow::BubbleContentsButtonRow( - MaximizeBubbleControllerBubble* bubble) - : bubble_(bubble), - left_button_(NULL), - minimize_button_(NULL), - right_button_(NULL) { - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kHorizontal, 0, 0, - MaximizeBubbleControllerBubble::kLayoutSpacing)); - set_background(views::Background::CreateSolidBackground( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor)); - - if (base::i18n::IsRTL()) { - AddMaximizeRightButton(); - AddMinimizeButton(); - AddMaximizeLeftButton(); - } else { - AddMaximizeLeftButton(); - AddMinimizeButton(); - AddMaximizeRightButton(); - } -} - -BubbleContentsButtonRow::~BubbleContentsButtonRow() { -} - -void BubbleContentsButtonRow::ButtonPressed(views::Button* sender, - const ui::Event& event) { - // While shutting down, the connection to the owner might already be broken. - if (!bubble_->controller()) - return; - if (sender == left_button_) { - bubble_->controller()->OnButtonClicked( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) ? - SNAP_RESTORE : SNAP_LEFT); - } else if (sender == minimize_button_) { - bubble_->controller()->OnButtonClicked(SNAP_MINIMIZE); - } else { - DCHECK(sender == right_button_); - bubble_->controller()->OnButtonClicked( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) ? - SNAP_RESTORE : SNAP_RIGHT); - } -} - -void BubbleContentsButtonRow::ButtonHovered(BubbleDialogButton* sender) { - // While shutting down, the connection to the owner might already be broken. - if (!bubble_->controller()) - return; - if (sender == left_button_) { - bubble_->controller()->OnButtonHover( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) ? - SNAP_RESTORE : SNAP_LEFT); - } else if (sender == minimize_button_) { - bubble_->controller()->OnButtonHover(SNAP_MINIMIZE); - } else if (sender == right_button_) { - bubble_->controller()->OnButtonHover( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) ? - SNAP_RESTORE : SNAP_RIGHT); - } else { - bubble_->controller()->OnButtonHover(SNAP_NONE); - } -} - -views::CustomButton* BubbleContentsButtonRow::GetButtonForUnitTest( - SnapType state) { - switch (state) { - case SNAP_LEFT: - return left_button_; - case SNAP_MINIMIZE: - return minimize_button_; - case SNAP_RIGHT: - return right_button_; - default: - NOTREACHED(); - return NULL; - } -} - -void BubbleContentsButtonRow::AddMaximizeLeftButton() { - if (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) { - left_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_H, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_P); - } else { - left_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_LEFT, - IDR_AURA_WINDOW_POSITION_LEFT_H, - IDR_AURA_WINDOW_POSITION_LEFT_P); - } -} - -void BubbleContentsButtonRow::AddMaximizeRightButton() { - if (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) { - right_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_H, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_P); - } else { - right_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_RIGHT, - IDR_AURA_WINDOW_POSITION_RIGHT_H, - IDR_AURA_WINDOW_POSITION_RIGHT_P); - } -} - -void BubbleContentsButtonRow::AddMinimizeButton() { - minimize_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_MIDDLE, - IDR_AURA_WINDOW_POSITION_MIDDLE_H, - IDR_AURA_WINDOW_POSITION_MIDDLE_P); -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/bubble_contents_button_row.h b/ash/wm/caption_buttons/bubble_contents_button_row.h deleted file mode 100644 index 5f6e8d1..0000000 --- a/ash/wm/caption_buttons/bubble_contents_button_row.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ -#define ASH_WM_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ - -#include "ash/wm/workspace/snap_types.h" -#include "ui/views/controls/button/button.h" - -namespace views { -class CustomButton; -} - -namespace ash { - -class BubbleDialogButton; -class MaximizeBubbleControllerBubble; - -// A class that creates all buttons and puts them into a view. -class BubbleContentsButtonRow : public views::View, - public views::ButtonListener { - public: - explicit BubbleContentsButtonRow(MaximizeBubbleControllerBubble* bubble); - virtual ~BubbleContentsButtonRow(); - - // views::ButtonListener: - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) OVERRIDE; - - // Called from BubbleDialogButton. - void ButtonHovered(BubbleDialogButton* sender); - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - MaximizeBubbleControllerBubble* bubble() { return bubble_; } - - private: - // Functions to add the left and right maximize / restore buttons. - void AddMaximizeLeftButton(); - void AddMaximizeRightButton(); - void AddMinimizeButton(); - - // The owning object which gets notifications. - MaximizeBubbleControllerBubble* bubble_; - - // The created buttons for our menu. - BubbleDialogButton* left_button_; - BubbleDialogButton* minimize_button_; - BubbleDialogButton* right_button_; - - DISALLOW_COPY_AND_ASSIGN(BubbleContentsButtonRow); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ diff --git a/ash/wm/caption_buttons/caption_button_types.h b/ash/wm/caption_buttons/caption_button_types.h deleted file mode 100644 index 81c4f35..0000000 --- a/ash/wm/caption_buttons/caption_button_types.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_ -#define ASH_WM_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_ - -namespace ash { - -// These are the types of maximization we know. -enum MaximizeBubbleFrameState { - FRAME_STATE_NONE = 0, - FRAME_STATE_FULL = 1, // This is the full maximized state. - FRAME_STATE_SNAP_LEFT = 2, - FRAME_STATE_SNAP_RIGHT = 3 -}; - -// 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_COUNT -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_ diff --git a/ash/wm/caption_buttons/frame_caption_button.cc b/ash/wm/caption_buttons/frame_caption_button.cc deleted file mode 100644 index 4852ebc..0000000 --- a/ash/wm/caption_buttons/frame_caption_button.cc +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2013 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 "ash/wm/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 ash { - -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; - -} // namespace - -// static -const char FrameCaptionButton::kViewClassName[] = "FrameCaptionButton"; - -FrameCaptionButton::FrameCaptionButton(views::ButtonListener* listener, - CaptionButtonIcon icon) - : CustomButton(listener), - icon_(icon), - paint_as_active_(false), - icon_image_id_(-1), - inactive_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 inactive_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_ && - inactive_icon_image_id == inactive_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_ = GetIconImageToPaint(); - - icon_ = icon; - icon_image_id_ = icon_image_id; - inactive_icon_image_id_ = inactive_icon_image_id; - 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); - inactive_icon_image_ = *rb.GetImageSkiaNamed(inactive_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(); -} - -gfx::Size FrameCaptionButton::GetPreferredSize() { - 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); - - gfx::ImageSkia icon_image = GetIconImageToPaint(); - 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()), 255); - } else { - 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); -} - -const gfx::ImageSkia& FrameCaptionButton::GetIconImageToPaint() const { - return paint_as_active_ ? icon_image_ : inactive_icon_image_; -} - -void FrameCaptionButton::PaintCentered(gfx::Canvas* canvas, - const gfx::ImageSkia& to_center, - int alpha) { - SkPaint paint; - paint.setAlpha(alpha); - canvas->DrawImageInt(to_center, - (width() - to_center.width()) / 2, - (height() - to_center.height()) / 2, - paint); -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/frame_caption_button.h b/ash/wm/caption_buttons/frame_caption_button.h deleted file mode 100644 index 90cf065..0000000 --- a/ash/wm/caption_buttons/frame_caption_button.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" -#include "base/memory/scoped_ptr.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/views/controls/button/custom_button.h" - -namespace gfx { -class SlideAnimation; -} - -namespace ash { - -// Base class for the window caption buttons (minimize, maximize, restore, -// close). -class ASH_EXPORT FrameCaptionButton : public views::CustomButton { - public: - enum Animate { - ANIMATE_YES, - ANIMATE_NO - }; - - static const char kViewClassName[]; - - FrameCaptionButton(views::ButtonListener* listener, CaptionButtonIcon icon); - virtual ~FrameCaptionButton(); - - // 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 inactive_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; - - // views::View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual const char* GetClassName() const OVERRIDE; - virtual 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_; - } - - protected: - // views::CustomButton override: - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - private: - // Returns the icon image to paint based on |paint_as_active_|. - const gfx::ImageSkia& GetIconImageToPaint() const; - - // 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_; - - // The images and image ids used to paint the button. - int icon_image_id_; - int inactive_icon_image_id_; - int hovered_background_image_id_; - int pressed_background_image_id_; - gfx::ImageSkia icon_image_; - gfx::ImageSkia inactive_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 ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_ diff --git a/ash/wm/caption_buttons/frame_caption_button_container_view.cc b/ash/wm/caption_buttons/frame_caption_button_container_view.cc deleted file mode 100644 index a6b02bf..0000000 --- a/ash/wm/caption_buttons/frame_caption_button_container_view.cc +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/frame_caption_button_container_view.h" - -#include <cmath> - -#include "ash/ash_switches.h" -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/wm/caption_buttons/alternate_frame_size_button.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "grit/ui_strings.h" // Accessibility names -#include "ui/base/hit_test.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/point.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -namespace { - -// 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); -} - -} // namespace - -// static -const char FrameCaptionButtonContainerView::kViewClassName[] = - "FrameCaptionButtonContainerView"; - -FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( - views::Widget* frame, - MinimizeAllowed minimize_allowed) - : frame_(frame), - minimize_button_(NULL), - size_button_(NULL), - close_button_(NULL) { - bool alternate_style = switches::UseAlternateFrameCaptionButtonStyle(); - - // 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)); - // Hide |minimize_button_| when using the non-alternate button style because - // |size_button_| is capable of minimizing in this case. - minimize_button_->SetVisible( - minimize_allowed == MINIMIZE_ALLOWED && - (alternate_style || !frame_->widget_delegate()->CanMaximize())); - AddChildView(minimize_button_); - - if (alternate_style) - size_button_ = new AlternateFrameSizeButton(this, frame, this); - else - size_button_ = new FrameMaximizeButton(this, frame); - size_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE)); - size_button_->SetVisible(frame_->widget_delegate()->CanMaximize()); - 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() { -} - -FrameMaximizeButton* -FrameCaptionButtonContainerView::GetOldStyleSizeButton() { - return switches::UseAlternateFrameCaptionButtonStyle() ? - NULL : static_cast<FrameMaximizeButton*>(size_button_); -} - -void FrameCaptionButtonContainerView::SetButtonImages( - CaptionButtonIcon icon, - int icon_image_id, - int inactive_icon_image_id, - int hovered_background_image_id, - int pressed_background_image_id) { - button_icon_id_map_[icon] = ButtonIconIds(icon_image_id, - inactive_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, - inactive_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; -} - -gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() { - int width = 0; - for (int i = 0; i < child_count(); ++i) { - 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(); - } -} - -const char* FrameCaptionButtonContainerView::GetClassName() const { - return kViewClassName; -} - -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.inactive_icon_image_id, - it->second.hovered_background_image_id, - it->second.pressed_background_image_id); - } -} - -void FrameCaptionButtonContainerView::ButtonPressed(views::Button* sender, - const ui::Event& event) { - // When shift-clicking, slow down animations for visual debugging. - // We used to do this via an event filter that looked for the shift key being - // pressed but this interfered with several normal keyboard shortcuts. - scoped_ptr<ui::ScopedAnimationDurationScaleMode> slow_duration_mode; - if (event.IsShiftDown()) { - slow_duration_mode.reset(new ui::ScopedAnimationDurationScaleMode( - ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); - } - - // Abort any animations of the button icons. - SetButtonsToNormal(ANIMATE_NO); - - ash::UserMetricsAction action = - ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE; - if (sender == minimize_button_) { - frame_->Minimize(); - } else if (sender == size_button_) { - if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen. - frame_->SetFullscreen(false); - action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN; - } else if (frame_->IsMaximized()) { - frame_->Restore(); - action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE; - } else { - frame_->Maximize(); - action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE; - } - } else if(sender == close_button_) { - frame_->Close(); - action = ash::UMA_WINDOW_CLOSE_BUTTON_CLICK; - } else { - return; - } - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(action); -} - -bool FrameCaptionButtonContainerView::IsMinimizeButtonVisible() const { - return minimize_button_->visible(); -} - -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); -} - -const FrameCaptionButton* FrameCaptionButtonContainerView::GetButtonClosestTo( - const gfx::Point& position_in_screen) const { - // Since the buttons all have the same size, the closest button is the button - // with the center point closest to |position_in_screen|. - // TODO(pkotwicz): Make the caption buttons not overlap. - gfx::Point position(position_in_screen); - views::View::ConvertPointFromScreen(this, &position); - - FrameCaptionButton* buttons[] = { - minimize_button_, size_button_, close_button_ - }; - int min_squared_distance = INT_MAX; - FrameCaptionButton* closest_button = NULL; - for (size_t i = 0; i < arraysize(buttons); ++i) { - FrameCaptionButton* button = buttons[i]; - if (!button->visible()) - continue; - - gfx::Point center_point = button->GetLocalBounds().CenterPoint(); - views::View::ConvertPointToTarget(button, this, ¢er_point); - int squared_distance = static_cast<int>( - pow(static_cast<double>(position.x() - center_point.x()), 2) + - pow(static_cast<double>(position.y() - center_point.y()), 2)); - if (squared_distance < min_squared_distance) { - min_squared_distance = squared_distance; - closest_button = button; - } - } - return closest_button; -} - -void FrameCaptionButtonContainerView::SetHoveredAndPressedButtons( - const FrameCaptionButton* to_hover, - const FrameCaptionButton* to_press) { - FrameCaptionButton* buttons[] = { - minimize_button_, size_button_, close_button_ - }; - for (size_t i = 0; i < arraysize(buttons); ++i) { - FrameCaptionButton* button = buttons[i]; - views::Button::ButtonState new_state = views::Button::STATE_NORMAL; - if (button == to_hover) - new_state = views::Button::STATE_HOVERED; - else if (button == to_press) - new_state = views::Button::STATE_PRESSED; - button->SetState(new_state); - } -} - -FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds() - : icon_image_id(-1), - inactive_icon_image_id(-1), - hovered_background_image_id(-1), - pressed_background_image_id(-1) { -} - -FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds( - int icon_id, - int inactive_icon_id, - int hovered_background_id, - int pressed_background_id) - : icon_image_id(icon_id), - inactive_icon_image_id(inactive_icon_id), - hovered_background_image_id(hovered_background_id), - pressed_background_image_id(pressed_background_id) { -} - -FrameCaptionButtonContainerView::ButtonIconIds::~ButtonIconIds() { -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/frame_caption_button_container_view.h b/ash/wm/caption_buttons/frame_caption_button_container_view.h deleted file mode 100644 index 29399f8..0000000 --- a/ash/wm/caption_buttons/frame_caption_button_container_view.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/alternate_frame_size_button_delegate.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/view.h" - -namespace views { -class Widget; -} - -namespace ash { -class FrameCaptionButton; -class FrameMaximizeButton; - -// Container view for the frame caption buttons. It performs the appropriate -// action when a caption button is clicked. -class ASH_EXPORT FrameCaptionButtonContainerView - : public views::View, - public views::ButtonListener, - public AlternateFrameSizeButtonDelegate { - public: - static const char kViewClassName[]; - - // Whether the frame can be minimized (either via the maximize/restore button - // or via a dedicated button). - enum MinimizeAllowed { - MINIMIZE_ALLOWED, - MINIMIZE_DISALLOWED - }; - - // |frame| is the views::Widget that the caption buttons act on. - // |minimize_allowed| indicates whether the frame can be minimized (either via - // the maximize/restore button or via a dedicated button). - FrameCaptionButtonContainerView(views::Widget* frame, - MinimizeAllowed minimize_allowed); - virtual ~FrameCaptionButtonContainerView(); - - // For testing. - class TestApi { - public: - explicit TestApi(FrameCaptionButtonContainerView* container_view) - : container_view_(container_view) { - } - - FrameCaptionButton* minimize_button() const { - return container_view_->minimize_button_; - } - - FrameCaptionButton* size_button() const { - return container_view_->size_button_; - } - - FrameCaptionButton* close_button() const { - return container_view_->close_button_; - } - - private: - FrameCaptionButtonContainerView* container_view_; - - DISALLOW_COPY_AND_ASSIGN(TestApi); - }; - - // Returns the size button if using the old caption button style, returns NULL - // otherwise. - FrameMaximizeButton* GetOldStyleSizeButton(); - - // 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 inactive_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; - - // views::View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual void Layout() OVERRIDE; - virtual const char* GetClassName() const OVERRIDE; - - private: - friend class FrameCaptionButtonContainerViewTest; - - struct ButtonIconIds { - ButtonIconIds(); - ButtonIconIds(int icon_id, - int inactive_icon_id, - int hovered_background_id, - int pressed_background_id); - ~ButtonIconIds(); - - int icon_image_id; - int inactive_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); - - // views::ButtonListener override: - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) OVERRIDE; - - // AlternateFrameSizeButton::Delegate overrides: - virtual bool IsMinimizeButtonVisible() const OVERRIDE; - virtual void SetButtonsToNormal(Animate animate) OVERRIDE; - virtual void SetButtonIcons(CaptionButtonIcon minimize_button_icon, - CaptionButtonIcon close_button_icon, - Animate animate) OVERRIDE; - virtual const FrameCaptionButton* GetButtonClosestTo( - const gfx::Point& position_in_screen) const OVERRIDE; - virtual void SetHoveredAndPressedButtons( - const FrameCaptionButton* to_hover, - const FrameCaptionButton* to_press) 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_; - - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerView); -}; - -} // namesapace ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ diff --git a/ash/wm/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/wm/caption_buttons/frame_caption_button_container_view_unittest.cc deleted file mode 100644 index 89b1d4f..0000000 --- a/ash/wm/caption_buttons/frame_caption_button_container_view_unittest.cc +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/frame_caption_button_container_view.h" - -#include "ash/ash_switches.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "base/command_line.h" -#include "grit/ash_resources.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -namespace { - -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate(bool can_maximize) : can_maximize_(can_maximize) { - } - virtual ~TestWidgetDelegate() { - } - - virtual bool CanMaximize() const OVERRIDE { - return can_maximize_; - } - - private: - bool can_maximize_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -class FrameCaptionButtonContainerViewTest : public ash::test::AshTestBase { - public: - enum MaximizeAllowed { - MAXIMIZE_ALLOWED, - MAXIMIZE_DISALLOWED - }; - - FrameCaptionButtonContainerViewTest() { - } - - virtual ~FrameCaptionButtonContainerViewTest() { - } - - // Creates a widget which allows maximizing based on |maximize_allowed|. - // The caller takes ownership of the returned widget. - views::Widget* CreateTestWidget( - MaximizeAllowed maximize_allowed) WARN_UNUSED_RESULT { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params; - params.delegate = new TestWidgetDelegate( - maximize_allowed == MAXIMIZE_ALLOWED); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.context = CurrentContext(); - widget->Init(params); - return widget; - } - - // Sets |container| to use arbitrary images for the buttons. Setting the - // images causes the buttons to have non-empty sizes. - void SetMockImages(FrameCaptionButtonContainerView* container) { - for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) { - container->SetButtonImages( - static_cast<CaptionButtonIcon>(icon), - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE, - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - } - } - - // Tests that |leftmost| and |rightmost| are at |container|'s edges. - bool CheckButtonsAtEdges(FrameCaptionButtonContainerView* container, - const ash::FrameCaptionButton& leftmost, - const ash::FrameCaptionButton& rightmost) { - gfx::Rect expected(container->GetPreferredSize()); - - gfx::Rect container_size(container->GetPreferredSize()); - if (leftmost.y() == rightmost.y() && - leftmost.height() == rightmost.height() && - leftmost.x() == expected.x() && - leftmost.y() == expected.y() && - leftmost.height() == expected.height() && - rightmost.bounds().right() == expected.right()) { - return true; - } - - LOG(ERROR) << "Buttons " << leftmost.bounds().ToString() << " " - << rightmost.bounds().ToString() << " not at edges of " - << expected.ToString(); - return false; - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTest); -}; - -class FrameCaptionButtonContainerViewTestOldStyle - : public FrameCaptionButtonContainerViewTest { - public: - FrameCaptionButtonContainerViewTestOldStyle() { - } - - virtual ~FrameCaptionButtonContainerViewTestOldStyle() { - } - - virtual void SetUp() OVERRIDE { - FrameCaptionButtonContainerViewTest::SetUp(); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDisableAlternateFrameCaptionButtonStyle); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestOldStyle); -}; - -// Test how the allowed actions affect which caption buttons are visible. -TEST_F(FrameCaptionButtonContainerViewTestOldStyle, ButtonVisibility) { - // The minimize button should be hidden when both minimizing and maximizing - // are allowed because the size button can do both. - scoped_ptr<views::Widget> widget_can_maximize( - CreateTestWidget(MAXIMIZE_ALLOWED)); - FrameCaptionButtonContainerView container1(widget_can_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - SetMockImages(&container1); - container1.Layout(); - FrameCaptionButtonContainerView::TestApi t1(&container1); - EXPECT_FALSE(t1.minimize_button()->visible()); - EXPECT_TRUE(t1.size_button()->visible()); - EXPECT_TRUE(t1.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container1, *t1.size_button(), *t1.close_button())); - - // The minimize button should be visible when minimizing is allowed but - // maximizing is disallowed. - scoped_ptr<views::Widget> widget_cannot_maximize( - CreateTestWidget(MAXIMIZE_DISALLOWED)); - FrameCaptionButtonContainerView container2(widget_cannot_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - SetMockImages(&container2); - container2.Layout(); - FrameCaptionButtonContainerView::TestApi t2(&container2); - EXPECT_TRUE(t2.minimize_button()->visible()); - EXPECT_FALSE(t2.size_button()->visible()); - EXPECT_TRUE(t2.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container2, *t2.minimize_button(), *t2.close_button())); - - // Neither the minimize button nor the size button should be visible when - // neither minimizing nor maximizing are allowed. - FrameCaptionButtonContainerView container3(widget_cannot_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED); - SetMockImages(&container3); - container3.Layout(); - FrameCaptionButtonContainerView::TestApi t3(&container3); - EXPECT_FALSE(t3.minimize_button()->visible()); - EXPECT_FALSE(t3.size_button()->visible()); - EXPECT_TRUE(t3.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container3, *t3.close_button(), *t3.close_button())); -} - -class FrameCaptionButtonContainerViewTestAlternateStyle - : public FrameCaptionButtonContainerViewTest { - public: - FrameCaptionButtonContainerViewTestAlternateStyle() { - } - - virtual ~FrameCaptionButtonContainerViewTestAlternateStyle() { - } - - virtual void SetUp() OVERRIDE { - FrameCaptionButtonContainerViewTest::SetUp(); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshEnableAlternateFrameCaptionButtonStyle); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestAlternateStyle); -}; - -// Test how the alternate button style affects which buttons are visible in the -// default case. -TEST_F(FrameCaptionButtonContainerViewTestAlternateStyle, ButtonVisibility) { - // Both the minimize button and the maximize button should be visible when - // both minimizing and maximizing are allowed when using the alternate - // button style. - scoped_ptr<views::Widget> widget_can_maximize( - CreateTestWidget(MAXIMIZE_ALLOWED)); - FrameCaptionButtonContainerView container(widget_can_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - SetMockImages(&container); - container.Layout(); - FrameCaptionButtonContainerView::TestApi t(&container); - EXPECT_TRUE(t.minimize_button()->visible()); - EXPECT_TRUE(t.size_button()->visible()); - EXPECT_TRUE(t.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container, *t.minimize_button(), *t.close_button())); -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/frame_maximize_button.cc b/ash/wm/caption_buttons/frame_maximize_button.cc deleted file mode 100644 index 9d631ad..0000000 --- a/ash/wm/caption_buttons/frame_maximize_button.cc +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/frame_maximize_button.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/screen_util.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "ash/wm/caption_buttons/frame_maximize_button_observer.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/wm_event.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "grit/ash_strings.h" -#include "ui/aura/window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/events/event.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/non_client_view.h" - -namespace ash { - -namespace { - -// Delay before forcing an update of the snap location. -const int kUpdateDelayMS = 400; - -// The delay of the bubble appearance. -const int kBubbleAppearanceDelayMS = 500; - -// The minimum sanp size in percent of the screen width. -const int kMinSnapSizePercent = 50; -} - -// EscapeEventFilter is installed on the RootWindow to track when the escape key -// is pressed. We use an EventFilter for this as the FrameMaximizeButton -// normally does not get focus. -class FrameMaximizeButton::EscapeEventFilter : public ui::EventHandler { - public: - explicit EscapeEventFilter(FrameMaximizeButton* button); - virtual ~EscapeEventFilter(); - - // EventFilter overrides: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - - private: - FrameMaximizeButton* button_; - - DISALLOW_COPY_AND_ASSIGN(EscapeEventFilter); -}; - -FrameMaximizeButton::EscapeEventFilter::EscapeEventFilter( - FrameMaximizeButton* button) - : button_(button) { - Shell::GetInstance()->AddPreTargetHandler(this); -} - -FrameMaximizeButton::EscapeEventFilter::~EscapeEventFilter() { - Shell::GetInstance()->RemovePreTargetHandler(this); -} - -void FrameMaximizeButton::EscapeEventFilter::OnKeyEvent( - ui::KeyEvent* event) { - if (event->type() == ui::ET_KEY_PRESSED && - event->key_code() == ui::VKEY_ESCAPE) { - button_->Cancel(false); - } -} - -// FrameMaximizeButton --------------------------------------------------------- - -FrameMaximizeButton::FrameMaximizeButton(views::ButtonListener* listener, - views::Widget* frame) - : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE), - frame_(frame), - observing_frame_(false), - is_snap_enabled_(false), - exceeded_drag_threshold_(false), - snap_type_(SNAP_NONE), - bubble_appearance_delay_ms_(kBubbleAppearanceDelayMS) { -} - -FrameMaximizeButton::~FrameMaximizeButton() { - // Before the window gets destroyed, the maximizer dialog needs to be shut - // down since it would otherwise call into a deleted object. - maximizer_.reset(); - if (observing_frame_) - OnWindowDestroying(frame_->GetNativeWindow()); -} - -void FrameMaximizeButton::AddObserver(FrameMaximizeButtonObserver* observer) { - observer_list_.AddObserver(observer); -} - -void FrameMaximizeButton::RemoveObserver( - FrameMaximizeButtonObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -void FrameMaximizeButton::SnapButtonHovered(SnapType type) { - // Make sure to only show hover operations when no button is pressed and - // a similar snap operation in progress does not get re-applied. - if (is_snap_enabled_ || type == snap_type_) - return; - // Prime the mouse location with the center of the (local) button. - press_location_ = gfx::Point(width() / 2, height() / 2); - // Then get an adjusted mouse position to initiate the effect. - gfx::Point location = press_location_; - switch (type) { - case SNAP_LEFT: - location.set_x(location.x() - width()); - break; - case SNAP_RIGHT: - location.set_x(location.x() + width()); - break; - case SNAP_MINIMIZE: - location.set_y(location.y() + height()); - break; - case SNAP_RESTORE: - // Simulate a mouse button move over the according button. - if (GetMaximizeBubbleFrameState() == FRAME_STATE_SNAP_LEFT) - location.set_x(location.x() - width()); - else if (GetMaximizeBubbleFrameState() == FRAME_STATE_SNAP_RIGHT) - location.set_x(location.x() + width()); - break; - case SNAP_MAXIMIZE: - break; - case SNAP_NONE: - Cancel(true); - return; - default: - // We should not come here. - NOTREACHED(); - } - UpdateSnap(location); -} - -void FrameMaximizeButton::ExecuteSnapAndCloseMenu(SnapType snap_type) { - Cancel(true); - // Tell our menu to close. - maximizer_.reset(); - snap_type_ = snap_type; - Snap(); -} - -void FrameMaximizeButton::OnMaximizeBubbleShown(views::Widget* bubble) { - FOR_EACH_OBSERVER(FrameMaximizeButtonObserver, - observer_list_, - OnMaximizeBubbleShown(bubble)); -} - -void FrameMaximizeButton::DestroyMaximizeMenu() { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowDestroying(aura::Window* window) { - maximizer_.reset(); - if (observing_frame_) { - CHECK_EQ(frame_->GetNativeWindow(), window); - frame_->GetNativeWindow()->RemoveObserver(this); - frame_->RemoveObserver(this); - observing_frame_ = false; - } -} - -void FrameMaximizeButton::OnWidgetActivationChanged(views::Widget* widget, - bool active) { - // Upon losing focus, the bubble menu and the phantom window should hide. - if (!active) - Cancel(false); -} - -bool FrameMaximizeButton::OnMousePressed(const ui::MouseEvent& event) { - // If we are already in a mouse click / drag operation, a second button down - // call will cancel (this addresses crbug.com/143755). - if (is_snap_enabled_) { - Cancel(false); - } else { - is_snap_enabled_ = event.IsOnlyLeftMouseButton(); - if (is_snap_enabled_) - ProcessStartEvent(event); - } - FrameCaptionButton::OnMousePressed(event); - return true; -} - -void FrameMaximizeButton::OnMouseEntered(const ui::MouseEvent& event) { - FrameCaptionButton::OnMouseEntered(event); - if (!maximizer_) { - DCHECK(GetWidget()); - if (!observing_frame_) { - observing_frame_ = true; - frame_->GetNativeWindow()->AddObserver(this); - frame_->AddObserver(this); - } - maximizer_.reset(new MaximizeBubbleController( - this, - GetMaximizeBubbleFrameState(), - bubble_appearance_delay_ms_)); - } -} - -void FrameMaximizeButton::OnMouseExited(const ui::MouseEvent& event) { - FrameCaptionButton::OnMouseExited(event); - // Remove the bubble menu when the button is not pressed and the mouse is not - // within the bubble. - if (!is_snap_enabled_ && maximizer_) { - if (maximizer_->GetBubbleWindow()) { - gfx::Point screen_location = Shell::GetScreen()->GetCursorScreenPoint(); - if (!maximizer_->GetBubbleWindow()->GetBoundsInScreen().Contains( - screen_location)) { - maximizer_.reset(); - // Make sure that all remaining snap hover states get removed. - SnapButtonHovered(SNAP_NONE); - } - } else { - // The maximize dialog does not show up immediately after creating the - // |maximizer_|. Destroy the dialog therefore before it shows up. - maximizer_.reset(); - } - } -} - -bool FrameMaximizeButton::OnMouseDragged(const ui::MouseEvent& event) { - if (is_snap_enabled_) - ProcessUpdateEvent(event); - return FrameCaptionButton::OnMouseDragged(event); -} - -void FrameMaximizeButton::OnMouseReleased(const ui::MouseEvent& event) { - maximizer_.reset(); - bool snap_was_enabled = is_snap_enabled_; - if (!ProcessEndEvent(event) && snap_was_enabled) - FrameCaptionButton::OnMouseReleased(event); - // At this point |this| might be already destroyed. -} - -void FrameMaximizeButton::OnMouseCaptureLost() { - Cancel(false); - FrameCaptionButton::OnMouseCaptureLost(); -} - -void FrameMaximizeButton::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_TAP_DOWN) { - is_snap_enabled_ = true; - ProcessStartEvent(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_TAP || - (event->type() == ui::ET_GESTURE_SCROLL_END && is_snap_enabled_) || - event->type() == ui::ET_SCROLL_FLING_START) { - // The position of the event may have changed from the previous event (both - // for TAP and SCROLL_END). So it is necessary to update the snap-state for - // the current event. - ProcessUpdateEvent(*event); - if (event->type() == ui::ET_GESTURE_TAP) { - snap_type_ = SnapTypeForLocation(event->location()); - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_FRAMEMAXIMIZE_TAP); - } - ProcessEndEvent(*event); - event->SetHandled(); - return; - } - - if (is_snap_enabled_) { - if (event->type() == ui::ET_GESTURE_END && - event->details().touch_points() == 1) { - // The position of the event may have changed from the previous event. So - // it is necessary to update the snap-state for the current event. - ProcessUpdateEvent(*event); - snap_type_ = SnapTypeForLocation(event->location()); - ProcessEndEvent(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE || - event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { - ProcessUpdateEvent(*event); - event->SetHandled(); - return; - } - } - - FrameCaptionButton::OnGestureEvent(event); -} - -void FrameMaximizeButton::SetVisible(bool visible) { - views::View::SetVisible(visible); -} - -void FrameMaximizeButton::ProcessStartEvent(const ui::LocatedEvent& event) { - DCHECK(is_snap_enabled_); - // Prepare the help menu. - if (!maximizer_) { - maximizer_.reset(new MaximizeBubbleController( - this, - GetMaximizeBubbleFrameState(), - bubble_appearance_delay_ms_)); - } else { - // If the menu did not show up yet, we delay it even a bit more. - maximizer_->DelayCreation(); - } - InstallEventFilter(); - snap_type_ = SNAP_NONE; - press_location_ = event.location(); - exceeded_drag_threshold_ = false; - update_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kUpdateDelayMS), - this, - &FrameMaximizeButton::UpdateSnapFromEventLocation); -} - -void FrameMaximizeButton::ProcessUpdateEvent(const ui::LocatedEvent& event) { - DCHECK(is_snap_enabled_); - if (!exceeded_drag_threshold_) { - exceeded_drag_threshold_ = views::View::ExceededDragThreshold( - event.location() - press_location_); - } - if (exceeded_drag_threshold_) - UpdateSnap(event.location()); -} - -bool FrameMaximizeButton::ProcessEndEvent(const ui::LocatedEvent& event) { - update_timer_.Stop(); - UninstallEventFilter(); - bool should_snap = is_snap_enabled_; - is_snap_enabled_ = false; - - // Remove our help bubble. - maximizer_.reset(); - - if (!should_snap || snap_type_ == SNAP_NONE) - return false; - - SetState(views::CustomButton::STATE_NORMAL); - // SetState will not call SchedulePaint() if state was already set to - // STATE_NORMAL during a drag. - SchedulePaint(); - phantom_window_.reset(); - Snap(); - return true; -} - -void FrameMaximizeButton::Cancel(bool keep_menu_open) { - if (!keep_menu_open) { - maximizer_.reset(); - UninstallEventFilter(); - is_snap_enabled_ = false; - } - phantom_window_.reset(); - snap_type_ = SNAP_NONE; - update_timer_.Stop(); - SchedulePaint(); -} - -void FrameMaximizeButton::InstallEventFilter() { - if (escape_event_filter_) - return; - - escape_event_filter_.reset(new EscapeEventFilter(this)); -} - -void FrameMaximizeButton::UninstallEventFilter() { - escape_event_filter_.reset(NULL); -} - -void FrameMaximizeButton::UpdateSnapFromEventLocation() { - // If the drag threshold has been exceeded the snap location is up to date. - if (exceeded_drag_threshold_) - return; - exceeded_drag_threshold_ = true; - UpdateSnap(press_location_); -} - -void FrameMaximizeButton::UpdateSnap(const gfx::Point& location) { - SnapType type = SnapTypeForLocation(location); - if (type == snap_type_) - return; - - snap_type_ = type; - SchedulePaint(); - - if (snap_type_ == SNAP_NONE) { - phantom_window_.reset(); - return; - } - - if (!phantom_window_) { - phantom_window_.reset( - new internal::PhantomWindowController(frame_->GetNativeWindow())); - } - if (maximizer_) { - phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow()); - maximizer_->SetSnapType(snap_type_); - } - phantom_window_->Show(ScreenBoundsForType(snap_type_)); -} - -SnapType FrameMaximizeButton::SnapTypeForLocation( - const gfx::Point& location) const { - MaximizeBubbleFrameState maximize_type = GetMaximizeBubbleFrameState(); - gfx::Vector2d delta(location - press_location_); - if (!views::View::ExceededDragThreshold(delta)) - return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; - if (delta.x() < 0 && delta.y() > delta.x() && delta.y() < -delta.x()) - return maximize_type == FRAME_STATE_SNAP_LEFT ? SNAP_RESTORE : SNAP_LEFT; - if (delta.x() > 0 && delta.y() > -delta.x() && delta.y() < delta.x()) - return maximize_type == FRAME_STATE_SNAP_RIGHT ? SNAP_RESTORE : SNAP_RIGHT; - if (delta.y() > 0) - return SNAP_MINIMIZE; - return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; -} - -gfx::Rect FrameMaximizeButton::ScreenBoundsForType(SnapType type) const { - aura::Window* window = frame_->GetNativeWindow(); - switch (type) { - case SNAP_LEFT: - return ScreenUtil::ConvertRectToScreen( - window->parent(), - wm::GetDefaultLeftSnappedWindowBoundsInParent(window)); - case SNAP_RIGHT: - return ScreenUtil::ConvertRectToScreen( - window->parent(), - wm::GetDefaultRightSnappedWindowBoundsInParent(window)); - case SNAP_MAXIMIZE: - return ScreenUtil::ConvertRectToScreen( - window->parent(), - ScreenUtil::GetMaximizedWindowBoundsInParent(window)); - case SNAP_MINIMIZE: { - gfx::Rect rect = GetMinimizeAnimationTargetBoundsInScreen(window); - if (!rect.IsEmpty()) { - // PhantomWindowController insets slightly, outset it so the phantom - // doesn't appear inset. - rect.Inset(-8, -8); - } - return rect; - } - case SNAP_RESTORE: { - wm::WindowState* window_state = wm::GetWindowState(window); - return window_state->HasRestoreBounds() ? - window_state->GetRestoreBoundsInScreen() : - frame_->GetWindowBoundsInScreen(); - } - case SNAP_NONE: - NOTREACHED(); - } - return gfx::Rect(); -} - -void FrameMaximizeButton::Snap() { - Shell* shell = Shell::GetInstance(); - wm::WindowState* window_state = wm::GetWindowState(frame_->GetNativeWindow()); - switch (snap_type_) { - case SNAP_LEFT: { - const wm::WMEvent event(wm::WM_EVENT_SNAP_LEFT); - window_state->OnWMEvent(&event); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT); - break; - } - case SNAP_RIGHT: { - const wm::WMEvent event(wm::WM_EVENT_SNAP_RIGHT); - window_state->OnWMEvent(&event); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT); - break; - } - case SNAP_MAXIMIZE: - frame_->Maximize(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE); - break; - case SNAP_MINIMIZE: - frame_->Minimize(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MINIMIZE); - break; - case SNAP_RESTORE: - frame_->Restore(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_RESTORE); - break; - case SNAP_NONE: - NOTREACHED(); - } -} - -MaximizeBubbleFrameState -FrameMaximizeButton::GetMaximizeBubbleFrameState() const { - wm::WindowState* window_state = - wm::GetWindowState(frame_->GetNativeWindow()); - // When there are no restore bounds, we are in normal mode. - if (!window_state->HasRestoreBounds()) - return FRAME_STATE_NONE; - // The normal maximized test can be used. - if (frame_->IsMaximized()) - return FRAME_STATE_FULL; - // For Left/right maximize we need to check the dimensions. - gfx::Rect bounds = frame_->GetWindowBoundsInScreen(); - gfx::Rect screen = Shell::GetScreen()->GetDisplayNearestWindow( - frame_->GetNativeView()).work_area(); - if (bounds.width() < (screen.width() * kMinSnapSizePercent) / 100) - return FRAME_STATE_NONE; - // We might still have a horizontally filled window at this point which we - // treat as no special state. - if (bounds.y() != screen.y() || bounds.height() != screen.height()) - return FRAME_STATE_NONE; - - // We have to be in a maximize mode at this point. - if (bounds.x() == screen.x()) - return FRAME_STATE_SNAP_LEFT; - if (bounds.right() == screen.right()) - return FRAME_STATE_SNAP_RIGHT; - // If we come here, it is likely caused by the fact that the - // "VerticalResizeDoubleClick" stored a restore rectangle. In that case - // we allow all maximize operations (and keep the restore rectangle). - return FRAME_STATE_NONE; -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/frame_maximize_button.h b/ash/wm/caption_buttons/frame_maximize_button.h deleted file mode 100644 index f751aa3..0000000 --- a/ash/wm/caption_buttons/frame_maximize_button.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/views/widget/widget_observer.h" - -namespace views { -class Widget; -} - -namespace ash { -class FrameMaximizeButtonObserver; - -namespace internal { -class PhantomWindowController; -} - -class MaximizeBubbleController; - -// Button used for the maximize control on the frame. Handles snapping logic. -class ASH_EXPORT FrameMaximizeButton : public FrameCaptionButton, - public views::WidgetObserver, - public aura::WindowObserver { - public: - FrameMaximizeButton(views::ButtonListener* listener, - views::Widget* frame); - virtual ~FrameMaximizeButton(); - - void AddObserver(FrameMaximizeButtonObserver* observer); - void RemoveObserver(FrameMaximizeButtonObserver* observer); - - // Updates |snap_type_| based on a a given snap type. This is used by - // external hover events from the button menu. - void SnapButtonHovered(SnapType type); - - // The user clicked the |type| button and the action needs to be performed, - // which will at the same time close the window. - void ExecuteSnapAndCloseMenu(SnapType type); - - // Called by the MaximizeBubbleController when the maximize bubble is shown. - void OnMaximizeBubbleShown(views::Widget* bubble); - - // Remove the maximize menu from the screen (and destroy it). - void DestroyMaximizeMenu(); - - // Returns true when the user clicks and drags the button. - bool is_snap_enabled() const { return is_snap_enabled_; } - - // WindowObserver overrides: - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // WidgetObserver overrides: - virtual void OnWidgetActivationChanged(views::Widget* widget, - bool active) OVERRIDE; - - // ImageButton overrides: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseCaptureLost() OVERRIDE; - - // ui::EventHandler overrides: - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // views::View overwrite: - virtual void SetVisible(bool visible) OVERRIDE; - - // Unit test overwrite: Change the UI delay used for the bubble show up. - void set_bubble_appearance_delay_ms(int bubble_appearance_delay_ms) { - bubble_appearance_delay_ms_ = bubble_appearance_delay_ms; - } - - // Unit test accessor for the maximize bubble. - MaximizeBubbleController* maximizer() { return maximizer_.get(); } - - // Unit test to see if phantom window is open. - bool phantom_window_open() { return phantom_window_.get() != NULL; } - - private: - class EscapeEventFilter; - - // Initializes the snap-gesture based on the event. This should only be called - // when the event is confirmed to have started a snap gesture. - void ProcessStartEvent(const ui::LocatedEvent& event); - - // Updates the snap-state based on the current event. This should only be - // called after the snap gesture has already started. - void ProcessUpdateEvent(const ui::LocatedEvent& event); - - // Returns true if the window was snapped. Returns false otherwise. - bool ProcessEndEvent(const ui::LocatedEvent& event); - - // Cancels snap behavior. If |keep_menu_open| is set, a possibly opened - // bubble help will remain open. - void Cancel(bool keep_menu_open); - - // Installs/uninstalls an EventFilter to track when escape is pressed. - void InstallEventFilter(); - void UninstallEventFilter(); - - // Updates the snap position from the event location. This is invoked by - // |update_timer_|. - void UpdateSnapFromEventLocation(); - - // Updates |snap_type_| based on a mouse drag. - void UpdateSnap(const gfx::Point& location); - - // Returns the type of snap based on the specified location. - SnapType SnapTypeForLocation(const gfx::Point& location) const; - - // Returns the bounds of the resulting window for the specified type. - gfx::Rect ScreenBoundsForType(SnapType type) const; - - // Snaps the window to the current snap position determined by |snap_type_|. - void Snap(); - - // Determine the maximize type of this window. - MaximizeBubbleFrameState GetMaximizeBubbleFrameState() const; - - // Widget that the maximize button acts on. This is different than the widget - // which contains the button in the case of AppNonClientFrameViewAsh. - views::Widget* frame_; - - // True if we have put observers on |frame_|. - bool observing_frame_; - - // Renders the snap position. - scoped_ptr<internal::PhantomWindowController> phantom_window_; - - // Is snapping enabled? Set on press so that in drag we know whether we - // should show the snap locations. - bool is_snap_enabled_; - - // Did the user drag far enough to trigger snapping? - bool exceeded_drag_threshold_; - - // Location of the press. - gfx::Point press_location_; - - // Current snap type. - SnapType snap_type_; - - scoped_ptr<EscapeEventFilter> escape_event_filter_; - - base::OneShotTimer<FrameMaximizeButton> update_timer_; - - scoped_ptr<MaximizeBubbleController> maximizer_; - - // The delay of the bubble appearance. - int bubble_appearance_delay_ms_; - - ObserverList<FrameMaximizeButtonObserver> observer_list_; - - DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButton); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ diff --git a/ash/wm/caption_buttons/frame_maximize_button_observer.h b/ash/wm/caption_buttons/frame_maximize_button_observer.h deleted file mode 100644 index 1962f60..0000000 --- a/ash/wm/caption_buttons/frame_maximize_button_observer.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ - -#include "ash/ash_export.h" - -namespace views { -class Widget; -} - -namespace ash { - -class ASH_EXPORT FrameMaximizeButtonObserver { - public: - virtual ~FrameMaximizeButtonObserver() {} - - // Called when the maximize button's help bubble is shown. - virtual void OnMaximizeBubbleShown(views::Widget* bubble) = 0; -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ diff --git a/ash/wm/caption_buttons/frame_maximize_button_unittest.cc b/ash/wm/caption_buttons/frame_maximize_button_unittest.cc deleted file mode 100644 index 23b60f5..0000000 --- a/ash/wm/caption_buttons/frame_maximize_button_unittest.cc +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/frame_maximize_button.h" - -#include "ash/ash_switches.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "grit/ash_resources.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/aura/window_tree_host.h" -#include "ui/events/event_processor.h" -#include "ui/events/event_utils.h" -#include "ui/events/gestures/gesture_configuration.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -class CancelCallbackHandler { - public: - CancelCallbackHandler(int update_events_before_cancel, - FrameMaximizeButton* maximize_button) : - update_events_before_cancel_(update_events_before_cancel), - maximize_button_(maximize_button) {} - virtual ~CancelCallbackHandler() {} - - void CountedCancelCallback(ui::EventType event_type, - const gfx::Vector2dF& pos) { - if (event_type == ui::ET_GESTURE_SCROLL_UPDATE && - !(--update_events_before_cancel_)) { - // Make sure that we are in the middle of a resizing operation, cancel it - // and then test that it is exited. - EXPECT_TRUE(maximize_button_->is_snap_enabled()); - maximize_button_->DestroyMaximizeMenu(); - EXPECT_FALSE(maximize_button_->is_snap_enabled()); - } - } - - private: - // When this counter reaches 0, the gesture maximize action gets cancelled. - int update_events_before_cancel_; - - // The maximize button which needs to get informed of the gesture termination. - FrameMaximizeButton* maximize_button_; - - DISALLOW_COPY_AND_ASSIGN(CancelCallbackHandler); -}; - -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate() {} - virtual ~TestWidgetDelegate() {} - - // views::WidgetDelegate overrides: - virtual views::View* GetContentsView() OVERRIDE { - return this; - } - virtual bool CanResize() const OVERRIDE { - return true; - } - virtual bool CanMaximize() const OVERRIDE { - return true; - } - - ash::FrameCaptionButtonContainerView* caption_button_container() { - return caption_button_container_; - } - - private: - // Overridden from views::View: - virtual void Layout() OVERRIDE { - caption_button_container_->Layout(); - - // Right align the caption button container. - gfx::Size preferred_size = caption_button_container_->GetPreferredSize(); - caption_button_container_->SetBounds(width() - preferred_size.width(), 0, - preferred_size.width(), preferred_size.height()); - } - - virtual void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) OVERRIDE { - if (details.is_add && details.child == this) { - caption_button_container_ = new FrameCaptionButtonContainerView( - GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - - // Set arbitrary images for the container's buttons so that the buttons - // have non-empty sizes. - for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) { - caption_button_container_->SetButtonImages( - static_cast<CaptionButtonIcon>(icon), - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE, - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - } - - AddChildView(caption_button_container_); - } - } - - // Not owned. - ash::FrameCaptionButtonContainerView* caption_button_container_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -class FrameMaximizeButtonTest : public ash::test::AshTestBase { - public: - FrameMaximizeButtonTest() {} - virtual ~FrameMaximizeButtonTest() {} - - // The returned widget takes ownership of |delegate|. - views::Widget* CreateWidget(views::WidgetDelegate* delegate) { - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - views::Widget* widget = new views::Widget; - params.context = CurrentContext(); - params.delegate = delegate; - params.bounds = gfx::Rect(10, 10, 100, 100); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - widget->Init(params); - widget->Show(); - return widget; - } - - void CloseWidget() { - if (widget_) - widget_->CloseNow(); - widget_ = NULL; - } - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDisableAlternateFrameCaptionButtonStyle); - - TestWidgetDelegate* delegate = new TestWidgetDelegate(); - widget_ = CreateWidget(delegate); - FrameCaptionButtonContainerView* caption_button_container = - delegate->caption_button_container(); - - FrameCaptionButtonContainerView::TestApi test(caption_button_container); - maximize_button_ = static_cast<FrameMaximizeButton*>( - test.size_button()); - } - - virtual void TearDown() OVERRIDE { - CloseWidget(); - AshTestBase::TearDown(); - } - - views::Widget* widget() { return widget_; } - - FrameMaximizeButton* maximize_button() { return maximize_button_; } - - private: - views::Widget* widget_; - FrameMaximizeButton* maximize_button_; - - DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButtonTest); -}; - -// Tests that clicking on the resize-button toggles between maximize and normal -// state. -TEST_F(FrameMaximizeButtonTest, ResizeButtonToggleMaximize) { - wm::WindowState* window_state = - wm::GetWindowState(widget()->GetNativeWindow()); - views::View* view = maximize_button(); - gfx::Point center = view->GetBoundsInScreen().CenterPoint(); - - aura::test::EventGenerator generator( - window_state->window()->GetRootWindow(), center); - - EXPECT_FALSE(window_state->IsMaximized()); - - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state->IsMaximized()); - - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state->IsMaximized()); - - generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); - EXPECT_FALSE(window_state->IsMaximized()); - - generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); - EXPECT_FALSE(window_state->IsMaximized()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_ResizeButtonDrag DISABLED_ResizeButtonDrag -#else -#define MAYBE_ResizeButtonDrag ResizeButtonDrag -#endif - -// Tests that click+dragging on the resize-button tiles or minimizes the window. -TEST_F(FrameMaximizeButtonTest, MAYBE_ResizeButtonDrag) { - aura::Window* window = widget()->GetNativeWindow(); - views::View* view = maximize_button(); - gfx::Point center = view->GetBoundsInScreen().CenterPoint(); - - aura::test::EventGenerator generator(window->GetRootWindow(), center); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsNormalStateType()); - - // Snap right. - { - generator.PressLeftButton(); - generator.MoveMouseBy(10, 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultRightSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); - } - - // Snap left. - { - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.PressLeftButton(); - generator.MoveMouseBy(-10, 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); - } - - // Minimize. - { - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.PressLeftButton(); - generator.MoveMouseBy(0, 10); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_TRUE(window_state->IsMinimized()); - } - - window_state->Restore(); - - // Now test the same behaviour for gesture events. - - // Snap right. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(80, 0); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - // This is a short resizing distance and different touch behavior - // applies which leads in half of the screen being used. - EXPECT_EQ("400,0 400x553", window->bounds().ToString()); - } - - // Snap left. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(-80, 0); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); - } - - // Minimize. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(0, 40); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_TRUE(window_state->IsMinimized()); - } - - // Test with gesture events. -} - -// Test that closing the (browser) window with an opened balloon does not -// crash the system. In other words: Make sure that shutting down the frame -// destroys the opened balloon in an orderly fashion. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonExternalShutDown) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Even though the widget is closing the bubble menu should not crash upon - // its delayed destruction. - CloseWidget(); -} - -// Test that maximizing the browser after hovering in does not crash the system -// when the observer gets removed in the bubble destruction process. -TEST_F(FrameMaximizeButtonTest, MaximizeOnHoverThenClick) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - generator.ClickLeftButton(); - EXPECT_TRUE(wm::GetWindowState(window)->IsMaximized()); -} - -// Test that hovering over a button in the balloon dialog will show the phantom -// window. Moving then away from the button will hide it again. Then check that -// pressing and dragging the button itself off the button will also release the -// phantom window. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftButtonDragOut) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Move the mouse over the left maximize button. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - - generator.MoveMouseTo(left_max_pos); - // Expect the phantom window to be open. - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Move away to see the window being destroyed. - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move back over the button. - generator.MoveMouseTo(button_pos); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Press button and drag out of dialog. - generator.PressLeftButton(); - generator.MoveMouseTo(off_pos); - generator.ReleaseLeftButton(); - - // Check that the phantom window is also gone. - EXPECT_FALSE(maximize_button->phantom_window_open()); -} - -// Test that clicking a button in the maximizer bubble (in this case the -// maximize left button) will do the requested action. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftByButton) { - aura::Window* window = widget()->GetNativeWindow(); - - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Move the mouse over the left maximize button. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - generator.ClickLeftButton(); - - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), - window->bounds().ToString()); -} - -// Test that the activation focus does not change when the bubble gets shown. -TEST_F(FrameMaximizeButtonTest, MaximizeKeepFocus) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - - aura::Window* active = - aura::client::GetFocusClient(window)->GetFocusedWindow(); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Check that the focused window is still the same. - EXPECT_EQ(active, aura::client::GetFocusClient(window)->GetFocusedWindow()); -} - -TEST_F(FrameMaximizeButtonTest, MaximizeTap) { - aura::Window* window = widget()->GetNativeWindow(); - aura::Window* root_window = window->GetRootWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - - const int touch_default_radius = - ui::GestureConfiguration::default_radius(); - ui::GestureConfiguration::set_default_radius(0); - - ui::EventProcessor* dispatcher = root_window->GetHost()->event_processor(); - const int kTouchId = 2; - ui::TouchEvent press(ui::ET_TOUCH_PRESSED, - button_pos, - kTouchId, - ui::EventTimeForNow()); - ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); - ASSERT_FALSE(details.dispatcher_destroyed); - - button_pos.Offset(9, 8); - ui::TouchEvent release( - ui::ET_TOUCH_RELEASED, - button_pos, - kTouchId, - press.time_stamp() + base::TimeDelta::FromMilliseconds(50)); - details = dispatcher->OnEventFromSource(&release); - ASSERT_FALSE(details.dispatcher_destroyed); - - ui::GestureConfiguration::set_default_radius(touch_default_radius); -} - -// Test that only the left button will activate the maximize button. -TEST_F(FrameMaximizeButtonTest, OnlyLeftButtonMaximizes) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsNormalStateType()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Move the mouse cursor over the button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // After pressing the left button the button should get triggered. - generator.PressLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(maximize_button->is_snap_enabled()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Pressing the right button then should cancel the operation. - generator.PressRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->maximizer()); - - // After releasing the second button the window shouldn't be maximized. - generator.ReleaseRightButton(); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state->IsMaximized()); - - // Second experiment: Starting with right should also not trigger. - generator.MoveMouseTo(off_pos); - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Pressing first the right button should not activate. - generator.PressRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->is_snap_enabled()); - - // Pressing then additionally the left button shouldn't activate either. - generator.PressLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->is_snap_enabled()); - generator.ReleaseRightButton(); - generator.ReleaseLeftButton(); - EXPECT_FALSE(window_state->IsMaximized()); -} - -// Click a button of window maximize functionality. -// If |snap_type| is SNAP_NONE the FrameMaximizeButton gets clicked, otherwise -// the associated snap button. -// |Window| is the window which owns the maximize button. -// |maximize_button| is the FrameMaximizeButton which controls the window. -void ClickMaxButton( - ash::FrameMaximizeButton* maximize_button, - aura::Window* window, - SnapType snap_type) { - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - if (snap_type != SNAP_NONE) { - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(snap_type)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - } - // After pressing the left button the button should get triggered. - generator.ClickLeftButton(); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Test that the restore from left/right maximize is properly done. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - wm::WindowState* window_state = wm::GetWindowState(window); - // The window should not be maximized. - EXPECT_FALSE(window_state->IsMaximized()); - // But the bounds should be different. - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(0, new_bounds.x()); - EXPECT_EQ(0, new_bounds.y()); - - // Now click the same button again to see that it restores. - ClickMaxButton(maximize_button, window, SNAP_LEFT); - // But the bounds should be restored. - new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Maximize, left/right maximize and then restore should works. -TEST_F(FrameMaximizeButtonTest, MaximizeMaximizeLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - EXPECT_FALSE(window_state->IsMaximized()); - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(0, new_bounds.x()); - EXPECT_EQ(0, new_bounds.y()); - - // Now click the same button again to see that it restores. - ClickMaxButton(maximize_button, window, SNAP_LEFT); - RunAllPendingInMessageLoop(); - // But the bounds should be restored. - new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Left/right maximize, maximize and then restore should work. -TEST_F(FrameMaximizeButtonTest, MaximizeSnapLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_FALSE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - EXPECT_TRUE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - EXPECT_FALSE(window_state->IsMaximized()); - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Test that minimizing the window per keyboard closes the maximize bubble. -TEST_F(FrameMaximizeButtonTest, MinimizePerKeyClosesBubble) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - - // Move the mouse cursor over the maximize button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // We simulate the keystroke by calling minimizeWindow directly. - wm::WindowState* window_state = wm::GetWindowState(window); - window_state->Minimize(); - - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Tests that dragging down on the maximize button minimizes the window. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragDownMinimizes) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - wm::WindowState* window_state = wm::GetWindowState(window); - // Drag down on a maximized window. - window_state->Maximize(); - EXPECT_TRUE(window_state->IsMaximized()); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x(), button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.GestureScrollSequence(button_pos, off_pos, - base::TimeDelta::FromMilliseconds(0), 1); - - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); - - // Drag down on a restored window. - window_state->Restore(); - - button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - off_pos = gfx::Point(button_pos.x(), button_pos.y() + 200); - generator.GestureScrollSequence(button_pos, off_pos, - base::TimeDelta::FromMilliseconds(10), 1); - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Tests that dragging Left and pressing ESC does properly abort. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragLeftEscapeExits) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() - button_pos.x() / 2, button_pos.y()); - - const int kGestureSteps = 10; - CancelCallbackHandler cancel_handler(kGestureSteps / 2, maximize_button); - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.GestureScrollSequenceWithCallback( - button_pos, - off_pos, - base::TimeDelta::FromMilliseconds(0), - kGestureSteps, - base::Bind(&CancelCallbackHandler::CountedCancelCallback, - base::Unretained(&cancel_handler))); - - // Check that there was no size change. - EXPECT_EQ(widget()->GetWindowBoundsInScreen().size().ToString(), - initial_bounds.size().ToString()); - // Check that there is no phantom window left open. - EXPECT_FALSE(maximize_button->phantom_window_open()); -} - -// Test that hovering over a button in the maximizer bubble and switching -// activation without moving the mouse properly aborts. -TEST_F(FrameMaximizeButtonTest, LossOfActivationWhileMaximizeBubbleOpenAborts) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_TRUE(widget()->IsActive()); - - // Move the mouse over the maximize button in order to bring up the maximizer - // bubble. - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Hover the mouse over the left maximize button in the maximizer bubble to - // show the phantom window. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Change activation by creating a new window. This could be done via an - // accelerator. The root window takes ownership of |just_created|. - views::Widget* just_created = views::Widget::CreateWindowWithContextAndBounds( - NULL, widget()->GetNativeWindow(), gfx::Rect(100, 100)); - just_created->Show(); - just_created->Activate(); - EXPECT_FALSE(widget()->IsActive()); - - // Test that we have properly reset the state of the now inactive window. - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); - EXPECT_EQ(initial_bounds.ToString(), window->GetBoundsInScreen().ToString()); -} - -} // namespace test -} // namespace ash diff --git a/ash/wm/caption_buttons/maximize_bubble_controller.cc b/ash/wm/caption_buttons/maximize_bubble_controller.cc deleted file mode 100644 index f01d0e2..0000000 --- a/ash/wm/caption_buttons/maximize_bubble_controller.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/maximize_bubble_controller.h" - -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller_bubble.h" -#include "base/timer/timer.h" - - -namespace ash { - -MaximizeBubbleController::MaximizeBubbleController( - FrameMaximizeButton* frame_maximize_button, - MaximizeBubbleFrameState maximize_type, - int appearance_delay_ms) - : frame_maximize_button_(frame_maximize_button), - bubble_(NULL), - maximize_type_(maximize_type), - snap_type_for_creation_(SNAP_NONE), - appearance_delay_ms_(appearance_delay_ms) { - // Create the task which will create the bubble delayed. - base::OneShotTimer<MaximizeBubbleController>* new_timer = - new base::OneShotTimer<MaximizeBubbleController>(); - // Note: Even if there was no delay time given, we need to have a timer. - new_timer->Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds( - appearance_delay_ms_ ? appearance_delay_ms_ : 10), - this, - &MaximizeBubbleController::CreateBubble); - timer_.reset(new_timer); - if (!appearance_delay_ms_) - CreateBubble(); -} - -MaximizeBubbleController::~MaximizeBubbleController() { - // Note: The destructor only gets initiated through the owner. - timer_.reset(); - if (bubble_) { - bubble_->ControllerRequestsCloseAndDelete(); - bubble_ = NULL; - } -} - -void MaximizeBubbleController::SetSnapType(SnapType snap_type) { - if (bubble_) { - bubble_->SetSnapType(snap_type); - } else { - // The bubble has not been created yet. This can occur if bubble creation is - // delayed. - snap_type_for_creation_ = snap_type; - } -} - -aura::Window* MaximizeBubbleController::GetBubbleWindow() { - return bubble_ ? bubble_->GetBubbleWindow() : NULL; -} - -void MaximizeBubbleController::DelayCreation() { - if (timer_.get() && timer_->IsRunning()) - timer_->Reset(); -} - -void MaximizeBubbleController::OnButtonClicked(SnapType snap_type) { - frame_maximize_button_->ExecuteSnapAndCloseMenu(snap_type); -} - -void MaximizeBubbleController::OnButtonHover(SnapType snap_type) { - frame_maximize_button_->SnapButtonHovered(snap_type); -} - -views::CustomButton* MaximizeBubbleController::GetButtonForUnitTest( - SnapType state) { - return bubble_ ? bubble_->GetButtonForUnitTest(state) : NULL; -} - -void MaximizeBubbleController::RequestDestructionThroughOwner() { - // Tell the parent to destroy us (if this didn't happen yet). - if (timer_) { - timer_.reset(NULL); - // Informs the owner that the menu is gone and requests |this| destruction. - frame_maximize_button_->DestroyMaximizeMenu(); - // Note: After this call |this| is destroyed. - } -} - -void MaximizeBubbleController::CreateBubble() { - if (!bubble_) { - bubble_ = new MaximizeBubbleControllerBubble(this, appearance_delay_ms_, - snap_type_for_creation_); - frame_maximize_button_->OnMaximizeBubbleShown(bubble_->GetWidget()); - } - - timer_->Stop(); -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/maximize_bubble_controller.h b/ash/wm/caption_buttons/maximize_bubble_controller.h deleted file mode 100644 index 53a07dd..0000000 --- a/ash/wm/caption_buttons/maximize_bubble_controller.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ -#define ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/memory/scoped_ptr.h" - -namespace aura { -class Window; -} - -namespace base { -class Timer; -} - -namespace views { -class CustomButton; -} - -namespace ash { - -class FrameMaximizeButton; -class MaximizeBubbleControllerBubble; - -// A class which shows a helper UI for the maximize button after a delay. -class ASH_EXPORT MaximizeBubbleController { - public: - MaximizeBubbleController(FrameMaximizeButton* frame_maximize_button, - MaximizeBubbleFrameState maximize_type, - int appearance_delay_ms); - // Called from the outside to destroy the interface to the UI visuals. - // The visuals will then delete when possible (maybe asynchronously). - virtual ~MaximizeBubbleController(); - - // Update the UI visuals to reflect the previewed |snap_type| snapping state. - void SetSnapType(SnapType snap_type); - - // To achieve proper Z-sorting with the snap animation, this window will be - // presented above the phantom window. - aura::Window* GetBubbleWindow(); - - // Reset the delay of the menu creation (if it was not created yet). - void DelayCreation(); - - // Called to tell the owning FrameMaximizeButton that a button was clicked. - void OnButtonClicked(SnapType snap_type); - - // Called to tell the the owning FrameMaximizeButton that the hover status - // for a button has changed. |snap_type| can be either SNAP_LEFT, SNAP_RIGHT, - // SNAP_MINIMIZE or SNAP_NONE. - void OnButtonHover(SnapType snap_type); - - // Get the owning FrameMaximizeButton. - FrameMaximizeButton* frame_maximize_button() { - return frame_maximize_button_; - } - - // The status of the associated window: Maximized or normal. - MaximizeBubbleFrameState maximize_type() const { return maximize_type_; } - - // A unit test function to return buttons of the sub menu. |state| can be - // either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - // Called from the the Bubble class to destroy itself: It tells the owning - // object that it will destroy itself asynchronously. The owner will then - // destroy |this|. - void RequestDestructionThroughOwner(); - - private: - // The function which creates the bubble once the delay is elapsed. - void CreateBubble(); - - // The owning button which is also the anchor for the menu. - FrameMaximizeButton* frame_maximize_button_; - - // The bubble menu. - MaximizeBubbleControllerBubble* bubble_; - - // The current maximize state of the owning window. - const MaximizeBubbleFrameState maximize_type_; - - // The snap type with which the bubble is created. This is needed because the - // creation of the bubble can be delayed and SetSnapType() may be called - // before the bubble is created. - SnapType snap_type_for_creation_; - - // The timer for the delayed creation of the menu. - scoped_ptr<base::Timer> timer_; - - // The appearance delay in ms (delay and fade in & fade out delay). - const int appearance_delay_ms_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleController); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ diff --git a/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc b/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc deleted file mode 100644 index 2753659..0000000 --- a/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright 2013 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 "ash/wm/caption_buttons/maximize_bubble_controller_bubble.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/caption_buttons/bubble_contents_button_row.h" -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "grit/ash_strings.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/path.h" -#include "ui/views/bubble/bubble_frame_view.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/mouse_watcher.h" -#include "ui/wm/public/masked_window_targeter.h" - -namespace ash { - -// BubbleContentsView --------------------------------------------------------- - -// A class which creates the content of the bubble: The buttons, and the label. -class BubbleContentsView : public views::View { - public: - BubbleContentsView(MaximizeBubbleControllerBubble* bubble, - SnapType initial_snap_type); - virtual ~BubbleContentsView(); - - // Set the label content to reflect the currently selected |snap_type|. - // This function can be executed through the frame maximize button as well as - // through hover operations. - void SetSnapType(SnapType snap_type); - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - private: - // The owning class. - MaximizeBubbleControllerBubble* bubble_; - - // The object which owns all the buttons. - BubbleContentsButtonRow* buttons_view_; - - // The label object which shows the user the selected action. - views::Label* label_view_; - - DISALLOW_COPY_AND_ASSIGN(BubbleContentsView); -}; - -BubbleContentsView::BubbleContentsView( - MaximizeBubbleControllerBubble* bubble, - SnapType initial_snap_type) - : bubble_(bubble), - buttons_view_(NULL), - label_view_(NULL) { - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kVertical, 0, 0, - MaximizeBubbleControllerBubble::kLayoutSpacing)); - set_background(views::Background::CreateSolidBackground( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor)); - - buttons_view_ = new BubbleContentsButtonRow(bubble); - AddChildView(buttons_view_); - - label_view_ = new views::Label(); - SetSnapType(initial_snap_type); - label_view_->SetBackgroundColor( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - const SkColor kBubbleTextColor = SK_ColorWHITE; - label_view_->SetEnabledColor(kBubbleTextColor); - const int kLabelSpacing = 4; - label_view_->SetBorder( - views::Border::CreateEmptyBorder(kLabelSpacing, 0, kLabelSpacing, 0)); - AddChildView(label_view_); -} - -BubbleContentsView::~BubbleContentsView() { -} - -// Set the label content to reflect the currently selected |snap_type|. -// This function can be executed through the frame maximize button as well as -// through hover operations. -void BubbleContentsView::SetSnapType(SnapType snap_type) { - if (!bubble_->controller()) - return; - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - int id = 0; - switch (snap_type) { - case SNAP_LEFT: - id = IDS_ASH_SNAP_WINDOW_LEFT; - break; - case SNAP_RIGHT: - id = IDS_ASH_SNAP_WINDOW_RIGHT; - break; - case SNAP_MAXIMIZE: - DCHECK_NE(FRAME_STATE_FULL, bubble_->controller()->maximize_type()); - id = IDS_ASH_MAXIMIZE_WINDOW; - break; - case SNAP_MINIMIZE: - id = IDS_ASH_MINIMIZE_WINDOW; - break; - case SNAP_RESTORE: - DCHECK_NE(FRAME_STATE_NONE, bubble_->controller()->maximize_type()); - id = IDS_ASH_RESTORE_WINDOW; - break; - default: - // If nothing is selected, we automatically select the click operation. - id = bubble_->controller()->maximize_type() == FRAME_STATE_FULL ? - IDS_ASH_RESTORE_WINDOW : IDS_ASH_MAXIMIZE_WINDOW; - break; - } - label_view_->SetText(rb.GetLocalizedString(id)); -} - -views::CustomButton* BubbleContentsView::GetButtonForUnitTest(SnapType state) { - return buttons_view_->GetButtonForUnitTest(state); -} - - -// MaximizeBubbleBorder ------------------------------------------------------- - -namespace { - -const int kLineWidth = 1; -const int kArrowHeight = 10; -const int kArrowWidth = 20; - -} // namespace - -class MaximizeBubbleBorder : public views::BubbleBorder { - public: - MaximizeBubbleBorder(views::View* content_view, views::View* anchor); - - virtual ~MaximizeBubbleBorder() {} - - // Get the mouse active area of the window. - void GetMask(gfx::Path* mask); - - // views::BubbleBorder: - virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const OVERRIDE; - virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE; - virtual gfx::Size GetMinimumSize() const OVERRIDE; - - private: - // Note: Animations can continue after then main window frame was destroyed. - // To avoid this problem, the owning screen metrics get extracted upon - // creation. - gfx::Size anchor_size_; - gfx::Point anchor_screen_origin_; - views::View* content_view_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleBorder); -}; - -MaximizeBubbleBorder::MaximizeBubbleBorder(views::View* content_view, - views::View* anchor) - : views::BubbleBorder( - views::BubbleBorder::TOP_RIGHT, views::BubbleBorder::NO_SHADOW, - MaximizeBubbleControllerBubble::kBubbleBackgroundColor), - anchor_size_(anchor->size()), - anchor_screen_origin_(0, 0), - content_view_(content_view) { - views::View::ConvertPointToScreen(anchor, &anchor_screen_origin_); - set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); -} - -void MaximizeBubbleBorder::GetMask(gfx::Path* mask) { - gfx::Insets inset = GetInsets(); - // Note: Even though the tip could be added as activatable, it is left out - // since it would not change the action behavior in any way plus it makes - // more sense to keep the focus on the underlying button for clicks. - int left = inset.left() - kLineWidth; - int right = inset.left() + content_view_->width() + kLineWidth; - int top = inset.top() - kLineWidth; - int bottom = inset.top() + content_view_->height() + kLineWidth; - mask->moveTo(left, top); - mask->lineTo(right, top); - mask->lineTo(right, bottom); - mask->lineTo(left, bottom); - mask->lineTo(left, top); - mask->close(); -} - -gfx::Rect MaximizeBubbleBorder::GetBounds( - const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const { - gfx::Size border_size(contents_size); - gfx::Insets insets = GetInsets(); - border_size.Enlarge(insets.width(), insets.height()); - - // Position the bubble to center the box on the anchor. - int x = (anchor_size_.width() - border_size.width()) / 2; - // Position the bubble under the anchor, overlapping the arrow with it. - int y = anchor_size_.height() - insets.top(); - - gfx::Point view_origin(x + anchor_screen_origin_.x(), - y + anchor_screen_origin_.y()); - - return gfx::Rect(view_origin, border_size); -} - -void MaximizeBubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) { - gfx::Insets inset = GetInsets(); - - // Draw the border line around everything. - int y = inset.top(); - // Top - canvas->FillRect(gfx::Rect(inset.left(), - y - kLineWidth, - content_view_->width(), - kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Bottom - canvas->FillRect(gfx::Rect(inset.left(), - y + content_view_->height(), - content_view_->width(), - kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Left - canvas->FillRect(gfx::Rect(inset.left() - kLineWidth, - y - kLineWidth, - kLineWidth, - content_view_->height() + 2 * kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Right - canvas->FillRect(gfx::Rect(inset.left() + content_view_->width(), - y - kLineWidth, - kLineWidth, - content_view_->height() + 2 * kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - - // Draw the arrow afterwards covering the border. - SkPath path; - path.incReserve(4); - // The center of the tip should be in the middle of the button. - int tip_x = inset.left() + content_view_->width() / 2; - int left_base_x = tip_x - kArrowWidth / 2; - int left_base_y = y; - int tip_y = left_base_y - kArrowHeight; - path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); - path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); - path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), - SkIntToScalar(left_base_y)); - - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - canvas->DrawPath(path, paint); -} - -gfx::Size MaximizeBubbleBorder::GetMinimumSize() const { - return gfx::Size(kLineWidth * 2 + kArrowWidth, - std::max(kLineWidth, kArrowHeight) + kLineWidth); -} - -namespace { - -// MaximizebubbleTargeter ----------------------------------------------------- - -// Window targeter used for the bubble. -class MaximizeBubbleTargeter : public ::wm::MaskedWindowTargeter { - public: - MaximizeBubbleTargeter(aura::Window* window, - MaximizeBubbleBorder* border) - : ::wm::MaskedWindowTargeter(window), - border_(border) { - } - - virtual ~MaximizeBubbleTargeter() {} - - private: - // ::wm::MaskedWindowTargeter: - virtual bool GetHitTestMask(aura::Window* window, - gfx::Path* mask) const OVERRIDE { - border_->GetMask(mask); - return true; - } - - MaximizeBubbleBorder* border_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleTargeter); -}; - -} // namespace - - -// BubbleMouseWatcherHost ----------------------------------------------------- - -// The mouse watcher host which makes sure that the bubble does not get closed -// while the mouse cursor is over the maximize button or the balloon content. -// Note: This object gets destroyed when the MouseWatcher gets destroyed. -class BubbleMouseWatcherHost: public views::MouseWatcherHost { - public: - explicit BubbleMouseWatcherHost(MaximizeBubbleControllerBubble* bubble); - virtual ~BubbleMouseWatcherHost(); - - // views::MouseWatcherHost: - virtual bool Contains(const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) OVERRIDE; - private: - MaximizeBubbleControllerBubble* bubble_; - - DISALLOW_COPY_AND_ASSIGN(BubbleMouseWatcherHost); -}; - -BubbleMouseWatcherHost::BubbleMouseWatcherHost( - MaximizeBubbleControllerBubble* bubble) - : bubble_(bubble) { -} - -BubbleMouseWatcherHost::~BubbleMouseWatcherHost() { -} - -bool BubbleMouseWatcherHost::Contains( - const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) { - return bubble_->Contains(screen_point, type); -} - - -// MaximizeBubbleControllerBubble --------------------------------------------- - -// static -const SkColor MaximizeBubbleControllerBubble::kBubbleBackgroundColor = - 0xFF141414; -const int MaximizeBubbleControllerBubble::kLayoutSpacing = -1; - -MaximizeBubbleControllerBubble::MaximizeBubbleControllerBubble( - MaximizeBubbleController* owner, - int appearance_delay_ms, - SnapType initial_snap_type) - : views::BubbleDelegateView(owner->frame_maximize_button(), - views::BubbleBorder::TOP_RIGHT), - shutting_down_(false), - owner_(owner), - contents_view_(NULL), - bubble_border_(NULL), - appearance_delay_ms_(appearance_delay_ms) { - set_margins(gfx::Insets()); - - // The window needs to be owned by the root so that the phantom window does - // not cover it upon animation. - aura::Window* parent = Shell::GetContainer( - Shell::GetTargetRootWindow(), - internal::kShellWindowId_ShelfContainer); - set_parent_window(parent); - - set_notify_enter_exit_on_child(true); - set_adjust_if_offscreen(false); - SetPaintToLayer(true); - set_color(kBubbleBackgroundColor); - set_close_on_deactivate(false); - set_background( - views::Background::CreateSolidBackground(kBubbleBackgroundColor)); - - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kVertical, 0, 0, kLayoutSpacing)); - - contents_view_ = new BubbleContentsView(this, initial_snap_type); - AddChildView(contents_view_); - - // Note that the returned widget has an observer which points to our - // functions. - views::Widget* bubble_widget = views::BubbleDelegateView::CreateBubble(this); - bubble_widget->set_focus_on_creation(false); - - SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); - bubble_widget->non_client_view()->frame_view()->set_background(NULL); - - bubble_border_ = new MaximizeBubbleBorder(this, GetAnchorView()); - GetBubbleFrameView()->SetBubbleBorder( - scoped_ptr<views::BubbleBorder>(bubble_border_)); - GetBubbleFrameView()->set_background(NULL); - - // Recalculate size with new border. - SizeToContents(); - - GetWidget()->Show(); - - aura::Window* window = bubble_widget->GetNativeWindow(); - window->SetEventTargeter(scoped_ptr<ui::EventTargeter>( - new MaximizeBubbleTargeter(window, bubble_border_))); - - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - ash::UMA_WINDOW_MAXIMIZE_BUTTON_SHOW_BUBBLE); - - mouse_watcher_.reset(new views::MouseWatcher( - new BubbleMouseWatcherHost(this), - this)); - mouse_watcher_->Start(); -} - -MaximizeBubbleControllerBubble::~MaximizeBubbleControllerBubble() { -} - -aura::Window* MaximizeBubbleControllerBubble::GetBubbleWindow() { - return GetWidget()->GetNativeWindow(); -} - -gfx::Rect MaximizeBubbleControllerBubble::GetAnchorRect() { - if (!owner_) - return gfx::Rect(); - - gfx::Rect anchor_rect = - owner_->frame_maximize_button()->GetBoundsInScreen(); - return anchor_rect; -} - -bool MaximizeBubbleControllerBubble::CanActivate() const { - return false; -} - -bool MaximizeBubbleControllerBubble::WidgetHasHitTestMask() const { - return bubble_border_ != NULL; -} - -void MaximizeBubbleControllerBubble::GetWidgetHitTestMask( - gfx::Path* mask) const { - DCHECK(mask); - DCHECK(bubble_border_); - bubble_border_->GetMask(mask); -} - -void MaximizeBubbleControllerBubble::MouseMovedOutOfHost() { - if (!owner_ || shutting_down_) - return; - // When we leave the bubble, we might be still be in gesture mode or over - // the maximize button. So only close if none of the other cases apply. - if (!owner_->frame_maximize_button()->is_snap_enabled()) { - gfx::Point screen_location = Shell::GetScreen()->GetCursorScreenPoint(); - if (!owner_->frame_maximize_button()->GetBoundsInScreen().Contains( - screen_location)) { - owner_->RequestDestructionThroughOwner(); - } - } -} - -bool MaximizeBubbleControllerBubble::Contains( - const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) { - if (!owner_ || shutting_down_) - return false; - bool inside_button = - owner_->frame_maximize_button()->GetBoundsInScreen().Contains( - screen_point); - if (!owner_->frame_maximize_button()->is_snap_enabled() && inside_button) { - SetSnapType(controller()->maximize_type() == FRAME_STATE_FULL ? - SNAP_RESTORE : SNAP_MAXIMIZE); - return true; - } - // Check if either a gesture is taking place (=> bubble stays no matter what - // the mouse does) or the mouse is over the maximize button or the bubble - // content. - return (owner_->frame_maximize_button()->is_snap_enabled() || - inside_button || - contents_view_->GetBoundsInScreen().Contains(screen_point)); -} - -gfx::Size MaximizeBubbleControllerBubble::GetPreferredSize() { - return contents_view_->GetPreferredSize(); -} - -void MaximizeBubbleControllerBubble::OnWidgetDestroying(views::Widget* widget) { - if (GetWidget() == widget) { - mouse_watcher_->Stop(); - - if (owner_) { - // If the bubble destruction was triggered by some other external - // influence then ourselves, the owner needs to be informed that the menu - // is gone. - shutting_down_ = true; - owner_->RequestDestructionThroughOwner(); - owner_ = NULL; - } - } - BubbleDelegateView::OnWidgetDestroying(widget); -} - -void MaximizeBubbleControllerBubble::ControllerRequestsCloseAndDelete() { - // This only gets called from the owning base class once it is deleted. - if (shutting_down_) - return; - shutting_down_ = true; - owner_ = NULL; - - // Close the widget asynchronously after the hide animation is finished. - if (!appearance_delay_ms_) - GetWidget()->CloseNow(); - else - GetWidget()->Close(); -} - -void MaximizeBubbleControllerBubble::SetSnapType(SnapType snap_type) { - if (contents_view_) - contents_view_->SetSnapType(snap_type); -} - -views::CustomButton* MaximizeBubbleControllerBubble::GetButtonForUnitTest( - SnapType state) { - return contents_view_->GetButtonForUnitTest(state); -} - -} // namespace ash diff --git a/ash/wm/caption_buttons/maximize_bubble_controller_bubble.h b/ash/wm/caption_buttons/maximize_bubble_controller_bubble.h deleted file mode 100644 index 39f7ee2..0000000 --- a/ash/wm/caption_buttons/maximize_bubble_controller_bubble.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ -#define ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ - -#include "ash/wm/workspace/snap_types.h" -#include "ui/views/bubble/bubble_delegate.h" -#include "ui/views/mouse_watcher.h" - -namespace views { -class CustomButton; -} - -namespace ash { - -class BubbleContentsView; -class MaximizeBubbleBorder; -class MaximizeBubbleController; - -// The class which creates and manages the bubble menu element. -// It creates a 'bubble border' and the content accordingly. -// Note: Since the phantom window will show animations on top of the maximize -// button this menu gets created as a separate window and the phantom window -// will be created underneath this window. -class MaximizeBubbleControllerBubble : public views::BubbleDelegateView, - public views::MouseWatcherListener { - public: - static const SkColor kBubbleBackgroundColor; - static const int kLayoutSpacing; // The spacing between two buttons. - - MaximizeBubbleControllerBubble(MaximizeBubbleController* owner, - int appearance_delay_ms, - SnapType initial_snap_type); - virtual ~MaximizeBubbleControllerBubble(); - - // The window of the menu under which the phantom window will get created. - aura::Window* GetBubbleWindow(); - - // Overridden from views::BubbleDelegateView. - virtual gfx::Rect GetAnchorRect() OVERRIDE; - virtual bool CanActivate() const OVERRIDE; - - // Overridden from views::WidgetDelegateView. - virtual bool WidgetHasHitTestMask() const OVERRIDE; - virtual void GetWidgetHitTestMask(gfx::Path* mask) const OVERRIDE; - - // Implementation of MouseWatcherListener. - virtual void MouseMovedOutOfHost() OVERRIDE; - - // Implementation of MouseWatcherHost. - virtual bool Contains(const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type); - - // Overridden from views::View. - virtual gfx::Size GetPreferredSize() OVERRIDE; - - // Overridden from views::Widget::Observer. - virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; - - // Called from the controller class to indicate that the menu should get - // destroyed. - virtual void ControllerRequestsCloseAndDelete(); - - // Called from the owning class to change the menu content to the given - // |snap_type| so that the user knows what is selected. - void SetSnapType(SnapType snap_type); - - // Get the owning MaximizeBubbleController. This might return NULL in case - // of an asynchronous shutdown. - MaximizeBubbleController* controller() const { return owner_; } - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - private: - // True if the shut down has been initiated. - bool shutting_down_; - - // Our owning class. - MaximizeBubbleController* owner_; - - // The content accessor of the menu. - BubbleContentsView* contents_view_; - - // The bubble border (weak reference). - MaximizeBubbleBorder* bubble_border_; - - // The mouse watcher which takes care of out of window hover events. - scoped_ptr<views::MouseWatcher> mouse_watcher_; - - // The fade delay - if 0 it will show / hide immediately. - const int appearance_delay_ms_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleControllerBubble); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ diff --git a/ash/wm/custom_frame_view_ash.cc b/ash/wm/custom_frame_view_ash.cc deleted file mode 100644 index 4eb5c8f..0000000 --- a/ash/wm/custom_frame_view_ash.cc +++ /dev/null @@ -1,520 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/wm/custom_frame_view_ash.h" - -#include "ash/ash_switches.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "ash/wm/caption_buttons/frame_maximize_button_observer.h" -#include "ash/wm/frame_border_hit_test_controller.h" -#include "ash/wm/header_painter.h" -#include "ash/wm/immersive_fullscreen_controller.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_state_delegate.h" -#include "ash/wm/window_state_observer.h" -#include "base/command_line.h" -#include "base/debug/leak_annotations.h" -#include "grit/ash_resources.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/rect_conversions.h" -#include "ui/gfx/size.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" -#include "ui/views/widget/widget_deletion_observer.h" - -namespace { - -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; -} - -/////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAshWindowStateDelegate - -// Handles a user's fullscreen request (Shift+F4/F4). Puts the window into -// immersive fullscreen if immersive fullscreen is enabled for non-browser -// windows. -class CustomFrameViewAshWindowStateDelegate - : public ash::wm::WindowStateDelegate, - public ash::wm::WindowStateObserver, - public aura::WindowObserver { - public: - CustomFrameViewAshWindowStateDelegate( - ash::wm::WindowState* window_state, - ash::CustomFrameViewAsh* custom_frame_view) - : window_state_(NULL) { -#if defined(OS_CHROMEOS) - // TODO(pkotwicz): Investigate if immersive fullscreen can be enabled for - // Windows Ash. - if (ash::switches::UseImmersiveFullscreenForAllWindows()) { - immersive_fullscreen_controller_.reset( - new ash::ImmersiveFullscreenController); - custom_frame_view->InitImmersiveFullscreenControllerForView( - immersive_fullscreen_controller_.get()); - - // Add a window state observer to exit fullscreen properly in case - // fullscreen is exited without going through - // WindowState::ToggleFullscreen(). This is the case when exiting - // immersive fullscreen via the "Restore" window control. - // TODO(pkotwicz): This is a hack. Remove ASAP. http://crbug.com/319048 - window_state_ = window_state; - window_state_->AddObserver(this); - window_state_->window()->AddObserver(this); - } -#endif - } - virtual ~CustomFrameViewAshWindowStateDelegate() { - if (window_state_) { - window_state_->RemoveObserver(this); - window_state_->window()->RemoveObserver(this); - } - } - private: - // Overridden from ash::wm::WindowStateDelegate: - virtual bool ToggleFullscreen(ash::wm::WindowState* window_state) OVERRIDE { - bool enter_fullscreen = !window_state->IsFullscreen(); - if (enter_fullscreen) { - window_state->window()->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - } else { - window_state->Restore(); - } - if (immersive_fullscreen_controller_) { - immersive_fullscreen_controller_->SetEnabled( - ash::ImmersiveFullscreenController::WINDOW_TYPE_OTHER, - enter_fullscreen); - } - return true; - } - // Overridden from aura::WindowObserver: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { - window_state_->RemoveObserver(this); - window_state_->window()->RemoveObserver(this); - window_state_ = NULL; - } - // Overridden from ash::wm::WindowStateObserver: - virtual void OnPostWindowStateTypeChange( - ash::wm::WindowState* window_state, - ash::wm::WindowStateType old_type) OVERRIDE { - if (!window_state->IsFullscreen() && - !window_state->IsMinimized() && - immersive_fullscreen_controller_.get() && - immersive_fullscreen_controller_->IsEnabled()) { - immersive_fullscreen_controller_->SetEnabled( - ash::ImmersiveFullscreenController::WINDOW_TYPE_OTHER, - false); - } - } - - ash::wm::WindowState* window_state_; - scoped_ptr<ash::ImmersiveFullscreenController> - immersive_fullscreen_controller_; - - DISALLOW_COPY_AND_ASSIGN(CustomFrameViewAshWindowStateDelegate); -}; - -} // namespace - -namespace ash { - -/////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh::HeaderView - -// View which paints the header. It slides off and on screen in immersive -// fullscreen. -class CustomFrameViewAsh::HeaderView - : public views::View, - public ImmersiveFullscreenController::Delegate, - public FrameMaximizeButtonObserver { - public: - // |frame| is the widget that the caption buttons act on. - explicit HeaderView(views::Widget* frame); - virtual ~HeaderView(); - - // Schedules a repaint for the entire title. - void SchedulePaintForTitle(); - - // Tells the window controls to reset themselves to the normal state. - void ResetWindowControls(); - - // Returns the amount of the view's pixels which should be on screen. - int GetPreferredOnScreenHeight() const; - - // Returns the view's preferred height. - int GetPreferredHeight() const; - - // Returns the view's minimum width. - int GetMinimumWidth() const; - - // views::View overrides: - virtual void Layout() OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - - HeaderPainter* header_painter() { - return header_painter_.get(); - } - - private: - // ImmersiveFullscreenController::Delegate overrides: - virtual void OnImmersiveRevealStarted() OVERRIDE; - virtual void OnImmersiveRevealEnded() OVERRIDE; - virtual void OnImmersiveFullscreenExited() OVERRIDE; - virtual void SetVisibleFraction(double visible_fraction) OVERRIDE; - virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE; - - // FrameMaximizeButtonObserver overrides: - virtual void OnMaximizeBubbleShown(views::Widget* bubble) OVERRIDE; - - // The widget that the caption buttons act on. - views::Widget* frame_; - - // Helper for painting the header. - scoped_ptr<HeaderPainter> header_painter_; - - // View which contains the window caption buttons. - FrameCaptionButtonContainerView* caption_button_container_; - - // The maximize bubble widget. |maximize_bubble_| may be non-NULL but have - // been already destroyed. - views::Widget* maximize_bubble_; - - // Keeps track of whether |maximize_bubble_| is still alive. - scoped_ptr<views::WidgetDeletionObserver> maximize_bubble_lifetime_observer_; - - // The fraction of the header's height which is visible while in fullscreen. - // This value is meaningless when not in fullscreen. - double fullscreen_visible_fraction_; - - DISALLOW_COPY_AND_ASSIGN(HeaderView); -}; - -CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame) - : frame_(frame), - header_painter_(new ash::HeaderPainter), - caption_button_container_(NULL), - maximize_bubble_(NULL), - fullscreen_visible_fraction_(0) { - // Unfortunately, there is no views::WidgetDelegate::CanMinimize(). Assume - // that the window frame can be minimized if it can be maximized. - FrameCaptionButtonContainerView::MinimizeAllowed minimize_allowed = - frame_->widget_delegate()->CanMaximize() ? - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED : - FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED; - caption_button_container_ = new FrameCaptionButtonContainerView(frame_, - minimize_allowed); - AddChildView(caption_button_container_); - FrameMaximizeButton* frame_maximize_button = - caption_button_container_->GetOldStyleSizeButton(); - if (frame_maximize_button) - frame_maximize_button->AddObserver(this); - - header_painter_->Init(HeaderPainter::STYLE_OTHER, frame_, this, NULL, - caption_button_container_); -} - -CustomFrameViewAsh::HeaderView::~HeaderView() { - FrameMaximizeButton* frame_maximize_button = - caption_button_container_->GetOldStyleSizeButton(); - if (frame_maximize_button) - frame_maximize_button->RemoveObserver(this); -} - -void CustomFrameViewAsh::HeaderView::SchedulePaintForTitle() { - header_painter_->SchedulePaintForTitle(GetTitleFontList()); -} - -void CustomFrameViewAsh::HeaderView::ResetWindowControls() { - caption_button_container_->ResetWindowControls(); -} - -int CustomFrameViewAsh::HeaderView::GetPreferredOnScreenHeight() const { - if (frame_->IsFullscreen()) { - return static_cast<int>( - GetPreferredHeight() * fullscreen_visible_fraction_); - } - return GetPreferredHeight(); -} - -int CustomFrameViewAsh::HeaderView::GetPreferredHeight() const { - // Reserve enough space to see the buttons and the separator line. - return caption_button_container_->bounds().bottom() + - header_painter_->HeaderContentSeparatorSize(); -} - -int CustomFrameViewAsh::HeaderView::GetMinimumWidth() const { - return header_painter_->GetMinimumHeaderWidth(); -} - -void CustomFrameViewAsh::HeaderView::Layout() { - header_painter_->LayoutHeader(); - header_painter_->set_header_height(GetPreferredHeight()); -} - -void CustomFrameViewAsh::HeaderView::OnPaint(gfx::Canvas* canvas) { - bool paint_as_active = - frame_->non_client_view()->frame_view()->ShouldPaintAsActive(); - caption_button_container_->SetPaintAsActive(paint_as_active); - - int theme_image_id = 0; - if (paint_as_active) - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_ACTIVE; - else - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_INACTIVE; - - HeaderPainter::Mode header_mode = paint_as_active ? - HeaderPainter::MODE_ACTIVE : HeaderPainter::MODE_INACTIVE; - header_painter_->PaintHeader( - canvas, - header_mode, - theme_image_id, - 0); - header_painter_->PaintTitleBar(canvas, GetTitleFontList()); - header_painter_->PaintHeaderContentSeparator(canvas, header_mode); -} - -void CustomFrameViewAsh::HeaderView::OnImmersiveRevealStarted() { - fullscreen_visible_fraction_ = 0; - SetPaintToLayer(true); - SetFillsBoundsOpaquely(false); - parent()->Layout(); -} - -void CustomFrameViewAsh::HeaderView::OnImmersiveRevealEnded() { - fullscreen_visible_fraction_ = 0; - SetPaintToLayer(false); - parent()->Layout(); -} - -void CustomFrameViewAsh::HeaderView::OnImmersiveFullscreenExited() { - fullscreen_visible_fraction_ = 0; - SetPaintToLayer(false); - parent()->Layout(); -} - -void CustomFrameViewAsh::HeaderView::SetVisibleFraction( - double visible_fraction) { - if (fullscreen_visible_fraction_ != visible_fraction) { - fullscreen_visible_fraction_ = visible_fraction; - parent()->Layout(); - } -} - -std::vector<gfx::Rect> -CustomFrameViewAsh::HeaderView::GetVisibleBoundsInScreen() const { - // TODO(pkotwicz): Implement views::View::ConvertRectToScreen(). - gfx::Rect visible_bounds(GetVisibleBounds()); - gfx::Point visible_origin_in_screen(visible_bounds.origin()); - views::View::ConvertPointToScreen(this, &visible_origin_in_screen); - std::vector<gfx::Rect> bounds_in_screen; - bounds_in_screen.push_back( - gfx::Rect(visible_origin_in_screen, visible_bounds.size())); - if (maximize_bubble_lifetime_observer_.get() && - maximize_bubble_lifetime_observer_->IsWidgetAlive()) { - bounds_in_screen.push_back(maximize_bubble_->GetWindowBoundsInScreen()); - } - return bounds_in_screen; -} - -void CustomFrameViewAsh::HeaderView::OnMaximizeBubbleShown( - views::Widget* bubble) { - maximize_bubble_ = bubble; - maximize_bubble_lifetime_observer_.reset( - new views::WidgetDeletionObserver(bubble)); -} - -/////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh::OverlayView - -// View which takes up the entire widget and contains the HeaderView. HeaderView -// is a child of OverlayView to avoid creating a larger texture than necessary -// when painting the HeaderView to its own layer. -class CustomFrameViewAsh::OverlayView : public views::View { - public: - explicit OverlayView(HeaderView* header_view); - virtual ~OverlayView(); - - // views::View override: - virtual void Layout() OVERRIDE; - virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; - - private: - HeaderView* header_view_; - - DISALLOW_COPY_AND_ASSIGN(OverlayView); -}; - -CustomFrameViewAsh::OverlayView::OverlayView(HeaderView* header_view) - : header_view_(header_view) { - AddChildView(header_view); -} - -CustomFrameViewAsh::OverlayView::~OverlayView() { -} - -void CustomFrameViewAsh::OverlayView::Layout() { - // Layout |header_view_| because layout affects the result of - // GetPreferredOnScreenHeight(). - header_view_->Layout(); - - int onscreen_height = header_view_->GetPreferredOnScreenHeight(); - if (onscreen_height == 0) { - header_view_->SetVisible(false); - } else { - int height = header_view_->GetPreferredHeight(); - header_view_->SetBounds(0, onscreen_height - height, width(), height); - header_view_->SetVisible(true); - } -} - -bool CustomFrameViewAsh::OverlayView::HitTestRect(const gfx::Rect& rect) const { - // Grab events in the header view. Return false for other events so that they - // can be handled by the client view. - return header_view_->HitTestRect(rect); -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, public: - -// static -const char CustomFrameViewAsh::kViewClassName[] = "CustomFrameViewAsh"; - -CustomFrameViewAsh::CustomFrameViewAsh(views::Widget* frame) - : frame_(frame), - header_view_(new HeaderView(frame)), - frame_border_hit_test_controller_( - new FrameBorderHitTestController(frame_)) { - // |header_view_| is set as the non client view's overlay view so that it can - // overlay the web contents in immersive fullscreen. - frame->non_client_view()->SetOverlayView(new OverlayView(header_view_)); - - // A delegate for a more complex way of fullscreening the window may already - // be set. This is the case for packaged apps. - wm::WindowState* window_state = wm::GetWindowState(frame->GetNativeWindow()); - if (!window_state->HasDelegate()) { - window_state->SetDelegate(scoped_ptr<wm::WindowStateDelegate>( - new CustomFrameViewAshWindowStateDelegate( - window_state, this))); - } -} - -CustomFrameViewAsh::~CustomFrameViewAsh() { -} - -void CustomFrameViewAsh::InitImmersiveFullscreenControllerForView( - ImmersiveFullscreenController* immersive_fullscreen_controller) { - immersive_fullscreen_controller->Init(header_view_, frame_, header_view_); -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, views::NonClientFrameView overrides: - -gfx::Rect CustomFrameViewAsh::GetBoundsForClientView() const { - int top_height = NonClientTopBorderHeight(); - return HeaderPainter::GetBoundsForClientView(top_height, bounds()); -} - -gfx::Rect CustomFrameViewAsh::GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const { - int top_height = NonClientTopBorderHeight(); - return HeaderPainter::GetWindowBoundsForClientBounds(top_height, - client_bounds); -} - -int CustomFrameViewAsh::NonClientHitTest(const gfx::Point& point) { - return FrameBorderHitTestController::NonClientHitTest(this, - header_view_->header_painter(), point); -} - -void CustomFrameViewAsh::GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) { - // No window masks in Aura. -} - -void CustomFrameViewAsh::ResetWindowControls() { - header_view_->ResetWindowControls(); -} - -void CustomFrameViewAsh::UpdateWindowIcon() { -} - -void CustomFrameViewAsh::UpdateWindowTitle() { - header_view_->SchedulePaintForTitle(); -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, views::View overrides: - -gfx::Size CustomFrameViewAsh::GetPreferredSize() { - gfx::Size pref = frame_->client_view()->GetPreferredSize(); - gfx::Rect bounds(0, 0, pref.width(), pref.height()); - return frame_->non_client_view()->GetWindowBoundsForClientBounds( - bounds).size(); -} - -const char* CustomFrameViewAsh::GetClassName() const { - return kViewClassName; -} - -gfx::Size CustomFrameViewAsh::GetMinimumSize() { - 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 CustomFrameViewAsh::GetMaximumSize() { - 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 CustomFrameViewAsh::SchedulePaintInRect(const gfx::Rect& r) { - // We may end up here before |header_view_| has been added to the Widget. - if (header_view_->GetWidget()) { - // The HeaderView is not a child of CustomFrameViewAsh. Redirect the paint - // to HeaderView instead. - gfx::RectF to_paint(r); - views::View::ConvertRectToTarget(this, header_view_, &to_paint); - header_view_->SchedulePaintInRect(gfx::ToEnclosingRect(to_paint)); - } else { - views::NonClientFrameView::SchedulePaintInRect(r); - } -} - -bool CustomFrameViewAsh::HitTestRect(const gfx::Rect& rect) const { - // NonClientView hit tests the NonClientFrameView first instead of going in - // z-order. Return false so that events get to the OverlayView. - return false; -} - -views::View* CustomFrameViewAsh::GetHeaderView() { - return header_view_; -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, private: - -int CustomFrameViewAsh::NonClientTopBorderHeight() const { - return frame_->IsFullscreen() ? 0 : header_view_->GetPreferredHeight(); -} - -} // namespace ash diff --git a/ash/wm/custom_frame_view_ash.h b/ash/wm/custom_frame_view_ash.h deleted file mode 100644 index c7b09f1..0000000 --- a/ash/wm/custom_frame_view_ash.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_CUSTOM_FRAME_VIEW_ASH_H_ -#define ASH_WM_CUSTOM_FRAME_VIEW_ASH_H_ - -#include "ash/ash_export.h" -#include "base/memory/scoped_ptr.h" -#include "ui/views/window/non_client_view.h" - -namespace ash { -class FrameBorderHitTestController; -class HeaderPainter; -class ImmersiveFullscreenController; -} -namespace views { -class Widget; -} - -namespace ash { - -// A NonClientFrameView used for packaged apps, dialogs and other non-browser -// windows. It supports immersive fullscreen. When in immersive fullscreen, the -// client view takes up the entire widget and the window header is an overlay. -// The window header overlay slides onscreen when the user hovers the mouse at -// the top of the screen. See also views::CustomFrameView and -// BrowserNonClientFrameViewAsh. -class ASH_EXPORT CustomFrameViewAsh : public views::NonClientFrameView { - public: - // Internal class name. - static const char kViewClassName[]; - - explicit CustomFrameViewAsh(views::Widget* frame); - virtual ~CustomFrameViewAsh(); - - // Inits |immersive_fullscreen_controller| so that the controller reveals - // and hides |header_view_| in immersive fullscreen. - // CustomFrameViewAsh does not take ownership of - // |immersive_fullscreen_controller|. - void InitImmersiveFullscreenControllerForView( - ImmersiveFullscreenController* immersive_fullscreen_controller); - - // views::NonClientFrameView overrides: - virtual gfx::Rect GetBoundsForClientView() const OVERRIDE; - virtual gfx::Rect GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const OVERRIDE; - virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE; - virtual void GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) OVERRIDE; - virtual void ResetWindowControls() OVERRIDE; - virtual void UpdateWindowIcon() OVERRIDE; - virtual void UpdateWindowTitle() OVERRIDE; - - // views::View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual const char* GetClassName() const OVERRIDE; - virtual gfx::Size GetMinimumSize() OVERRIDE; - virtual gfx::Size GetMaximumSize() OVERRIDE; - virtual void SchedulePaintInRect(const gfx::Rect& r) OVERRIDE; - virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; - - // Get the view of the header. - views::View* GetHeaderView(); - - private: - class OverlayView; - friend class TestWidgetConstraintsDelegate; - - // Height from top of window to top of client area. - int NonClientTopBorderHeight() const; - - // Not owned. - views::Widget* frame_; - - // View which contains the title and window controls. - class HeaderView; - HeaderView* header_view_; - - // Updates the hittest bounds overrides based on the window state type. - scoped_ptr<FrameBorderHitTestController> frame_border_hit_test_controller_; - - DISALLOW_COPY_AND_ASSIGN(CustomFrameViewAsh); -}; - -} // namespace ash - -#endif // ASH_WM_CUSTOM_FRAME_VIEW_ASH_H_ diff --git a/ash/wm/custom_frame_view_ash_unittest.cc b/ash/wm/custom_frame_view_ash_unittest.cc deleted file mode 100644 index 953b55c..0000000 --- a/ash/wm/custom_frame_view_ash_unittest.cc +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2014 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 "ash/wm/custom_frame_view_ash.h" - -#include "ash/test/ash_test_base.h" -#include "base/memory/scoped_ptr.h" -#include "grit/ash_resources.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -// A views::WidgetDelegate which uses a CustomFrameViewAsh. -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate() { - } - virtual ~TestWidgetDelegate() { - } - - virtual views::NonClientFrameView* CreateNonClientFrameView( - views::Widget* widget) OVERRIDE { - custom_frame_view_ = new CustomFrameViewAsh(widget); - return custom_frame_view_; - } - - CustomFrameViewAsh* custom_frame_view() const { - return custom_frame_view_; - } - - private: - // Not owned. - CustomFrameViewAsh* custom_frame_view_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -class TestWidgetConstraintsDelegate : public TestWidgetDelegate { - public: - TestWidgetConstraintsDelegate() { - } - virtual ~TestWidgetConstraintsDelegate() { - } - - // views::View implementation. - virtual gfx::Size GetMinimumSize() OVERRIDE { - return minimum_size_; - } - - virtual gfx::Size GetMaximumSize() OVERRIDE { - return maximum_size_; - } - - virtual views::View* GetContentsView() OVERRIDE { - // Set this instance as the contents view so that the maximum and minimum - // size constraints will be used. - return this; - } - - void set_minimum_size(const gfx::Size& min_size) { - minimum_size_ = min_size; - } - - void set_maximum_size(const gfx::Size& max_size) { - maximum_size_ = max_size; - } - - int GetTitleBarHeight() const { - return custom_frame_view()->NonClientTopBorderHeight(); - } - - private: - gfx::Size minimum_size_; - gfx::Size maximum_size_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetConstraintsDelegate); -}; - -class CustomFrameViewAshTest : public test::AshTestBase { - public: - CustomFrameViewAshTest() {} - virtual ~CustomFrameViewAshTest() {} - - protected: - scoped_ptr<views::Widget> CreateWidget(TestWidgetDelegate* delegate) { - scoped_ptr<views::Widget> widget(new views::Widget); - views::Widget::InitParams params; - params.delegate = delegate; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.bounds = gfx::Rect(0, 0, 100, 100); - params.context = CurrentContext(); - widget->Init(params); - return widget.Pass(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(CustomFrameViewAshTest); -}; - -// Test that the height of the header is correct upon initially displaying -// the widget. -TEST_F(CustomFrameViewAshTest, HeaderHeight) { - TestWidgetDelegate* delegate = new TestWidgetDelegate; - - scoped_ptr<views::Widget> widget(CreateWidget(delegate)); - widget->Show(); - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - gfx::ImageSkia* close_button = - rb.GetImageSkiaNamed(IDR_AURA_WINDOW_CONTROL_BACKGROUND_H); - - // |kSeparatorSize| should match |kHeaderContentSeparatorSize| in - // header_painter.cc - // TODO(pkotwicz): Clean this test up once the separator overlays the window - // controls. - const int kSeparatorSize = 1; - - // The header should have enough room for the window controls and the - // separator line. - EXPECT_EQ(close_button->height() + kSeparatorSize, - delegate->custom_frame_view()->GetHeaderView()->height()); - - widget->Maximize(); - EXPECT_EQ(close_button->height() + kSeparatorSize, - delegate->custom_frame_view()->GetHeaderView()->height()); -} - -// Verify that CustomFrameViewAsh returns the correct minimum and maximum frame -// sizes when the client view does not specify any size constraints. -TEST_F(CustomFrameViewAshTest, NoSizeConstraints) { - TestWidgetConstraintsDelegate* delegate = new TestWidgetConstraintsDelegate; - scoped_ptr<views::Widget> widget(CreateWidget(delegate)); - - CustomFrameViewAsh* custom_frame_view = delegate->custom_frame_view(); - gfx::Size min_frame_size = custom_frame_view->GetMinimumSize(); - gfx::Size max_frame_size = custom_frame_view->GetMaximumSize(); - - EXPECT_EQ(delegate->GetTitleBarHeight(), min_frame_size.height()); - - // A width and height constraint of 0 denotes unbounded. - EXPECT_EQ(0, max_frame_size.width()); - EXPECT_EQ(0, max_frame_size.height()); -} - -// Verify that CustomFrameViewAsh returns the correct minimum and maximum frame -// sizes when the client view specifies size constraints. -TEST_F(CustomFrameViewAshTest, MinimumAndMaximumSize) { - gfx::Size min_client_size(500, 500); - gfx::Size max_client_size(800, 800); - TestWidgetConstraintsDelegate* delegate = new TestWidgetConstraintsDelegate; - delegate->set_minimum_size(min_client_size); - delegate->set_maximum_size(max_client_size); - scoped_ptr<views::Widget> widget(CreateWidget(delegate)); - - CustomFrameViewAsh* custom_frame_view = delegate->custom_frame_view(); - gfx::Size min_frame_size = custom_frame_view->GetMinimumSize(); - gfx::Size max_frame_size = custom_frame_view->GetMaximumSize(); - - EXPECT_EQ(min_client_size.width(), min_frame_size.width()); - EXPECT_EQ(max_client_size.width(), max_frame_size.width()); - EXPECT_EQ(min_client_size.height() + delegate->GetTitleBarHeight(), - min_frame_size.height()); - EXPECT_EQ(max_client_size.height() + delegate->GetTitleBarHeight(), - max_frame_size.height()); -} - -} // namespace ash diff --git a/ash/wm/frame_border_hit_test_controller.cc b/ash/wm/frame_border_hit_test_controller.cc deleted file mode 100644 index 238a977..0000000 --- a/ash/wm/frame_border_hit_test_controller.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2013 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 "ash/wm/frame_border_hit_test_controller.h" - -#include "ash/ash_constants.h" -#include "ash/wm/header_painter.h" -#include "ash/wm/resize_handle_window_targeter.h" -#include "ash/wm/window_state_observer.h" -#include "ui/aura/env.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/aura/window_targeter.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 ash { - -FrameBorderHitTestController::FrameBorderHitTestController(views::Widget* frame) - : frame_window_(frame->GetNativeWindow()) { - frame_window_->SetEventTargeter(scoped_ptr<ui::EventTargeter>( - new ResizeHandleWindowTargeter(frame_window_, NULL))); -} - -FrameBorderHitTestController::~FrameBorderHitTestController() { -} - -// static -int FrameBorderHitTestController::NonClientHitTest( - views::NonClientFrameView* view, - HeaderPainter* header_painter, - const gfx::Point& point) { - 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)) - 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 = - frame->IsMaximized() || frame->IsFullscreen() ? 0 : - kResizeInsideBoundsSize; - int frame_component = view->GetHTComponentForFrame(point, - resize_border, - resize_border, - kResizeAreaCornerSize, - kResizeAreaCornerSize, - can_ever_resize); - if (frame_component != HTNOWHERE) - return frame_component; - - int client_component = frame->client_view()->NonClientHitTest(point); - if (client_component != HTNOWHERE) - return client_component; - - return header_painter->NonClientHitTest(point); -} - -} // namespace ash diff --git a/ash/wm/frame_border_hit_test_controller.h b/ash/wm/frame_border_hit_test_controller.h deleted file mode 100644 index 126f406..0000000 --- a/ash/wm/frame_border_hit_test_controller.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_FRAME_BORDER_HITTEST_CONTROLLER_H_ -#define ASH_WM_FRAME_BORDER_HITTEST_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" - -namespace aura { -class Window; -} - -namespace gfx { -class Point; -} - -namespace views { -class NonClientFrameView; -class Widget; -} - -namespace ash { -class HeaderPainter; - -// Class which manages the hittest override bounds for |frame|. -class ASH_EXPORT FrameBorderHitTestController { - public: - explicit FrameBorderHitTestController(views::Widget* frame); - virtual ~FrameBorderHitTestController(); - - // Does the non client hit test on behalf of |view|. |point| must be in the - // coordinates of |view|'s widget. - static int NonClientHitTest(views::NonClientFrameView* view, - HeaderPainter* header_painter, - const gfx::Point& point); - - private: - // The window whose hittest override bounds are being managed. - aura::Window* frame_window_; - - DISALLOW_COPY_AND_ASSIGN(FrameBorderHitTestController); -}; - -} // namespace ash - -#endif // ASH_WM_FRAME_BORDER_HITTEST_CONTROLLER_H_ diff --git a/ash/wm/header_painter.cc b/ash/wm/header_painter.cc deleted file mode 100644 index c6db020..0000000 --- a/ash/wm/header_painter.cc +++ /dev/null @@ -1,625 +0,0 @@ -// Copyright 2013 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 "ash/wm/header_painter.h" - -#include <vector> - -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "base/logging.h" // DCHECK -#include "grit/ash_resources.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/window.h" -#include "ui/base/hit_test.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/base/theme_provider.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/skia_util.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -using aura::Window; -using views::Widget; - -namespace { -// Space between left edge of window and popup window icon. -const int kIconOffsetX = 9; -// Height and width of window icon. -const int kIconSize = 16; -// Space between the title text and the caption buttons. -const int kTitleLogoSpacing = 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; -// Color for the non-maximized window title text. -const SkColor kNonMaximizedWindowTitleTextColor = SkColorSetRGB(40, 40, 40); -// Color for the maximized window title text. -const SkColor kMaximizedWindowTitleTextColor = SK_ColorWHITE; -// Size of header/content separator line below the header image for non-browser -// windows. -const int kHeaderContentSeparatorSize = 1; -// Color of the active window header/content separator line for non-browser -// windows. -const SkColor kHeaderContentSeparatorColor = SkColorSetRGB(180, 180, 182); -// Color of the inactive window header/content separator line for non-browser -// windows. -const SkColor kHeaderContentSeparatorInactiveColor = - SkColorSetRGB(150, 150, 152); -// 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; -// Duration of crossfade animation for activating and deactivating frame. -const int kActivationCrossfadeDurationMs = 200; - -// Tiles an image into an area, rounding the top corners. Samples |image| -// starting |image_inset_x| pixels from the left of the image. -void TileRoundRect(gfx::Canvas* canvas, - const gfx::ImageSkia& image, - const SkPaint& paint, - const gfx::Rect& bounds, - int top_left_corner_radius, - int top_right_corner_radius, - int image_inset_x) { - SkRect rect = gfx::RectToSkRect(bounds); - const SkScalar kTopLeftRadius = SkIntToScalar(top_left_corner_radius); - const SkScalar kTopRightRadius = SkIntToScalar(top_right_corner_radius); - SkScalar radii[8] = { - kTopLeftRadius, kTopLeftRadius, // top-left - kTopRightRadius, kTopRightRadius, // top-right - 0, 0, // bottom-right - 0, 0}; // bottom-left - SkPath path; - path.addRoundRect(rect, radii, SkPath::kCW_Direction); - canvas->DrawImageInPath(image, -image_inset_x, 0, path, paint); -} - -// Tiles |frame_image| and |frame_overlay_image| into an area, rounding the top -// corners. -void PaintFrameImagesInRoundRect(gfx::Canvas* canvas, - const gfx::ImageSkia* frame_image, - const gfx::ImageSkia* frame_overlay_image, - const SkPaint& paint, - const gfx::Rect& bounds, - int corner_radius, - int image_inset_x) { - SkXfermode::Mode normal_mode; - SkXfermode::AsMode(NULL, &normal_mode); - - // If |paint| is using an unusual SkXfermode::Mode (this is the case while - // crossfading), we must create a new canvas to overlay |frame_image| and - // |frame_overlay_image| using |normal_mode| and then paint the result - // using the unusual mode. We try to avoid this because creating a new - // browser-width canvas is expensive. - bool fast_path = (!frame_overlay_image || - SkXfermode::IsMode(paint.getXfermode(), normal_mode)); - if (fast_path) { - TileRoundRect(canvas, *frame_image, paint, bounds, corner_radius, - corner_radius, image_inset_x); - - if (frame_overlay_image) { - // Adjust |bounds| such that |frame_overlay_image| is not tiled. - gfx::Rect overlay_bounds = bounds; - overlay_bounds.Intersect( - gfx::Rect(bounds.origin(), frame_overlay_image->size())); - int top_left_corner_radius = corner_radius; - int top_right_corner_radius = corner_radius; - if (overlay_bounds.width() < bounds.width() - corner_radius) - top_right_corner_radius = 0; - TileRoundRect(canvas, *frame_overlay_image, paint, overlay_bounds, - top_left_corner_radius, top_right_corner_radius, 0); - } - } else { - gfx::Canvas temporary_canvas(bounds.size(), canvas->image_scale(), false); - temporary_canvas.TileImageInt(*frame_image, - image_inset_x, 0, - 0, 0, - bounds.width(), bounds.height()); - temporary_canvas.DrawImageInt(*frame_overlay_image, 0, 0); - TileRoundRect(canvas, gfx::ImageSkia(temporary_canvas.ExtractImageRep()), - paint, bounds, corner_radius, corner_radius, 0); - } -} - -} // namespace - -namespace ash { - -/////////////////////////////////////////////////////////////////////////////// -// HeaderPainter, public: - -HeaderPainter::HeaderPainter() - : frame_(NULL), - header_view_(NULL), - window_icon_(NULL), - caption_button_container_(NULL), - header_height_(0), - previous_theme_frame_id_(0), - previous_theme_frame_overlay_id_(0), - crossfade_theme_frame_id_(0), - crossfade_theme_frame_overlay_id_(0) {} - -HeaderPainter::~HeaderPainter() { -} - -void HeaderPainter::Init( - Style style, - views::Widget* frame, - views::View* header_view, - views::View* window_icon, - FrameCaptionButtonContainerView* caption_button_container) { - DCHECK(frame); - DCHECK(header_view); - // window_icon may be NULL. - DCHECK(caption_button_container); - style_ = style; - frame_ = frame; - header_view_ = header_view; - window_icon_ = window_icon; - caption_button_container_ = caption_button_container; -} - -// static -gfx::Rect HeaderPainter::GetBoundsForClientView( - int header_height, - const gfx::Rect& window_bounds) { - gfx::Rect client_bounds(window_bounds); - client_bounds.Inset(0, header_height, 0, 0); - return client_bounds; -} - -// static -gfx::Rect HeaderPainter::GetWindowBoundsForClientBounds( - int header_height, - const gfx::Rect& client_bounds) { - gfx::Rect window_bounds(client_bounds); - window_bounds.Inset(0, -header_height, 0, 0); - return window_bounds; -} - -int HeaderPainter::NonClientHitTest(const gfx::Point& point) const { - gfx::Point point_in_header_view(point); - views::View::ConvertPointFromWidget(header_view_, &point_in_header_view); - if (!GetHeaderLocalBounds().Contains(point_in_header_view)) - return HTNOWHERE; - if (caption_button_container_->visible()) { - gfx::Point point_in_caption_button_container(point); - views::View::ConvertPointFromWidget(caption_button_container_, - &point_in_caption_button_container); - int component = caption_button_container_->NonClientHitTest( - point_in_caption_button_container); - if (component != HTNOWHERE) - return component; - } - // Caption is a safe default. - return HTCAPTION; -} - -int HeaderPainter::GetMinimumHeaderWidth() const { - // Ensure we have enough space for the window icon and buttons. We allow - // the title string to collapse to zero width. - return GetTitleOffsetX() + - caption_button_container_->GetMinimumSize().width(); -} - -int HeaderPainter::GetRightInset() const { - return caption_button_container_->GetPreferredSize().width(); -} - -int HeaderPainter::GetThemeBackgroundXInset() const { - return kThemeFrameImageInsetX; -} - -void HeaderPainter::PaintHeader(gfx::Canvas* canvas, - Mode mode, - int theme_frame_id, - int theme_frame_overlay_id) { - bool initial_paint = (previous_theme_frame_id_ == 0); - if (!initial_paint && - (previous_theme_frame_id_ != theme_frame_id || - previous_theme_frame_overlay_id_ != theme_frame_overlay_id)) { - aura::Window* parent = frame_->GetNativeWindow()->parent(); - // Don't animate the header if the parent (a workspace) is already - // animating. Doing so results in continually painting during the animation - // and gives a slower frame rate. - // TODO(sky): expose a better way to determine this rather than assuming - // the parent is a workspace. - bool parent_animating = parent && - (parent->layer()->GetAnimator()->IsAnimatingProperty( - ui::LayerAnimationElement::OPACITY) || - parent->layer()->GetAnimator()->IsAnimatingProperty( - ui::LayerAnimationElement::VISIBILITY)); - if (!parent_animating) { - crossfade_animation_.reset(new gfx::SlideAnimation(this)); - crossfade_theme_frame_id_ = previous_theme_frame_id_; - crossfade_theme_frame_overlay_id_ = previous_theme_frame_overlay_id_; - crossfade_animation_->SetSlideDuration(kActivationCrossfadeDurationMs); - crossfade_animation_->Show(); - } else { - crossfade_animation_.reset(); - } - } - - ui::ThemeProvider* theme_provider = frame_->GetThemeProvider(); - gfx::ImageSkia* theme_frame = theme_provider->GetImageSkiaNamed( - theme_frame_id); - gfx::ImageSkia* theme_frame_overlay = NULL; - if (theme_frame_overlay_id != 0) { - theme_frame_overlay = theme_provider->GetImageSkiaNamed( - theme_frame_overlay_id); - } - - int corner_radius = GetHeaderCornerRadius(); - SkPaint paint; - - if (crossfade_animation_.get() && crossfade_animation_->is_animating()) { - gfx::ImageSkia* crossfade_theme_frame = - theme_provider->GetImageSkiaNamed(crossfade_theme_frame_id_); - gfx::ImageSkia* crossfade_theme_frame_overlay = NULL; - if (crossfade_theme_frame_overlay_id_ != 0) { - crossfade_theme_frame_overlay = theme_provider->GetImageSkiaNamed( - crossfade_theme_frame_overlay_id_); - } - if (!crossfade_theme_frame || - (crossfade_theme_frame_overlay_id_ != 0 && - !crossfade_theme_frame_overlay)) { - // Reset the animation. This case occurs when the user switches the theme - // that they are using. - crossfade_animation_.reset(); - } else { - int old_alpha = crossfade_animation_->CurrentValueBetween(255, 0); - int new_alpha = 255 - old_alpha; - - // Draw the old header background, clipping the corners to be rounded. - paint.setAlpha(old_alpha); - paint.setXfermodeMode(SkXfermode::kPlus_Mode); - PaintFrameImagesInRoundRect(canvas, - crossfade_theme_frame, - crossfade_theme_frame_overlay, - paint, - GetHeaderLocalBounds(), - corner_radius, - GetThemeBackgroundXInset()); - - paint.setAlpha(new_alpha); - } - } - - // Draw the header background, clipping the corners to be rounded. - PaintFrameImagesInRoundRect(canvas, - theme_frame, - theme_frame_overlay, - paint, - GetHeaderLocalBounds(), - corner_radius, - GetThemeBackgroundXInset()); - - previous_theme_frame_id_ = theme_frame_id; - previous_theme_frame_overlay_id_ = theme_frame_overlay_id; - - PaintBorder(canvas, mode); -} - -void HeaderPainter::PaintHeaderContentSeparator(gfx::Canvas* canvas, - Mode mode) { - DCHECK_EQ(style_, STYLE_OTHER); - SkColor color = (mode == MODE_ACTIVE) ? - kHeaderContentSeparatorColor : - kHeaderContentSeparatorInactiveColor; - - canvas->FillRect(gfx::Rect(0, - header_height_ - kHeaderContentSeparatorSize, - header_view_->width(), - kHeaderContentSeparatorSize), - color); -} - -int HeaderPainter::HeaderContentSeparatorSize() const { - return kHeaderContentSeparatorSize; -} - -void HeaderPainter::PaintTitleBar(gfx::Canvas* canvas, - const gfx::FontList& title_font_list) { - // The window icon is painted by its own views::View. - views::WidgetDelegate* delegate = frame_->widget_delegate(); - if (delegate && delegate->ShouldShowWindowTitle()) { - gfx::Rect title_bounds = GetTitleBounds(title_font_list); - title_bounds.set_x(header_view_->GetMirroredXForRect(title_bounds)); - SkColor title_color = (frame_->IsMaximized() || frame_->IsFullscreen()) ? - kMaximizedWindowTitleTextColor : kNonMaximizedWindowTitleTextColor; - canvas->DrawStringRectWithFlags(delegate->GetWindowTitle(), - title_font_list, - title_color, - title_bounds, - gfx::Canvas::NO_SUBPIXEL_RENDERING); - } -} - -void HeaderPainter::LayoutHeader() { - // Purposefully set |header_height_| to an invalid value. We cannot use - // |header_height_| because the computation of |header_height_| may depend - // on having laid out the window controls. - header_height_ = -1; - - UpdateCaptionButtonImages(); - caption_button_container_->Layout(); - - gfx::Size caption_button_container_size = - caption_button_container_->GetPreferredSize(); - caption_button_container_->SetBounds( - header_view_->width() - caption_button_container_size.width(), - 0, - caption_button_container_size.width(), - caption_button_container_size.height()); - - if (window_icon_) { - // Vertically center the window icon with respect to the caption button - // container. - int icon_offset_y = - GetCaptionButtonContainerCenterY() - window_icon_->height() / 2; - window_icon_->SetBounds(kIconOffsetX, icon_offset_y, kIconSize, kIconSize); - } -} - -void HeaderPainter::SchedulePaintForTitle( - const gfx::FontList& title_font_list) { - header_view_->SchedulePaintInRect(GetTitleBounds(title_font_list)); -} - -void HeaderPainter::OnThemeChanged() { - // We do not cache the images for |previous_theme_frame_id_| and - // |previous_theme_frame_overlay_id_|. Changing the theme changes the images - // returned from ui::ThemeProvider for |previous_theme_frame_id_| - // and |previous_theme_frame_overlay_id_|. Reset the image ids to prevent - // starting a crossfade animation with these images. - previous_theme_frame_id_ = 0; - previous_theme_frame_overlay_id_ = 0; - - if (crossfade_animation_.get() && crossfade_animation_->is_animating()) { - crossfade_animation_.reset(); - header_view_->SchedulePaintInRect(GetHeaderLocalBounds()); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// gfx::AnimationDelegate overrides: - -void HeaderPainter::AnimationProgressed(const gfx::Animation* animation) { - header_view_->SchedulePaintInRect(GetHeaderLocalBounds()); -} - -/////////////////////////////////////////////////////////////////////////////// -// HeaderPainter, private: - -void HeaderPainter::PaintBorder(gfx::Canvas* canvas, Mode mode) { - if (frame_->IsMaximized() || - frame_->IsFullscreen() || - (style_ == STYLE_OTHER && mode == MODE_ACTIVE)) { - return; - } - - gfx::ImageSkia top_left_corner; - gfx::ImageSkia top_right_corner; - gfx::ImageSkia top_edge; - gfx::ImageSkia left_edge; - gfx::ImageSkia right_edge; - gfx::ImageSkia bottom_edge; - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - if (style_ == STYLE_BROWSER) { - top_left_corner = *rb.GetImageSkiaNamed( - IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_TOP_LEFT); - top_right_corner = *rb.GetImageSkiaNamed( - IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_TOP_RIGHT); - top_edge = *rb.GetImageSkiaNamed(IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_TOP); - left_edge = *rb.GetImageSkiaNamed( - IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_LEFT); - right_edge = *rb.GetImageSkiaNamed( - IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_RIGHT); - } else { - top_edge = *rb.GetImageSkiaNamed( - IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_TOP); - left_edge = *rb.GetImageSkiaNamed( - IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_LEFT); - right_edge = *rb.GetImageSkiaNamed( - IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_RIGHT); - bottom_edge = *rb.GetImageSkiaNamed( - IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_BOTTOM); - } - - DCHECK(!top_edge.isNull()); - DCHECK(!left_edge.isNull()); - DCHECK(!right_edge.isNull()); - - int top_left_width = top_left_corner.width(); - int top_left_height = top_left_corner.height(); - if (!top_left_corner.isNull()) { - canvas->DrawImageInt(top_left_corner, 0, 0); - } - - int top_right_height = top_right_corner.height(); - if (!top_right_corner.isNull()) { - canvas->DrawImageInt(top_right_corner, - header_view_->width() - top_right_corner.width(), - top_right_height); - } - - canvas->TileImageInt(top_edge, - top_left_width, - 0, - header_view_->width() - top_left_width - top_right_corner.width(), - top_edge.height()); - - // TODO(pkotwicz): Compute |bottom| more accurately. The computation is - // inaccurate for browser windows. - int bottom = header_height_ - kHeaderContentSeparatorSize; - int bottom_height = bottom_edge.height(); - if (!bottom_edge.isNull()) { - canvas->TileImageInt(bottom_edge, - 0, bottom - bottom_height, - header_view_->width(), bottom_height); - } - - int left_edge_height = bottom - bottom_height - top_left_height; - canvas->TileImageInt(left_edge, - 0, top_left_height, - left_edge.width(), left_edge_height); - - int right_edge_height = bottom - bottom_height - top_right_height; - canvas->TileImageInt(right_edge, - header_view_->width() - right_edge.width(), - top_right_height, - right_edge.width(), - right_edge_height); -} - -void HeaderPainter::UpdateCaptionButtonImages() { - if (style_ == STYLE_BROWSER) { - if (frame_->IsMaximized() || frame_->IsFullscreen()) { - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_MINIMIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_MINIMIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_MINIMIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_SIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_SIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_CLOSE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_CLOSE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_CLOSE, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_LEFT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_LEFT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_LEFT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_RIGHT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_RIGHT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P); - } else { - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_MINIMIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_MINIMIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_MINIMIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_SIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_SIZE, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_CLOSE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_CLOSE, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_CLOSE, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_LEFT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_LEFT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_LEFT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_RIGHT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_RIGHT_SNAPPED, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H, - IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P); - } - } else { - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_MINIMIZE, - IDR_AURA_WINDOW_CONTROL_ICON_MINIMIZE, - IDR_AURA_WINDOW_CONTROL_ICON_MINIMIZE_I, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, - IDR_AURA_WINDOW_CONTROL_ICON_SIZE, - IDR_AURA_WINDOW_CONTROL_ICON_SIZE_I, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_CLOSE, - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE, - IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - - // There is no dedicated icon for the snap-left and snap-right buttons - // when |frame_| is inactive because they should never be visible while - // |frame_| is inactive. - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_LEFT_SNAPPED, - IDR_AURA_WINDOW_CONTROL_ICON_LEFT_SNAPPED, - IDR_AURA_WINDOW_CONTROL_ICON_LEFT_SNAPPED, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - caption_button_container_->SetButtonImages( - CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - IDR_AURA_WINDOW_CONTROL_ICON_RIGHT_SNAPPED, - IDR_AURA_WINDOW_CONTROL_ICON_RIGHT_SNAPPED, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, - IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); - } -} - -gfx::Rect HeaderPainter::GetHeaderLocalBounds() const { - return gfx::Rect(header_view_->width(), header_height_); -} - -int HeaderPainter::GetTitleOffsetX() const { - return window_icon_ ? - window_icon_->bounds().right() + kTitleIconOffsetX : - kTitleNoIconOffsetX; -} - -int HeaderPainter::GetCaptionButtonContainerCenterY() const { - return caption_button_container_->y() + - caption_button_container_->height() / 2; -} - -int HeaderPainter::GetHeaderCornerRadius() const { - bool square_corners = (frame_->IsMaximized() || frame_->IsFullscreen()); - const int kCornerRadius = 2; - return square_corners ? 0 : kCornerRadius; -} - -gfx::Rect HeaderPainter::GetTitleBounds(const gfx::FontList& title_font_list) { - int title_x = GetTitleOffsetX(); - // Center the text with respect to the caption button container. This way it - // adapts to the caption button height and aligns exactly with the window - // icon. Don't use |window_icon_| for this computation as it may be NULL. - int title_y = - GetCaptionButtonContainerCenterY() - title_font_list.GetHeight() / 2; - return gfx::Rect( - title_x, - std::max(0, title_y), - std::max(0, caption_button_container_->x() - kTitleLogoSpacing - title_x), - title_font_list.GetHeight()); -} - -} // namespace ash diff --git a/ash/wm/header_painter.h b/ash/wm/header_painter.h deleted file mode 100644 index dd9f5f2..0000000 --- a/ash/wm/header_painter.h +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_HEADER_PAINTER_H_ -#define ASH_WM_HEADER_PAINTER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" // OVERRIDE -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/geometry/rect.h" - -namespace gfx { -class Canvas; -class FontList; -class ImageSkia; -class Point; -class Size; -class SlideAnimation; -} -namespace views { -class View; -class Widget; -} - -namespace ash { -class FrameCaptionButtonContainerView; - -// Helper class for painting the window header. -class ASH_EXPORT HeaderPainter : public gfx::AnimationDelegate { - public: - enum Mode { - MODE_ACTIVE, - MODE_INACTIVE - }; - - // TODO(pkotwicz): Move code related to "browser" windows out of ash. - enum Style { - // Header style used for browser windows. - STYLE_BROWSER, - - // Header style used for apps and miscellaneous windows (e.g. task manager). - STYLE_OTHER - }; - - HeaderPainter(); - virtual ~HeaderPainter(); - - // None of the parameters are owned. - void Init(Style style, - views::Widget* frame, - views::View* header_view, - views::View* window_icon, - FrameCaptionButtonContainerView* caption_button_container); - - // Returns the bounds of the client view for a window with |header_height| - // and |window_bounds|. The return value and |window_bounds| are in the - // views::NonClientView's coordinates. - static gfx::Rect GetBoundsForClientView(int header_height, - const gfx::Rect& window_bounds); - - // Returns the bounds of the window given |header_height| and |client_bounds|. - // The return value and |client_bounds| are in the views::NonClientView's - // coordinates. - static gfx::Rect GetWindowBoundsForClientBounds( - int header_height, - const gfx::Rect& client_bounds); - - // Determines the window HT* code at |point|. Returns HTNOWHERE if |point| is - // not within the top |header_height_| of |header_view_|. |point| is in the - // coordinates of |header_view_|'s widget. The client view must be hittested - // before calling this method because a browser's tabs are in the top - // |header_height_| of |header_view_|. - int NonClientHitTest(const gfx::Point& point) const; - - // Returns the header's minimum width. - int GetMinimumHeaderWidth() const; - - // Returns the inset from the right edge. - int GetRightInset() const; - - // Returns the amount that the theme background should be inset. - int GetThemeBackgroundXInset() const; - - // Paints the header. - // |theme_frame_overlay_id| is 0 if no overlay image should be used. - // |mode| indicates whether the window should be painted as active. - void PaintHeader(gfx::Canvas* canvas, - Mode mode, - int theme_frame_id, - int theme_frame_overlay_id); - - // Paints the header/content separator line for non-browser windows. - void PaintHeaderContentSeparator(gfx::Canvas* canvas, Mode mode); - - // Returns size of the header/content separator line for non-browser windows - // in pixels. - int HeaderContentSeparatorSize() const; - - // Paint the title bar, primarily the title string. - void PaintTitleBar(gfx::Canvas* canvas, const gfx::FontList& title_font_list); - - // Performs layout for the header based on |frame_|'s show state. - void LayoutHeader(); - - // Sets the height of the header. The height of the header affects painting, - // and non client hit tests. It does not affect layout. - void set_header_height(int header_height) { - header_height_ = header_height; - } - - // Returns the header height. - int header_height() const { - return header_height_; - } - - // Schedule a re-paint of the entire title. - void SchedulePaintForTitle(const gfx::FontList& title_font_list); - - // Called when the browser theme changes. - void OnThemeChanged(); - - // Overridden from gfx::AnimationDelegate - virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(HeaderPainterTest, TitleIconAlignment); - - // Paints the border around the header. - void PaintBorder(gfx::Canvas* canvas, Mode mode); - - // Updates the images used for the minimize, restore and close buttons. - void UpdateCaptionButtonImages(); - - // Returns the header bounds in the coordinates of |header_view_|. The header - // is assumed to be positioned at the top left corner of |header_view_| and to - // have the same width as |header_view_|. - gfx::Rect GetHeaderLocalBounds() const; - - // Returns the offset between window left edge and title string. - int GetTitleOffsetX() const; - - // Returns the vertical center of the caption button container in window - // coordinates. - int GetCaptionButtonContainerCenterY() const; - - // Returns the radius of the header's top corners. - int GetHeaderCornerRadius() const; - - // Get the bounds for the title. The provided |title_font_list| is used to - // determine the correct dimensions. - gfx::Rect GetTitleBounds(const gfx::FontList& title_font_list); - - Style style_; - - // Not owned - views::Widget* frame_; - views::View* header_view_; - views::View* window_icon_; // May be NULL. - FrameCaptionButtonContainerView* caption_button_container_; - - // The height of the header. - int header_height_; - - // Image ids and opacity last used for painting header. - int previous_theme_frame_id_; - int previous_theme_frame_overlay_id_; - - // Image ids and opacity we are crossfading from. - int crossfade_theme_frame_id_; - int crossfade_theme_frame_overlay_id_; - - scoped_ptr<gfx::SlideAnimation> crossfade_animation_; - - DISALLOW_COPY_AND_ASSIGN(HeaderPainter); -}; - -} // namespace ash - -#endif // ASH_WM_HEADER_PAINTER_H_ diff --git a/ash/wm/header_painter_unittest.cc b/ash/wm/header_painter_unittest.cc deleted file mode 100644 index 6156214..0000000 --- a/ash/wm/header_painter_unittest.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2013 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 "ash/wm/header_painter.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/window_state.h" -#include "base/memory/scoped_ptr.h" -#include "grit/ash_resources.h" -#include "ui/gfx/font_list.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/non_client_view.h" - -using ash::HeaderPainter; -using views::NonClientFrameView; -using views::Widget; - -namespace ash { - -class HeaderPainterTest : public ash::test::AshTestBase { - public: - // Creates a test widget that owns its native widget. - Widget* CreateTestWidget() { - Widget* widget = new Widget; - Widget::InitParams params; - params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.context = CurrentContext(); - widget->Init(params); - return widget; - } -}; - -// Ensure the title text is vertically aligned with the window icon. -TEST_F(HeaderPainterTest, TitleIconAlignment) { - scoped_ptr<Widget> w(CreateTestWidget()); - ash::FrameCaptionButtonContainerView container(w.get(), - ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - views::View window_icon; - window_icon.SetBounds(0, 0, 16, 16); - w->SetBounds(gfx::Rect(0, 0, 500, 500)); - w->Show(); - - gfx::FontList default_font_list; - - // 1) Non-browser windows. - HeaderPainter non_browser_painter; - non_browser_painter.Init(HeaderPainter::STYLE_OTHER, - w.get(), - w->non_client_view()->frame_view(), - &window_icon, - &container); - non_browser_painter.LayoutHeader(); - gfx::Rect non_browser_header_title_bounds = - non_browser_painter.GetTitleBounds(default_font_list); - EXPECT_EQ(window_icon.bounds().CenterPoint().y(), - non_browser_header_title_bounds.CenterPoint().y()); - - // 2) Non-maximized browser windows. - HeaderPainter browser_painter; - browser_painter.Init(HeaderPainter::STYLE_BROWSER, - w.get(), - w->non_client_view()->frame_view(), - &window_icon, - &container); - browser_painter.LayoutHeader(); - gfx::Rect browser_header_title_bounds = - browser_painter.GetTitleBounds(default_font_list); - EXPECT_EQ(window_icon.bounds().CenterPoint().y(), - browser_header_title_bounds.CenterPoint().y()); - - // 3) Maximized browser windows. - w->Maximize(); - browser_painter.LayoutHeader(); - gfx::Rect maximized_browser_header_title_bounds = - browser_painter.GetTitleBounds(default_font_list); - EXPECT_EQ(window_icon.bounds().CenterPoint().y(), - maximized_browser_header_title_bounds.CenterPoint().y()); -} - -} // namespace ash diff --git a/ash/wm/panels/panel_frame_view.cc b/ash/wm/panels/panel_frame_view.cc index 73d10b4..9188dc8 100644 --- a/ash/wm/panels/panel_frame_view.cc +++ b/ash/wm/panels/panel_frame_view.cc @@ -4,9 +4,9 @@ #include "ash/wm/panels/panel_frame_view.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/frame_border_hit_test_controller.h" -#include "ash/wm/header_painter.h" +#include "ash/frame/caption_buttons/frame_caption_button_container_view.h" +#include "ash/frame/frame_border_hit_test_controller.h" +#include "ash/frame/header_painter.h" #include "grit/ash_resources.h" #include "ui/base/hit_test.h" #include "ui/base/l10n/l10n_util.h" diff --git a/ash/wm/resize_shadow_and_cursor_unittest.cc b/ash/wm/resize_shadow_and_cursor_unittest.cc index ba34050..6431409 100644 --- a/ash/wm/resize_shadow_and_cursor_unittest.cc +++ b/ash/wm/resize_shadow_and_cursor_unittest.cc @@ -3,10 +3,10 @@ // found in the LICENSE file. #include "ash/ash_constants.h" +#include "ash/frame/custom_frame_view_ash.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/test/cursor_manager_test_api.h" -#include "ash/wm/custom_frame_view_ash.h" #include "ash/wm/resize_shadow.h" #include "ash/wm/resize_shadow_controller.h" #include "ash/wm/window_state.h" diff --git a/ash/wm/solo_window_tracker_unittest.cc b/ash/wm/solo_window_tracker_unittest.cc deleted file mode 100644 index 08ac7ee..0000000 --- a/ash/wm/solo_window_tracker_unittest.cc +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright 2013 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 "ash/wm/solo_window_tracker.h" - -#include "ash/ash_constants.h" -#include "ash/ash_switches.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/aura/window_observer.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/screen.h" - -namespace ash { - -namespace { - -class WindowRepaintChecker : public aura::WindowObserver { - public: - explicit WindowRepaintChecker(aura::Window* window) - : window_(window), - is_paint_scheduled_(false) { - window_->AddObserver(this); - } - - virtual ~WindowRepaintChecker() { - if (window_) - window_->RemoveObserver(this); - } - - bool IsPaintScheduledAndReset() { - bool result = is_paint_scheduled_; - is_paint_scheduled_ = false; - return result; - } - - private: - // aura::WindowObserver overrides: - virtual void OnWindowPaintScheduled(aura::Window* window, - const gfx::Rect& region) OVERRIDE { - is_paint_scheduled_ = true; - } - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE { - DCHECK_EQ(window_, window); - window_ = NULL; - } - - aura::Window* window_; - bool is_paint_scheduled_; - - DISALLOW_COPY_AND_ASSIGN(WindowRepaintChecker); -}; - -} // namespace - -class SoloWindowTrackerTest : public test::AshTestBase { - public: - SoloWindowTrackerTest() { - } - virtual ~SoloWindowTrackerTest() { - } - - // Helpers methods to create test windows in the primary root window. - aura::Window* CreateWindowInPrimary() { - aura::Window* window = new aura::Window(NULL); - window->SetType(ui::wm::WINDOW_TYPE_NORMAL); - window->Init(aura::WINDOW_LAYER_TEXTURED); - window->SetBounds(gfx::Rect(100, 100)); - ParentWindowInPrimaryRootWindow(window); - return window; - } - aura::Window* CreateAlwaysOnTopWindowInPrimary() { - aura::Window* window = new aura::Window(NULL); - window->SetType(ui::wm::WINDOW_TYPE_NORMAL); - window->Init(aura::WINDOW_LAYER_TEXTURED); - window->SetBounds(gfx::Rect(100, 100)); - window->SetProperty(aura::client::kAlwaysOnTopKey, true); - ParentWindowInPrimaryRootWindow(window); - return window; - } - aura::Window* CreatePanelWindowInPrimary() { - aura::Window* window = new aura::Window(NULL); - window->SetType(ui::wm::WINDOW_TYPE_PANEL); - window->Init(aura::WINDOW_LAYER_TEXTURED); - window->SetBounds(gfx::Rect(100, 100)); - ParentWindowInPrimaryRootWindow(window); - return window; - } - - // Drag |window| to the dock. - void DockWindow(aura::Window* window) { - // Because the tests use windows without delegates, - // aura::test::EventGenerator cannot be used. - gfx::Point drag_to = - ash::ScreenUtil::GetDisplayBoundsInParent(window).top_right(); - scoped_ptr<WindowResizer> resizer(CreateWindowResizer( - window, - window->bounds().origin(), - HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_MOUSE)); - resizer->Drag(drag_to, 0); - resizer->CompleteDrag(); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, - window->parent()->id()); - } - - // Drag |window| out of the dock. - void UndockWindow(aura::Window* window) { - gfx::Point drag_to = - ash::ScreenUtil::GetDisplayWorkAreaBoundsInParent(window).top_right() - - gfx::Vector2d(10, 0); - scoped_ptr<WindowResizer> resizer(CreateWindowResizer( - window, - window->bounds().origin(), - HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_MOUSE)); - resizer->Drag(drag_to, 0); - resizer->CompleteDrag(); - EXPECT_NE(internal::kShellWindowId_DockedContainer, - window->parent()->id()); - } - - // Returns the primary display. - gfx::Display GetPrimaryDisplay() { - return ash::Shell::GetInstance()->GetScreen()->GetPrimaryDisplay(); - } - - // Returns the secondary display. - gfx::Display GetSecondaryDisplay() { - return ScreenUtil::GetSecondaryDisplay(); - } - - // Returns the window which uses the solo header, if any, on the primary - // display. - aura::Window* GetWindowWithSoloHeaderInPrimary() { - return GetWindowWithSoloHeader(Shell::GetPrimaryRootWindow()); - } - - // Returns the window which uses the solo header, if any, in |root|. - aura::Window* GetWindowWithSoloHeader(aura::Window* root) { - SoloWindowTracker* solo_window_tracker = - internal::GetRootWindowController(root)->solo_window_tracker(); - return solo_window_tracker ? - solo_window_tracker->GetWindowWithSoloHeader() : NULL; - } - - private: - DISALLOW_COPY_AND_ASSIGN(SoloWindowTrackerTest); -}; - -TEST_F(SoloWindowTrackerTest, Basic) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a second window. - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->Show(); - - // Now there are two windows, so we should not use solo headers. - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Hide one window. Solo should be enabled. - w2->Hide(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Show that window. Solo should be disabled. - w2->Show(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Minimize the first window. Solo should be enabled. - wm::GetWindowState(w1.get())->Minimize(); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeaderInPrimary()); - - // Close the minimized window. - w1.reset(); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeaderInPrimary()); - - // Open an always-on-top window (which lives in a different container). - scoped_ptr<aura::Window> w3(CreateAlwaysOnTopWindowInPrimary()); - w3->Show(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Close the always-on-top window. - w3.reset(); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Test that docked windows never use the solo header and that the presence of a -// docked window prevents all other windows from the using the solo window -// header. -TEST_F(SoloWindowTrackerTest, DockedWindow) { - if (!switches::UseDockedWindows() || !SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - DockWindow(w1.get()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - UndockWindow(w1.get()); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->Show(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - DockWindow(w2.get()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - wm::GetWindowState(w2.get())->Minimize(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Panels should not "count" for computing solo window headers, and the panel -// itself should never use the solo header. -TEST_F(SoloWindowTrackerTest, Panel) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a panel window. - scoped_ptr<aura::Window> w2(CreatePanelWindowInPrimary()); - w2->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because panels aren't included in the computation. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Even after closing the first window, the panel is still not considered - // solo. - w1.reset(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); -} - -// Modal dialogs should not use solo headers. -TEST_F(SoloWindowTrackerTest, Modal) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a fake modal window. - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - w2->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because modal windows aren't included in the computation. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Constrained windows should not use solo headers. -TEST_F(SoloWindowTrackerTest, Constrained) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a fake constrained window. - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->SetProperty(aura::client::kConstrainedWindowKey, true); - w2->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because constrained windows aren't included in the computation. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Non-drawing windows should not affect the solo computation. -TEST_F(SoloWindowTrackerTest, NotDrawn) { - aura::Window* w = CreateWindowInPrimary(); - w->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); - - // Create non-drawing window similar to DragDropTracker. - aura::Window* not_drawn = new aura::Window(NULL); - not_drawn->SetType(ui::wm::WINDOW_TYPE_NORMAL); - not_drawn->Init(aura::WINDOW_LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(not_drawn); - not_drawn->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because non-drawing windows aren't included in the computation. - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); -} - -TEST_F(SoloWindowTrackerTest, MultiDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("1000x600,600x400"); - - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w1->Show(); - WindowRepaintChecker checker1(w1.get()); - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w2->Show(); - WindowRepaintChecker checker2(w2.get()); - - // Now there are two windows in the same display, so we should not use solo - // headers. - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - - // Moves the second window to the secondary display. Both w1/w2 should be - // solo. - w2->SetBoundsInScreen(gfx::Rect(1200, 0, 100, 100), - ScreenUtil::GetSecondaryDisplay()); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Open two more windows in the primary display. - scoped_ptr<aura::Window> w3(CreateWindowInPrimary()); - w3->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w3->Show(); - scoped_ptr<aura::Window> w4(CreateWindowInPrimary()); - w4->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w4->Show(); - - // Because the primary display has three windows w1, w3, and w4, they - // shouldn't be solo. w2 should be solo. - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - - // Move w4 to the secondary display. Now w2 shouldn't be solo anymore. - w4->SetBoundsInScreen(gfx::Rect(1200, 0, 100, 100), GetSecondaryDisplay()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(NULL, GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Moves w3 to the secondary display too. Now w1 should be solo again. - w3->SetBoundsInScreen(gfx::Rect(1200, 0, 100, 100), GetSecondaryDisplay()); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(NULL, GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - - // Change w3's state to maximize. Doesn't affect w1. - wm::GetWindowState(w3.get())->Maximize(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(NULL, GetWindowWithSoloHeader(w2->GetRootWindow())); - - // Close w3 and w4. - w3.reset(); - w4.reset(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Move w2 back to the primary display. - w2->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - EXPECT_EQ(w1->GetRootWindow(), w2->GetRootWindow()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Close w2. - w2.reset(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); -} - -TEST_F(SoloWindowTrackerTest, ChildWindowVisibility) { - aura::Window* w = CreateWindowInPrimary(); - w->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); - - // Create a child window. This should not affect the solo-ness of |w1|. - aura::Window* child = new aura::Window(NULL); - child->SetType(ui::wm::WINDOW_TYPE_CONTROL); - child->Init(aura::WINDOW_LAYER_TEXTURED); - child->SetBounds(gfx::Rect(100, 100)); - w->AddChild(child); - child->Show(); - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); - - // Changing the visibility of |child| should not affect the solo-ness of |w1|. - child->Hide(); - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); -} - -TEST_F(SoloWindowTrackerTest, CreateAndDeleteSingleWindow) { - // Ensure that creating/deleting a window works well and doesn't cause - // crashes. See crbug.com/155634 - scoped_ptr<aura::Window> w(CreateWindowInPrimary()); - w->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w.get(), GetWindowWithSoloHeaderInPrimary()); - - // Close the window. - w.reset(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Recreate another window again. - w.reset(CreateWindowInPrimary()); - w->Show(); - EXPECT_EQ(w.get(), GetWindowWithSoloHeaderInPrimary()); -} - -} // namespace ash |