diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ui/views/window | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ui/views/window')
18 files changed, 733 insertions, 305 deletions
diff --git a/chromium/ui/views/window/client_view.cc b/chromium/ui/views/window/client_view.cc index 7edc5f4d5b9..fb7d89fed18 100644 --- a/chromium/ui/views/window/client_view.cc +++ b/chromium/ui/views/window/client_view.cc @@ -5,7 +5,7 @@ #include "ui/views/window/client_view.h" #include "base/logging.h" -#include "ui/base/accessibility/accessible_view_state.h" +#include "ui/accessibility/ax_view_state.h" #include "ui/base/hit_test.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -45,19 +45,19 @@ void ClientView::WidgetClosing() { /////////////////////////////////////////////////////////////////////////////// // ClientView, View overrides: -gfx::Size ClientView::GetPreferredSize() { +gfx::Size ClientView::GetPreferredSize() const { // |contents_view_| is allowed to be NULL up until the point where this view // is attached to a Container. return contents_view_ ? contents_view_->GetPreferredSize() : gfx::Size(); } -gfx::Size ClientView::GetMaximumSize() { +gfx::Size ClientView::GetMaximumSize() const { // |contents_view_| is allowed to be NULL up until the point where this view // is attached to a Container. return contents_view_ ? contents_view_->GetMaximumSize() : gfx::Size(); } -gfx::Size ClientView::GetMinimumSize() { +gfx::Size ClientView::GetMinimumSize() const { // |contents_view_| is allowed to be NULL up until the point where this view // is attached to a Container. return contents_view_ ? contents_view_->GetMinimumSize() : gfx::Size(); @@ -74,8 +74,8 @@ const char* ClientView::GetClassName() const { return kViewClassName; } -void ClientView::GetAccessibleState(ui::AccessibleViewState* state) { - state->role = ui::AccessibilityTypes::ROLE_CLIENT; +void ClientView::GetAccessibleState(ui::AXViewState* state) { + state->role = ui::AX_ROLE_CLIENT; } void ClientView::OnBoundsChanged(const gfx::Rect& previous_bounds) { diff --git a/chromium/ui/views/window/client_view.h b/chromium/ui/views/window/client_view.h index 8c890d70b7c..5a329aad567 100644 --- a/chromium/ui/views/window/client_view.h +++ b/chromium/ui/views/window/client_view.h @@ -57,15 +57,15 @@ class VIEWS_EXPORT ClientView : public View { virtual int NonClientHitTest(const gfx::Point& point); // Overridden from View: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual gfx::Size GetMaximumSize() OVERRIDE; - virtual gfx::Size GetMinimumSize() OVERRIDE; + virtual gfx::Size GetPreferredSize() const OVERRIDE; + virtual gfx::Size GetMinimumSize() const OVERRIDE; + virtual gfx::Size GetMaximumSize() const OVERRIDE; virtual void Layout() OVERRIDE; virtual const char* GetClassName() const OVERRIDE; protected: // Overridden from View: - virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; virtual void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) OVERRIDE; diff --git a/chromium/ui/views/window/custom_frame_view.cc b/chromium/ui/views/window/custom_frame_view.cc index bb27dc60ca5..a3fb3f7c96c 100644 --- a/chromium/ui/views/window/custom_frame_view.cc +++ b/chromium/ui/views/window/custom_frame_view.cc @@ -5,6 +5,7 @@ #include "ui/views/window/custom_frame_view.h" #include <algorithm> +#include <vector> #include "base/strings/utf_string_conversions.h" #include "grit/ui_resources.h" @@ -16,21 +17,19 @@ #include "ui/gfx/font.h" #include "ui/gfx/image/image.h" #include "ui/gfx/path.h" +#include "ui/gfx/rect.h" #include "ui/views/color_constants.h" #include "ui/views/controls/button/image_button.h" +#include "ui/views/views_delegate.h" +#include "ui/views/widget/native_widget_private.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/window/client_view.h" #include "ui/views/window/frame_background.h" +#include "ui/views/window/window_button_order_provider.h" #include "ui/views/window/window_resources.h" #include "ui/views/window/window_shape.h" -#if defined(USE_AURA) -#include "ui/views/widget/native_widget_aura.h" -#elif defined(OS_WIN) -#include "ui/views/widget/native_widget_win.h" -#endif - namespace views { namespace { @@ -65,19 +64,17 @@ const SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201); const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228); #endif -const gfx::Font& GetTitleFont() { - static gfx::Font* title_font = NULL; - if (!title_font) { -#if defined(USE_AURA) - title_font = new gfx::Font(NativeWidgetAura::GetWindowTitleFont()); -#elif defined(OS_WIN) - title_font = new gfx::Font(NativeWidgetWin::GetWindowTitleFont()); -#elif defined(OS_LINUX) - // TODO(ben): need to resolve what font this is. - title_font = new gfx::Font(); -#endif - } - return *title_font; +const gfx::FontList& GetTitleFontList() { + static const gfx::FontList title_font_list = + internal::NativeWidgetPrivate::GetWindowTitleFontList(); + return title_font_list; +} + +void LayoutButton(ImageButton* button, const gfx::Rect& bounds) { + button->SetVisible(true); + button->SetImageAlignment(ImageButton::ALIGN_LEFT, + ImageButton::ALIGN_BOTTOM); + button->SetBoundsRect(bounds); } } // namespace @@ -93,7 +90,9 @@ CustomFrameView::CustomFrameView() restore_button_(NULL), close_button_(NULL), should_show_maximize_button_(false), - frame_background_(new FrameBackground()) { + frame_background_(new FrameBackground()), + minimum_title_bar_x_(0), + maximum_title_bar_x_(-1) { } CustomFrameView::~CustomFrameView() { @@ -102,19 +101,12 @@ CustomFrameView::~CustomFrameView() { void CustomFrameView::Init(Widget* frame) { frame_ = frame; - close_button_ = new ImageButton(this); - close_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); - - // Close button images will be set in LayoutWindowControls(). - AddChildView(close_button_); - + close_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_CLOSE, + IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P); minimize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MINIMIZE, IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P); - maximize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MAXIMIZE, IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P); - restore_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_RESTORE, IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P); @@ -137,8 +129,8 @@ gfx::Rect CustomFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { int top_height = NonClientTopBorderHeight(); int border_thickness = NonClientBorderThickness(); - return gfx::Rect(std::max(0, client_bounds.x() - border_thickness), - std::max(0, client_bounds.y() - top_height), + return gfx::Rect(client_bounds.x() - border_thickness, + client_bounds.y() - top_height, client_bounds.width() + (2 * border_thickness), client_bounds.height() + top_height + border_thickness); } @@ -186,7 +178,7 @@ int CustomFrameView::NonClientHitTest(const gfx::Point& point) { void CustomFrameView::GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) { DCHECK(window_mask); - if (frame_->IsMaximized()) + if (frame_->IsMaximized() || !ShouldShowTitleBarAndBorder()) return; GetDefaultWindowMask(size, window_mask); @@ -205,13 +197,17 @@ void CustomFrameView::UpdateWindowIcon() { } void CustomFrameView::UpdateWindowTitle() { - SchedulePaintInRect(title_bounds_); + if (frame_->widget_delegate()->ShouldShowWindowTitle()) + SchedulePaintInRect(title_bounds_); } /////////////////////////////////////////////////////////////////////////////// // CustomFrameView, View overrides: void CustomFrameView::OnPaint(gfx::Canvas* canvas) { + if (!ShouldShowTitleBarAndBorder()) + return; + if (frame_->IsMaximized()) PaintMaximizedFrameBorder(canvas); else @@ -222,22 +218,25 @@ void CustomFrameView::OnPaint(gfx::Canvas* canvas) { } void CustomFrameView::Layout() { - LayoutWindowControls(); - LayoutTitleBar(); + if (ShouldShowTitleBarAndBorder()) { + LayoutWindowControls(); + LayoutTitleBar(); + } + LayoutClientView(); } -gfx::Size CustomFrameView::GetPreferredSize() { +gfx::Size CustomFrameView::GetPreferredSize() const { return frame_->non_client_view()->GetWindowBoundsForClientBounds( gfx::Rect(frame_->client_view()->GetPreferredSize())).size(); } -gfx::Size CustomFrameView::GetMinimumSize() { +gfx::Size CustomFrameView::GetMinimumSize() const { return frame_->non_client_view()->GetWindowBoundsForClientBounds( gfx::Rect(frame_->client_view()->GetMinimumSize())).size(); } -gfx::Size CustomFrameView::GetMaximumSize() { +gfx::Size CustomFrameView::GetMaximumSize() const { gfx::Size max_size = frame_->client_view()->GetMaximumSize(); gfx::Size converted_size = frame_->non_client_view()->GetWindowBoundsForClientBounds( @@ -282,7 +281,11 @@ int CustomFrameView::NonClientTopBorderHeight() const { int CustomFrameView::CaptionButtonY() const { // Maximized buttons start at window top so that even if their images aren't // drawn flush with the screen edge, they still obey Fitts' Law. +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + return FrameBorderThickness(); +#else return frame_->IsMaximized() ? FrameBorderThickness() : kFrameShadowThickness; +#endif } int CustomFrameView::TitlebarBottomThickness() const { @@ -296,7 +299,7 @@ int CustomFrameView::IconSize() const { // size are increased. return GetSystemMetrics(SM_CYSMICON); #else - return std::max(GetTitleFont().GetHeight(), kIconMinimumSize); + return std::max(GetTitleFontList().GetHeight(), kIconMinimumSize); #endif } @@ -320,11 +323,24 @@ gfx::Rect CustomFrameView::IconBounds() const { // 3D edge (or nothing at all, for maximized windows) above; hence the +1. int y = unavailable_px_at_top + (NonClientTopBorderHeight() - unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2; - return gfx::Rect(frame_thickness + kIconLeftSpacing, y, size, size); + return gfx::Rect(frame_thickness + kIconLeftSpacing + minimum_title_bar_x_, + y, size, size); +} + +bool CustomFrameView::ShouldShowTitleBarAndBorder() const { + if (frame_->IsFullscreen()) + return false; + + if (ViewsDelegate::views_delegate) { + return !ViewsDelegate::views_delegate->WindowManagerProvidesTitleBar( + frame_->IsMaximized()); + } + + return true; } bool CustomFrameView::ShouldShowClientEdge() const { - return !frame_->IsMaximized(); + return !frame_->IsMaximized() && ShouldShowTitleBarAndBorder(); } void CustomFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) { @@ -374,13 +390,13 @@ void CustomFrameView::PaintTitleBar(gfx::Canvas* canvas) { // It seems like in some conditions we can be asked to paint after the window // that contains us is WM_DESTROYed. At this point, our delegate is NULL. The // correct long term fix may be to shut down the RootView in WM_DESTROY. - if (!delegate) + if (!delegate || !delegate->ShouldShowWindowTitle()) return; - canvas->DrawStringInt(delegate->GetWindowTitle(), GetTitleFont(), - SK_ColorWHITE, GetMirroredXForRect(title_bounds_), - title_bounds_.y(), title_bounds_.width(), - title_bounds_.height()); + gfx::Rect rect = title_bounds_; + rect.set_x(GetMirroredXForRect(title_bounds_)); + canvas->DrawStringRect(delegate->GetWindowTitle(), GetTitleFontList(), + SK_ColorWHITE, rect); } void CustomFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { @@ -462,70 +478,68 @@ const gfx::ImageSkia* CustomFrameView::GetFrameImage() const { } void CustomFrameView::LayoutWindowControls() { - close_button_->SetImageAlignment(ImageButton::ALIGN_LEFT, - ImageButton::ALIGN_BOTTOM); + minimum_title_bar_x_ = 0; + maximum_title_bar_x_ = width(); + + if (bounds().IsEmpty()) + return; + int caption_y = CaptionButtonY(); bool is_maximized = frame_->IsMaximized(); // There should always be the same number of non-shadow pixels visible to the - // side of the caption buttons. In maximized mode we extend the rightmost - // button to the screen corner to obey Fitts' Law. - int right_extra_width = is_maximized ? + // side of the caption buttons. In maximized mode we extend the edge button + // to the screen corner to obey Fitts' Law. + int extra_width = is_maximized ? (kFrameBorderThickness - kFrameShadowThickness) : 0; - gfx::Size close_button_size = close_button_->GetPreferredSize(); - close_button_->SetBounds(width() - FrameBorderThickness() - - right_extra_width - close_button_size.width(), caption_y, - close_button_size.width() + right_extra_width, - close_button_size.height()); - - // When the window is restored, we show a maximized button; otherwise, we show - // a restore button. + int next_button_x = FrameBorderThickness(); + bool is_restored = !is_maximized && !frame_->IsMinimized(); ImageButton* invisible_button = is_restored ? restore_button_ : maximize_button_; invisible_button->SetVisible(false); - ImageButton* visible_button = is_restored ? maximize_button_ - : restore_button_; - FramePartImage normal_part, hot_part, pushed_part; - int next_button_x; - if (should_show_maximize_button_) { - visible_button->SetVisible(true); - visible_button->SetImageAlignment(ImageButton::ALIGN_LEFT, - ImageButton::ALIGN_BOTTOM); - gfx::Size visible_button_size = visible_button->GetPreferredSize(); - visible_button->SetBounds(close_button_->x() - visible_button_size.width(), - caption_y, visible_button_size.width(), - visible_button_size.height()); - next_button_x = visible_button->x(); - } else { - visible_button->SetVisible(false); - next_button_x = close_button_->x(); + WindowButtonOrderProvider* button_order = + WindowButtonOrderProvider::GetInstance(); + const std::vector<views::FrameButton>& leading_buttons = + button_order->leading_buttons(); + const std::vector<views::FrameButton>& trailing_buttons = + button_order->trailing_buttons(); + + ImageButton* button = NULL; + for (std::vector<views::FrameButton>::const_iterator it = + leading_buttons.begin(); it != leading_buttons.end(); ++it) { + button = GetImageButton(*it); + if (!button) + continue; + gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y), + button->GetPreferredSize()); + if (it == leading_buttons.begin()) + target_bounds.set_width(target_bounds.width() + extra_width); + LayoutButton(button, target_bounds); + next_button_x += button->width(); + minimum_title_bar_x_ = std::min(width(), next_button_x); } - minimize_button_->SetVisible(true); - minimize_button_->SetImageAlignment(ImageButton::ALIGN_LEFT, - ImageButton::ALIGN_BOTTOM); - gfx::Size minimize_button_size = minimize_button_->GetPreferredSize(); - minimize_button_->SetBounds( - next_button_x - minimize_button_size.width(), caption_y, - minimize_button_size.width(), - minimize_button_size.height()); - - normal_part = IDR_CLOSE; - hot_part = IDR_CLOSE_H; - pushed_part = IDR_CLOSE_P; - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - - close_button_->SetImage(CustomButton::STATE_NORMAL, - rb.GetImageNamed(normal_part).ToImageSkia()); - close_button_->SetImage(CustomButton::STATE_HOVERED, - rb.GetImageNamed(hot_part).ToImageSkia()); - close_button_->SetImage(CustomButton::STATE_PRESSED, - rb.GetImageNamed(pushed_part).ToImageSkia()); + // Trailing buttions are laid out in a RTL fashion + next_button_x = width() - FrameBorderThickness(); + for (std::vector<views::FrameButton>::const_reverse_iterator it = + trailing_buttons.rbegin(); it != trailing_buttons.rend(); ++it) { + button = GetImageButton(*it); + if (!button) + continue; + gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y), + button->GetPreferredSize()); + if (it == trailing_buttons.rbegin()) + target_bounds.set_width(target_bounds.width() + extra_width); + target_bounds.Offset(-target_bounds.width(), 0); + LayoutButton(button, target_bounds); + next_button_x = button->x(); + maximum_title_bar_x_ = std::max(minimum_title_bar_x_, next_button_x); + } } void CustomFrameView::LayoutTitleBar() { + DCHECK_GE(maximum_title_bar_x_, 0); // The window title position is calculated based on the icon position, even // when there is no icon. gfx::Rect icon_bounds(IconBounds()); @@ -533,10 +547,13 @@ void CustomFrameView::LayoutTitleBar() { if (show_window_icon) window_icon_->SetBoundsRect(icon_bounds); + if (!frame_->widget_delegate()->ShouldShowWindowTitle()) + return; + // The offset between the window left edge and the title text. int title_x = show_window_icon ? icon_bounds.right() + kTitleIconOffsetX : icon_bounds.x(); - int title_height = GetTitleFont().GetHeight(); + int title_height = GetTitleFontList().GetHeight(); // We bias the title position so that when the difference between the icon and // title heights is odd, the extra pixel of the title is above the vertical // midline rather than below. This compensates for how the icon is already @@ -544,11 +561,16 @@ void CustomFrameView::LayoutTitleBar() { // title from overlapping the 3D edge at the bottom of the titlebar. title_bounds_.SetRect(title_x, icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2), - std::max(0, minimize_button_->x() - kTitleCaptionSpacing - + std::max(0, maximum_title_bar_x_ - kTitleCaptionSpacing - title_x), title_height); } void CustomFrameView::LayoutClientView() { + if (!ShouldShowTitleBarAndBorder()) { + client_view_bounds_ = bounds(); + return; + } + int top_height = NonClientTopBorderHeight(); int border_thickness = NonClientBorderThickness(); client_view_bounds_.SetRect(border_thickness, top_height, @@ -574,4 +596,31 @@ ImageButton* CustomFrameView::InitWindowCaptionButton( return button; } +ImageButton* CustomFrameView::GetImageButton(views::FrameButton frame_button) { + ImageButton* button = NULL; + switch (frame_button) { + case views::FRAME_BUTTON_MINIMIZE: { + button = minimize_button_; + break; + } + case views::FRAME_BUTTON_MAXIMIZE: { + bool is_restored = !frame_->IsMaximized() && !frame_->IsMinimized(); + button = is_restored ? maximize_button_ : restore_button_; + if (!should_show_maximize_button_) { + // If we should not show the maximize/restore button, then we return + // NULL as we don't want this button to become visible and to be laid + // out. + button->SetVisible(false); + return NULL; + } + break; + } + case views::FRAME_BUTTON_CLOSE: { + button = close_button_; + break; + } + } + return button; +} + } // namespace views diff --git a/chromium/ui/views/window/custom_frame_view.h b/chromium/ui/views/window/custom_frame_view.h index 8c96df7fc9f..fe5a3e4c7bd 100644 --- a/chromium/ui/views/window/custom_frame_view.h +++ b/chromium/ui/views/window/custom_frame_view.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "ui/views/controls/button/button.h" +#include "ui/views/window/frame_buttons.h" #include "ui/views/window/non_client_view.h" namespace gfx { @@ -29,8 +30,8 @@ class Widget; // rendering the non-standard window caption, border, and controls. // //////////////////////////////////////////////////////////////////////////////// -class CustomFrameView : public NonClientFrameView, - public ButtonListener { +class VIEWS_EXPORT CustomFrameView : public NonClientFrameView, + public ButtonListener { public: CustomFrameView(); virtual ~CustomFrameView(); @@ -51,14 +52,16 @@ class CustomFrameView : public NonClientFrameView, // Overridden from View: virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; virtual void Layout() OVERRIDE; - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual gfx::Size GetMinimumSize() OVERRIDE; - virtual gfx::Size GetMaximumSize() OVERRIDE; + virtual gfx::Size GetPreferredSize() const OVERRIDE; + virtual gfx::Size GetMinimumSize() const OVERRIDE; + virtual gfx::Size GetMaximumSize() const OVERRIDE; // Overridden from ButtonListener: virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE; private: + friend class CustomFrameViewTest; + // Returns the thickness of the border that makes up the window frame edges. // This does not include any client edge. int FrameBorderThickness() const; @@ -86,6 +89,10 @@ class CustomFrameView : public NonClientFrameView, // there was one). gfx::Rect IconBounds() const; + // Returns true if the title bar, caption buttons, and frame border should be + // drawn. If false, the client view occupies the full area of this view. + bool ShouldShowTitleBarAndBorder() const; + // Returns true if the client edge should be drawn. This is true if // the window is not maximized. bool ShouldShowClientEdge() const; @@ -100,8 +107,13 @@ class CustomFrameView : public NonClientFrameView, SkColor GetFrameColor() const; const gfx::ImageSkia* GetFrameImage() const; - // Layout various sub-components of this view. + // Performs the layout for the window control buttons based on the + // configuration specified in WindowButtonOrderProvider. The sizing and + // positions of the buttons affects LayoutTitleBar, call this beforehand. void LayoutWindowControls(); + + // Calculations depend on the positions of the window controls. Always call + // LayoutWindowControls beforehand. void LayoutTitleBar(); void LayoutClientView(); @@ -112,6 +124,10 @@ class CustomFrameView : public NonClientFrameView, int hot_image_id, int pushed_image_id); + // Returns the window caption button for the given FrameButton type, if it + // should be visible. Otherwise NULL. + ImageButton* GetImageButton(views::FrameButton button); + // The bounds of the client view, in this view's coordinates. gfx::Rect client_view_bounds_; @@ -136,6 +152,11 @@ class CustomFrameView : public NonClientFrameView, // Background painter for the window frame. scoped_ptr<FrameBackground> frame_background_; + // The horizontal boundaries for the title bar to layout within. Restricted + // by the space used by the leading and trailing buttons. + int minimum_title_bar_x_; + int maximum_title_bar_x_; + DISALLOW_COPY_AND_ASSIGN(CustomFrameView); }; diff --git a/chromium/ui/views/window/custom_frame_view_unittest.cc b/chromium/ui/views/window/custom_frame_view_unittest.cc new file mode 100644 index 00000000000..26711190214 --- /dev/null +++ b/chromium/ui/views/window/custom_frame_view_unittest.cc @@ -0,0 +1,252 @@ +// 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 "ui/views/window/custom_frame_view.h" + +#include <vector> + +#include "ui/views/controls/button/image_button.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" +#include "ui/views/window/window_button_order_provider.h" + +namespace views { + +namespace { + +// Allows for the control of whether or not the widget can maximize or not. +// This can be set after initial setup in order to allow testing of both forms +// of delegates. By default this can maximize. +class MaximizeStateControlDelegate : public WidgetDelegateView { + public: + MaximizeStateControlDelegate() : can_maximize_(true) {} + virtual ~MaximizeStateControlDelegate() {} + + void set_can_maximize(bool can_maximize) { + can_maximize_ = can_maximize; + } + + // WidgetDelegate: + virtual bool CanMaximize() const OVERRIDE { return can_maximize_; } + + private: + bool can_maximize_; + + DISALLOW_COPY_AND_ASSIGN(MaximizeStateControlDelegate); +}; + +} // namespace + +class CustomFrameViewTest : public ViewsTestBase { + public: + CustomFrameViewTest() {} + virtual ~CustomFrameViewTest() {} + + CustomFrameView* custom_frame_view() { + return custom_frame_view_; + } + + MaximizeStateControlDelegate* maximize_state_control_delegate() { + return maximize_state_control_delegate_; + } + + Widget* widget() { + return widget_; + } + + // ViewsTestBase: + virtual void SetUp() OVERRIDE; + virtual void TearDown() OVERRIDE; + + protected: + const std::vector<views::FrameButton>& leading_buttons() { + return WindowButtonOrderProvider::GetInstance()->leading_buttons(); + } + + const std::vector<views::FrameButton>& trailing_buttons() { + return WindowButtonOrderProvider::GetInstance()->trailing_buttons(); + } + + ImageButton* minimize_button() { + return custom_frame_view_->minimize_button_; + } + + ImageButton* maximize_button() { + return custom_frame_view_->maximize_button_; + } + + ImageButton* restore_button() { + return custom_frame_view_->restore_button_; + } + + ImageButton* close_button() { + return custom_frame_view_->close_button_; + } + + gfx::Rect title_bounds() { + return custom_frame_view_->title_bounds_; + } + + void SetWindowButtonOrder( + const std::vector<views::FrameButton> leading_buttons, + const std::vector<views::FrameButton> trailing_buttons); + + private: + // Parent container for |custom_frame_view_| + Widget* widget_; + + // Owned by |widget_| + CustomFrameView* custom_frame_view_; + + // Delegate of |widget_| which controls maximizing + MaximizeStateControlDelegate* maximize_state_control_delegate_; + + DISALLOW_COPY_AND_ASSIGN(CustomFrameViewTest); +}; + +void CustomFrameViewTest::SetUp() { + ViewsTestBase::SetUp(); + + maximize_state_control_delegate_ = new MaximizeStateControlDelegate; + widget_ = new Widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); + params.delegate = maximize_state_control_delegate_; + params.remove_standard_frame = true; + widget_->Init(params); + + custom_frame_view_ = new CustomFrameView; + widget_->non_client_view()->SetFrameView(custom_frame_view_); +} + +void CustomFrameViewTest::TearDown() { + widget_->CloseNow(); + + ViewsTestBase::TearDown(); +} + +void CustomFrameViewTest::SetWindowButtonOrder( + const std::vector<views::FrameButton> leading_buttons, + const std::vector<views::FrameButton> trailing_buttons) { + WindowButtonOrderProvider::GetInstance()-> + SetWindowButtonOrder(leading_buttons, trailing_buttons); +} + +// Tests that there is a default button ordering before initialization causes +// a configuration file check. +TEST_F(CustomFrameViewTest, DefaultButtons) { + const std::vector<views::FrameButton>& trailing = trailing_buttons(); + EXPECT_EQ(trailing.size(), 3u); + EXPECT_TRUE(leading_buttons().empty()); + EXPECT_EQ(trailing[0], FRAME_BUTTON_MINIMIZE); + EXPECT_EQ(trailing[1], FRAME_BUTTON_MAXIMIZE); + EXPECT_EQ(trailing[2], FRAME_BUTTON_CLOSE); +} + +// Tests that layout places the buttons in order, that the restore button is +// hidden and the buttons are placed after the title. +TEST_F(CustomFrameViewTest, DefaultButtonLayout) { + Widget* parent = widget(); + CustomFrameView* view = custom_frame_view(); + view->Init(parent); + parent->SetBounds(gfx::Rect(0, 0, 300, 100)); + parent->Show(); + + EXPECT_LT(minimize_button()->x(), maximize_button()->x()); + EXPECT_LT(maximize_button()->x(), close_button()->x()); + EXPECT_FALSE(restore_button()->visible()); + + EXPECT_GT(minimize_button()->x(), + title_bounds().x() + title_bounds().width()); +} + +// Tests that setting the buttons to leading places them before the title. +TEST_F(CustomFrameViewTest, LeadingButtonLayout) { + Widget* parent = widget(); + CustomFrameView* view = custom_frame_view(); + + std::vector<views::FrameButton> leading; + leading.push_back(views::FRAME_BUTTON_CLOSE); + leading.push_back(views::FRAME_BUTTON_MINIMIZE); + leading.push_back(views::FRAME_BUTTON_MAXIMIZE); + + std::vector<views::FrameButton> trailing; + + SetWindowButtonOrder(leading, trailing); + + view->Init(parent); + parent->SetBounds(gfx::Rect(0, 0, 300, 100)); + parent->Show(); + EXPECT_LT(close_button()->x(), minimize_button()->x()); + EXPECT_LT(minimize_button()->x(), maximize_button()->x()); + EXPECT_FALSE(restore_button()->visible()); + EXPECT_LT(maximize_button()->x() + maximize_button()->width(), + title_bounds().x()); +} + +// Tests that layouts occuring while maximized swap the maximize button for the +// restore button +TEST_F(CustomFrameViewTest, MaximizeRevealsRestoreButton) { + Widget* parent = widget(); + CustomFrameView* view = custom_frame_view(); + view->Init(parent); + parent->SetBounds(gfx::Rect(0, 0, 300, 100)); + parent->Show(); + + ASSERT_FALSE(restore_button()->visible()); + ASSERT_TRUE(maximize_button()->visible()); + + parent->Maximize(); + view->Layout(); + + EXPECT_TRUE(restore_button()->visible()); + EXPECT_FALSE(maximize_button()->visible()); +} + +// Tests that when the parent cannot maximize that the maximize button is not +// visible +TEST_F(CustomFrameViewTest, CannotMaximizeHidesButton) { + Widget* parent = widget(); + CustomFrameView* view = custom_frame_view(); + MaximizeStateControlDelegate* delegate = maximize_state_control_delegate(); + delegate->set_can_maximize(false); + + view->Init(parent); + parent->SetBounds(gfx::Rect(0, 0, 300, 100)); + parent->Show(); + + EXPECT_FALSE(restore_button()->visible()); + EXPECT_FALSE(maximize_button()->visible()); +} + +// Tests that when maximized that the edge button has an increased width. +TEST_F(CustomFrameViewTest, LargerEdgeButtonsWhenMaximized) { + Widget* parent = widget(); + CustomFrameView* view = custom_frame_view(); + + // Custom ordering to have a button on each edge. + std::vector<views::FrameButton> leading; + leading.push_back(views::FRAME_BUTTON_CLOSE); + leading.push_back(views::FRAME_BUTTON_MAXIMIZE); + std::vector<views::FrameButton> trailing; + trailing.push_back(views::FRAME_BUTTON_MINIMIZE); + SetWindowButtonOrder(leading, trailing); + + view->Init(parent); + parent->SetBounds(gfx::Rect(0, 0, 300, 100)); + parent->Show(); + + gfx::Rect close_button_initial_bounds = close_button()->bounds(); + gfx::Rect minimize_button_initial_bounds = minimize_button()->bounds(); + + parent->Maximize(); + view->Layout(); + + EXPECT_GT(close_button()->bounds().width(), + close_button_initial_bounds.width()); + EXPECT_GT(minimize_button()->bounds().width(), + minimize_button_initial_bounds.width()); +} + +} // namespace views diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc index bfb870ed50b..172ca0fde3d 100644 --- a/chromium/ui/views/window/dialog_client_view.cc +++ b/chromium/ui/views/window/dialog_client_view.cc @@ -22,12 +22,30 @@ namespace { // conflict with other groups that could be in the dialog content. const int kButtonGroup = 6666; +#if defined(OS_WIN) || defined(OS_CHROMEOS) +const bool kIsOkButtonOnLeftSide = true; +#else +const bool kIsOkButtonOnLeftSide = false; +#endif + // Returns true if the given view should be shown (i.e. exists and is // visible). bool ShouldShow(View* view) { return view && view->visible(); } +// Do the layout for a button. +void LayoutButton(LabelButton* button, gfx::Rect* row_bounds) { + if (!button) + return; + + const gfx::Size size = button->GetPreferredSize(); + row_bounds->set_width(row_bounds->width() - size.width()); + button->SetBounds(row_bounds->right(), row_bounds->y(), + size.width(), row_bounds->height()); + row_bounds->set_width(row_bounds->width() - kRelatedButtonHSpacing); +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -157,7 +175,7 @@ void DialogClientView::OnDidChangeFocus(View* focused_before, //////////////////////////////////////////////////////////////////////////////// // DialogClientView, View overrides: -gfx::Size DialogClientView::GetPreferredSize() { +gfx::Size DialogClientView::GetPreferredSize() const { // Initialize the size to fit the buttons and extra view row. gfx::Size size( (ok_button_ ? ok_button_->GetPreferredSize().width() : 0) + @@ -213,19 +231,12 @@ void DialogClientView::Layout() { const int height = GetButtonsAndExtraViewRowHeight(); gfx::Rect row_bounds(bounds.x(), bounds.bottom() - height, bounds.width(), height); - if (cancel_button_) { - const gfx::Size size = cancel_button_->GetPreferredSize(); - row_bounds.set_width(row_bounds.width() - size.width()); - cancel_button_->SetBounds(row_bounds.right(), row_bounds.y(), - size.width(), height); - row_bounds.set_width(row_bounds.width() - kRelatedButtonHSpacing); - } - if (ok_button_) { - const gfx::Size size = ok_button_->GetPreferredSize(); - row_bounds.set_width(row_bounds.width() - size.width()); - ok_button_->SetBounds(row_bounds.right(), row_bounds.y(), - size.width(), height); - row_bounds.set_width(row_bounds.width() - kRelatedButtonHSpacing); + if (kIsOkButtonOnLeftSide) { + LayoutButton(cancel_button_, &row_bounds); + LayoutButton(ok_button_, &row_bounds); + } else { + LayoutButton(ok_button_, &row_bounds); + LayoutButton(cancel_button_, &row_bounds); } if (extra_view_) { row_bounds.set_width(std::min(row_bounds.width(), @@ -254,13 +265,6 @@ void DialogClientView::ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) { ClientView::ViewHierarchyChanged(details); if (details.is_add && details.child == this) { - // The old dialog style needs an explicit background color, while the new - // dialog style simply inherits the bubble's frame view color. - const DialogDelegate* dialog = GetDialogDelegate(); - if (dialog && !dialog->UseNewStyleForThisDialog()) - set_background(views::Background::CreateSolidBackground(GetNativeTheme()-> - GetSystemColor(ui::NativeTheme::kColorId_DialogBackground))); - focus_manager_ = GetFocusManager(); if (focus_manager_) GetFocusManager()->AddFocusChangeListener(this); @@ -293,6 +297,17 @@ void DialogClientView::NativeViewHierarchyChanged() { } } +void DialogClientView::OnNativeThemeChanged(const ui::NativeTheme* theme) { + // The old dialog style needs an explicit background color, while the new + // dialog style simply inherits the bubble's frame view color. + const DialogDelegate* dialog = GetDialogDelegate(); + + if (dialog && !dialog->UseNewStyleForThisDialog()) { + set_background(views::Background::CreateSolidBackground(GetNativeTheme()-> + GetSystemColor(ui::NativeTheme::kColorId_DialogBackground))); + } +} + //////////////////////////////////////////////////////////////////////////////// // DialogClientView, ButtonListener implementation: @@ -359,7 +374,7 @@ void DialogClientView::ChildVisibilityChanged(View* child) { // DialogClientView, private: LabelButton* DialogClientView::CreateDialogButton(ui::DialogButton type) { - const string16 title = GetDialogDelegate()->GetDialogButtonLabel(type); + const base::string16 title = GetDialogDelegate()->GetDialogButtonLabel(type); LabelButton* button = NULL; if (GetDialogDelegate()->UseNewStyleForThisDialog() && GetDialogDelegate()->GetDefaultDialogButton() == type && @@ -367,7 +382,7 @@ LabelButton* DialogClientView::CreateDialogButton(ui::DialogButton type) { button = new BlueButton(this, title); } else { button = new LabelButton(this, title); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); } button->SetFocusable(true); diff --git a/chromium/ui/views/window/dialog_client_view.h b/chromium/ui/views/window/dialog_client_view.h index d780806094c..1e8ced11c77 100644 --- a/chromium/ui/views/window/dialog_client_view.h +++ b/chromium/ui/views/window/dialog_client_view.h @@ -57,12 +57,13 @@ class VIEWS_EXPORT DialogClientView : public ClientView, View* focused_now) OVERRIDE; // View implementation: - virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual gfx::Size GetPreferredSize() const OVERRIDE; virtual void Layout() OVERRIDE; virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; virtual void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) OVERRIDE; virtual void NativeViewHierarchyChanged() OVERRIDE; + virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE; // ButtonListener implementation: virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE; diff --git a/chromium/ui/views/window/dialog_delegate.cc b/chromium/ui/views/window/dialog_delegate.cc index cb5374acf55..5ec29a216a9 100644 --- a/chromium/ui/views/window/dialog_delegate.cc +++ b/chromium/ui/views/window/dialog_delegate.cc @@ -14,8 +14,8 @@ #include "ui/views/widget/widget_observer.h" #include "ui/views/window/dialog_client_view.h" -#if defined(USE_AURA) -#include "ui/views/corewm/shadow_types.h" +#if defined(OS_WIN) +#include "ui/base/win/shell.h" #endif namespace views { @@ -23,23 +23,42 @@ namespace views { //////////////////////////////////////////////////////////////////////////////// // DialogDelegate: +DialogDelegate::DialogDelegate() : supports_new_style_(true) { +} + DialogDelegate::~DialogDelegate() { } // static -Widget* DialogDelegate::CreateDialogWidget(DialogDelegate* dialog, - gfx::NativeWindow context, - gfx::NativeWindow parent) { +Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate, + gfx::NativeView context, + gfx::NativeView parent) { views::Widget* widget = new views::Widget; views::Widget::InitParams params; - params.delegate = dialog; + params.delegate = delegate; + DialogDelegate* dialog = delegate->AsDialogDelegate(); + +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + // The new style doesn't support unparented dialogs on Linux desktop. + if (dialog) + dialog->supports_new_style_ &= parent != NULL; +#elif defined(OS_WIN) + // The new style doesn't support unparented dialogs on Windows Classic themes. + if (dialog && !ui::win::IsAeroGlassEnabled()) + dialog->supports_new_style_ &= parent != NULL; +#endif + if (!dialog || dialog->UseNewStyleForThisDialog()) { params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW; params.remove_standard_frame = true; + // The bubble frame includes its own shadow; remove any native shadowing. + params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE; } params.context = context; params.parent = parent; - params.top_level = true; + // Web-modal (ui::MODAL_TYPE_CHILD) dialogs with parents are marked as child + // widgets to prevent top-level window behavior (independent movement, etc). + params.child = parent && (delegate->GetModalType() == ui::MODAL_TYPE_CHILD); widget->Init(params); return widget; } @@ -154,43 +173,22 @@ NonClientFrameView* DialogDelegate::CreateNonClientFrameView(Widget* widget) { // static NonClientFrameView* DialogDelegate::CreateDialogFrameView(Widget* widget) { - return CreateDialogFrameView(widget, false); -} - -// static -NonClientFrameView* DialogDelegate::CreateDialogFrameView( - Widget* widget, - bool force_opaque_border) { BubbleFrameView* frame = new BubbleFrameView(gfx::Insets()); - const SkColor color = widget->GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_DialogBackground); - if (force_opaque_border) { - frame->SetBubbleBorder(new BubbleBorder( - BubbleBorder::NONE, - BubbleBorder::NO_SHADOW_OPAQUE_BORDER, - color)); - } else { - frame->SetBubbleBorder(new BubbleBorder(BubbleBorder::FLOAT, - BubbleBorder::SMALL_SHADOW, - color)); - } + scoped_ptr<BubbleBorder> border(new BubbleBorder( + BubbleBorder::FLOAT, BubbleBorder::SMALL_SHADOW, SK_ColorRED)); + border->set_use_theme_background_color(true); + frame->SetBubbleBorder(border.Pass()); DialogDelegate* delegate = widget->widget_delegate()->AsDialogDelegate(); if (delegate) { View* titlebar_view = delegate->CreateTitlebarExtraView(); if (titlebar_view) frame->SetTitlebarExtraView(titlebar_view); } - if (force_opaque_border) - widget->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM); -#if defined(USE_AURA) - // TODO(msw): Add a matching shadow type and remove the bubble frame border? - corewm::SetShadowType(widget->GetNativeWindow(), corewm::SHADOW_TYPE_NONE); -#endif return frame; } bool DialogDelegate::UseNewStyleForThisDialog() const { - return true; + return supports_new_style_; } const DialogClientView* DialogDelegate::GetDialogClientView() const { @@ -201,8 +199,8 @@ DialogClientView* DialogDelegate::GetDialogClientView() { return GetWidget()->client_view()->AsDialogClientView(); } -ui::AccessibilityTypes::Role DialogDelegate::GetAccessibleWindowRole() const { - return ui::AccessibilityTypes::ROLE_DIALOG; +ui::AXRole DialogDelegate::GetAccessibleWindowRole() const { + return ui::AX_ROLE_DIALOG; } //////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/ui/views/window/dialog_delegate.h b/chromium/ui/views/window/dialog_delegate.h index 8e8948de427..91fff1e51fb 100644 --- a/chromium/ui/views/window/dialog_delegate.h +++ b/chromium/ui/views/window/dialog_delegate.h @@ -7,7 +7,7 @@ #include "base/compiler_specific.h" #include "base/strings/string16.h" -#include "ui/base/accessibility/accessibility_types.h" +#include "ui/accessibility/ax_enums.h" #include "ui/base/models/dialog_model.h" #include "ui/base/ui_base_types.h" #include "ui/views/widget/widget_delegate.h" @@ -29,12 +29,13 @@ class DialogClientView; class VIEWS_EXPORT DialogDelegate : public ui::DialogModel, public WidgetDelegate { public: + DialogDelegate(); virtual ~DialogDelegate(); - // Create a |dialog| window Widget with the specified |context| or |parent|. - static Widget* CreateDialogWidget(DialogDelegate* dialog, - gfx::NativeWindow context, - gfx::NativeWindow parent); + // Create a dialog widget with the specified |context| or |parent|. + static Widget* CreateDialogWidget(WidgetDelegate* delegate, + gfx::NativeView context, + gfx::NativeView parent); // Override this function to display an extra view adjacent to the buttons. // Overrides may construct the view; this will only be called once per dialog. @@ -91,14 +92,6 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel, // Create a frame view using the new dialog style. static NonClientFrameView* CreateDialogFrameView(Widget* widget); - // The semi-transparent border and shadow of the new style frame view does not - // work on child windows under Views/Win32. This is a kludge to get a - // reasonable-looking opaque border for the dialog. Note that this does not - // support arrows. - // - // TODO(wittman): Remove once WinAura is in place. - static NonClientFrameView* CreateDialogFrameView(Widget* widget, - bool force_opaque_border); // Returns whether this particular dialog should use the new dialog style. virtual bool UseNewStyleForThisDialog() const; @@ -113,7 +106,11 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel, protected: // Overridden from WidgetDelegate: - virtual ui::AccessibilityTypes::Role GetAccessibleWindowRole() const OVERRIDE; + virtual ui::AXRole GetAccessibleWindowRole() const OVERRIDE; + + private: + // A flag indicating whether this dialog supports the new style. + bool supports_new_style_; }; // A DialogDelegate implementation that is-a View. Used to override GetWidget() diff --git a/chromium/ui/views/window/dialog_delegate_unittest.cc b/chromium/ui/views/window/dialog_delegate_unittest.cc index f56073affac..fedb6983eb2 100644 --- a/chromium/ui/views/window/dialog_delegate_unittest.cc +++ b/chromium/ui/views/window/dialog_delegate_unittest.cc @@ -37,8 +37,11 @@ class TestDialog : public DialogDelegateView, public ButtonListener { } // DialogDelegateView overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE { return gfx::Size(200, 200); } - virtual string16 GetWindowTitle() const OVERRIDE { return title_; } + virtual gfx::Size GetPreferredSize() const OVERRIDE { + return gfx::Size(200, 200); + } + virtual base::string16 GetWindowTitle() const OVERRIDE { return title_; } + virtual bool UseNewStyleForThisDialog() const OVERRIDE { return true; } // ButtonListener override: virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE { @@ -73,7 +76,7 @@ class TestDialog : public DialogDelegateView, public ButtonListener { GetWidget()->Close(); } - void set_title(const string16& title) { title_ = title; } + void set_title(const base::string16& title) { title_ = title; } private: bool canceled_; @@ -81,7 +84,7 @@ class TestDialog : public DialogDelegateView, public ButtonListener { // Prevent the dialog from closing, for repeated ok and cancel button clicks. bool closeable_; Button* last_pressed_button_; - string16 title_; + base::string16 title_; DISALLOW_COPY_AND_ASSIGN(TestDialog); }; @@ -121,21 +124,21 @@ TEST_F(DialogTest, DefaultButtons) { dialog()->PressEnterAndCheckStates(ok_button); // Focus another button in the dialog, it should become the default. - LabelButton* button_1 = new LabelButton(dialog(), string16()); + LabelButton* button_1 = new LabelButton(dialog(), base::string16()); client_view->AddChildView(button_1); client_view->OnWillChangeFocus(ok_button, button_1); EXPECT_TRUE(button_1->is_default()); dialog()->PressEnterAndCheckStates(button_1); // Focus a Checkbox (not a push button), OK should become the default again. - Checkbox* checkbox = new Checkbox(string16()); + Checkbox* checkbox = new Checkbox(base::string16()); client_view->AddChildView(checkbox); client_view->OnWillChangeFocus(button_1, checkbox); EXPECT_FALSE(button_1->is_default()); dialog()->PressEnterAndCheckStates(ok_button); // Focus yet another button in the dialog, it should become the default. - LabelButton* button_2 = new LabelButton(dialog(), string16()); + LabelButton* button_2 = new LabelButton(dialog(), base::string16()); client_view->AddChildView(button_2); client_view->OnWillChangeFocus(checkbox, button_2); EXPECT_FALSE(button_1->is_default()); @@ -205,21 +208,22 @@ TEST_F(DialogTest, HitTest) { } } -TEST_F(DialogTest, InitialBoundsAccommodateTitle) { - TestDialog* titled_dialog(new TestDialog()); - titled_dialog->set_title(ASCIIToUTF16("Title")); - DialogDelegate::CreateDialogWidget(titled_dialog, GetContext(), NULL); +TEST_F(DialogTest, BoundsAccommodateTitle) { + TestDialog* dialog2(new TestDialog()); + dialog2->set_title(base::ASCIIToUTF16("Title")); + DialogDelegate::CreateDialogWidget(dialog2, GetContext(), NULL); // Titled dialogs have taller initial frame bounds than untitled dialogs. - EXPECT_GT(titled_dialog->GetWidget()->GetWindowBoundsInScreen().height(), - dialog()->GetWidget()->GetWindowBoundsInScreen().height()); + View* frame1 = dialog()->GetWidget()->non_client_view()->frame_view(); + View* frame2 = dialog2->GetWidget()->non_client_view()->frame_view(); + EXPECT_LT(frame1->GetPreferredSize().height(), + frame2->GetPreferredSize().height()); - // Giving the default test dialog a title will make the bounds the same. - dialog()->set_title(ASCIIToUTF16("Title")); + // Giving the default test dialog a title will yield the same bounds. + dialog()->set_title(base::ASCIIToUTF16("Title")); dialog()->GetWidget()->UpdateWindowTitle(); - View* frame = dialog()->GetWidget()->non_client_view()->frame_view(); - EXPECT_EQ(titled_dialog->GetWidget()->GetWindowBoundsInScreen().height(), - frame->GetPreferredSize().height()); + EXPECT_EQ(frame1->GetPreferredSize().height(), + frame2->GetPreferredSize().height()); } } // namespace views diff --git a/chromium/ui/views/window/frame_background.cc b/chromium/ui/views/window/frame_background.cc index 111ac257814..f9e8293c0db 100644 --- a/chromium/ui/views/window/frame_background.cc +++ b/chromium/ui/views/window/frame_background.cc @@ -26,10 +26,7 @@ FrameBackground::FrameBackground() top_right_corner_(NULL), bottom_left_corner_(NULL), bottom_right_corner_(NULL), - maximized_top_left_(NULL), - maximized_top_right_(NULL), - maximized_top_offset_(0), - theme_background_y_(0) { + maximized_top_inset_(0) { } FrameBackground::~FrameBackground() { @@ -124,41 +121,25 @@ void FrameBackground::PaintRestored(gfx::Canvas* canvas, View* view) const { } void FrameBackground::PaintMaximized(gfx::Canvas* canvas, View* view) const { - // We will be painting from top_offset to top_offset + theme_frame_height. If - // this is less than top_area_height_, we need to paint the frame color - // to fill in the area beneath the image. - // TODO(jamescook): I'm not sure this is correct, as it doesn't seem to fully - // account for the top_offset, but this is how it worked before. - int theme_frame_bottom = maximized_top_offset_ + theme_image_->height(); + // We will be painting from -|maximized_top_inset_| to + // -|maximized_top_inset_| + |theme_image_|->height(). If this is less than + // |top_area_height_|, we need to paint the frame color to fill in the area + // beneath the image. + int theme_frame_bottom = -maximized_top_inset_ + theme_image_->height(); if (top_area_height_ > theme_frame_bottom) { canvas->FillRect(gfx::Rect(0, 0, view->width(), top_area_height_), frame_color_); } - int left_offset = 0; - int right_offset = 0; - - // Draw top-left and top-right corners to give maximized ChromeOS windows - // a rounded appearance. - if (maximized_top_left_ || maximized_top_right_) { - // If we have either a left or right we should have both. - DCHECK(maximized_top_left_ && maximized_top_right_); - left_offset = maximized_top_left_->width(); - right_offset = maximized_top_right_->width(); - canvas->DrawImageInt(*maximized_top_left_, 0, 0); - canvas->DrawImageInt(*maximized_top_right_, - view->width() - right_offset, 0); - } - // Draw the theme frame. canvas->TileImageInt(*theme_image_, - left_offset, - maximized_top_offset_, - view->width() - (left_offset + right_offset), + 0, + -maximized_top_inset_, + view->width(), theme_image_->height()); // Draw the theme frame overlay, if available. if (theme_overlay_image_) - canvas->DrawImageInt(*theme_overlay_image_, 0, theme_background_y_); + canvas->DrawImageInt(*theme_overlay_image_, 0, -maximized_top_inset_); } void FrameBackground::PaintFrameColor(gfx::Canvas* canvas, View* view) const { diff --git a/chromium/ui/views/window/frame_background.h b/chromium/ui/views/window/frame_background.h index b8684f61399..bdabf51f72e 100644 --- a/chromium/ui/views/window/frame_background.h +++ b/chromium/ui/views/window/frame_background.h @@ -44,11 +44,8 @@ class VIEWS_EXPORT FrameBackground { // which must extend behind the tab strip. void set_top_area_height(int height) { top_area_height_ = height; } - // Only used if we have an overlay image for the theme. - void set_theme_background_y(int y) { theme_background_y_ = y; } - - // Vertical offset for theme image when drawing maximized. - void set_maximized_top_offset(int offset) { maximized_top_offset_ = offset; } + // Vertical inset for theme image when drawing maximized. + void set_maximized_top_inset(int inset) { maximized_top_inset_ = inset; } // Sets images used when drawing the sides of the frame. // Caller owns the memory. @@ -94,12 +91,8 @@ class VIEWS_EXPORT FrameBackground { const gfx::ImageSkia* bottom_left_corner_; const gfx::ImageSkia* bottom_right_corner_; - // Attributes for maximized window painting. - // TODO(jamescook): Remove all these. - gfx::ImageSkia* maximized_top_left_; - gfx::ImageSkia* maximized_top_right_; - int maximized_top_offset_; - int theme_background_y_; + // Vertical inset for theme image when drawing maximized. + int maximized_top_inset_; DISALLOW_COPY_AND_ASSIGN(FrameBackground); }; diff --git a/chromium/ui/views/window/native_frame_view.cc b/chromium/ui/views/window/native_frame_view.cc index 1cbafabe57b..1ffbcdbb02b 100644 --- a/chromium/ui/views/window/native_frame_view.cc +++ b/chromium/ui/views/window/native_frame_view.cc @@ -16,6 +16,9 @@ namespace views { //////////////////////////////////////////////////////////////////////////////// // NativeFrameView, public: +// static +const char NativeFrameView::kViewClassName[] = "NativeFrameView"; + NativeFrameView::NativeFrameView(Widget* frame) : NonClientFrameView(), frame_(frame) { @@ -37,8 +40,12 @@ gfx::Rect NativeFrameView::GetWindowBoundsForClientBounds( return views::GetWindowBoundsForClientBounds( static_cast<View*>(const_cast<NativeFrameView*>(this)), client_bounds); #else - // TODO(sad): - return client_bounds; + // Enforce minimum size (1, 1) in case that |client_bounds| is passed with + // empty size. + gfx::Rect window_bounds = client_bounds; + if (window_bounds.IsEmpty()) + window_bounds.set_size(gfx::Size(1,1)); + return window_bounds; #endif } @@ -63,20 +70,30 @@ void NativeFrameView::UpdateWindowTitle() { // Nothing to do. } -// Returns the client size. On Windows, this is the expected behavior for -// native frames (see |NativeWidgetWin::WidgetSizeIsClientSize()|), while other -// platforms currently always return client bounds from -// |GetWindowBoundsForClientBounds()|. -gfx::Size NativeFrameView::GetPreferredSize() { - return frame_->client_view()->GetPreferredSize(); +gfx::Size NativeFrameView::GetPreferredSize() const { + gfx::Size client_preferred_size = frame_->client_view()->GetPreferredSize(); +#if defined(OS_WIN) + // Returns the client size. On Windows, this is the expected behavior for + // native frames (see |NativeWidgetWin::WidgetSizeIsClientSize()|), while + // other platforms currently always return client bounds from + // |GetWindowBoundsForClientBounds()|. + return client_preferred_size; +#else + return frame_->non_client_view()->GetWindowBoundsForClientBounds( + gfx::Rect(client_preferred_size)).size(); +#endif } -gfx::Size NativeFrameView::GetMinimumSize() { +gfx::Size NativeFrameView::GetMinimumSize() const { return frame_->client_view()->GetMinimumSize(); } -gfx::Size NativeFrameView::GetMaximumSize() { +gfx::Size NativeFrameView::GetMaximumSize() const { return frame_->client_view()->GetMaximumSize(); } +const char* NativeFrameView::GetClassName() const { + return kViewClassName; +} + } // namespace views diff --git a/chromium/ui/views/window/native_frame_view.h b/chromium/ui/views/window/native_frame_view.h index 378e354bf79..154453d3eba 100644 --- a/chromium/ui/views/window/native_frame_view.h +++ b/chromium/ui/views/window/native_frame_view.h @@ -13,6 +13,8 @@ class Widget; class VIEWS_EXPORT NativeFrameView : public NonClientFrameView { public: + static const char kViewClassName[]; + explicit NativeFrameView(Widget* frame); virtual ~NativeFrameView(); @@ -28,9 +30,10 @@ class VIEWS_EXPORT NativeFrameView : public NonClientFrameView { virtual void UpdateWindowTitle() OVERRIDE; // View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual gfx::Size GetMinimumSize() OVERRIDE; - virtual gfx::Size GetMaximumSize() OVERRIDE; + virtual gfx::Size GetPreferredSize() const OVERRIDE; + virtual gfx::Size GetMinimumSize() const OVERRIDE; + virtual gfx::Size GetMaximumSize() const OVERRIDE; + virtual const char* GetClassName() const OVERRIDE; private: // Our containing frame. diff --git a/chromium/ui/views/window/non_client_view.cc b/chromium/ui/views/window/non_client_view.cc index f7cd70e5cd3..e4068dba177 100644 --- a/chromium/ui/views/window/non_client_view.cc +++ b/chromium/ui/views/window/non_client_view.cc @@ -4,7 +4,7 @@ #include "ui/views/window/non_client_view.h" -#include "ui/base/accessibility/accessible_view_state.h" +#include "ui/accessibility/ax_view_state.h" #include "ui/base/hit_test.h" #include "ui/gfx/rect_conversions.h" #include "ui/views/rect_based_targeting_utils.h" @@ -127,14 +127,14 @@ void NonClientView::LayoutFrameView() { frame_view_->Layout(); } -void NonClientView::SetAccessibleName(const string16& name) { +void NonClientView::SetAccessibleName(const base::string16& name) { accessible_name_ = name; } //////////////////////////////////////////////////////////////////////////////// // NonClientView, View overrides: -gfx::Size NonClientView::GetPreferredSize() { +gfx::Size NonClientView::GetPreferredSize() const { // TODO(pkasting): This should probably be made to look similar to // GetMinimumSize() below. This will require implementing GetPreferredSize() // better in the various frame views. @@ -142,11 +142,11 @@ gfx::Size NonClientView::GetPreferredSize() { return GetWindowBoundsForClientBounds(client_bounds).size(); } -gfx::Size NonClientView::GetMinimumSize() { +gfx::Size NonClientView::GetMinimumSize() const { return frame_view_->GetMinimumSize(); } -gfx::Size NonClientView::GetMaximumSize() { +gfx::Size NonClientView::GetMaximumSize() const { return frame_view_->GetMaximumSize(); } @@ -177,8 +177,8 @@ void NonClientView::ViewHierarchyChanged( } } -void NonClientView::GetAccessibleState(ui::AccessibleViewState* state) { - state->role = ui::AccessibilityTypes::ROLE_CLIENT; +void NonClientView::GetAccessibleState(ui::AXViewState* state) { + state->role = ui::AX_ROLE_CLIENT; state->name = accessible_name_; } @@ -186,8 +186,8 @@ const char* NonClientView::GetClassName() const { return kViewClassName; } -views::View* NonClientView::GetEventHandlerForRect(const gfx::Rect& rect) { - if (!views::UsePointBasedTargeting(rect)) +View* NonClientView::GetEventHandlerForRect(const gfx::Rect& rect) { + if (!UsePointBasedTargeting(rect)) return View::GetEventHandlerForRect(rect); // Because of the z-ordering of our child views (the client view is positioned @@ -212,7 +212,7 @@ views::View* NonClientView::GetEventHandlerForRect(const gfx::Rect& rect) { return View::GetEventHandlerForRect(rect); } -views::View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) { +View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) { // The same logic as for |GetEventHandlerForRect()| applies here. if (frame_view_->parent() == this) { // During the reset of the frame_view_ it's possible to be in this code @@ -220,7 +220,7 @@ views::View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) { // removed from the NonClientView. gfx::Point point_in_child_coords(point); View::ConvertPointToTarget(this, frame_view_.get(), &point_in_child_coords); - views::View* handler = + View* handler = frame_view_->GetTooltipHandlerForPoint(point_in_child_coords); if (handler) return handler; @@ -232,12 +232,23 @@ views::View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) { //////////////////////////////////////////////////////////////////////////////// // NonClientFrameView, public: +NonClientFrameView::~NonClientFrameView() { +} + void NonClientFrameView::SetInactiveRenderingDisabled(bool disable) { - if (paint_as_active_ == disable) + if (inactive_rendering_disabled_ == disable) return; - paint_as_active_ = disable; - ShouldPaintAsActiveChanged(); + bool should_paint_as_active_old = ShouldPaintAsActive(); + inactive_rendering_disabled_ = disable; + + // The widget schedules a paint when the activation changes. + if (should_paint_as_active_old != ShouldPaintAsActive()) + SchedulePaint(); +} + +bool NonClientFrameView::ShouldPaintAsActive() const { + return inactive_rendering_disabled_ || GetWidget()->IsActive(); } int NonClientFrameView::GetHTComponentForFrame(const gfx::Point& point, @@ -301,16 +312,8 @@ bool NonClientFrameView::HitTestRect(const gfx::Rect& rect) const { //////////////////////////////////////////////////////////////////////////////// // NonClientFrameView, protected: -bool NonClientFrameView::ShouldPaintAsActive() const { - return GetWidget()->IsActive() || paint_as_active_; -} - -void NonClientFrameView::ShouldPaintAsActiveChanged() { - SchedulePaint(); -} - -void NonClientFrameView::GetAccessibleState(ui::AccessibleViewState* state) { - state->role = ui::AccessibilityTypes::ROLE_CLIENT; +void NonClientFrameView::GetAccessibleState(ui::AXViewState* state) { + state->role = ui::AX_ROLE_CLIENT; } const char* NonClientFrameView::GetClassName() const { @@ -322,4 +325,7 @@ void NonClientFrameView::OnBoundsChanged(const gfx::Rect& previous_bounds) { // FrameView when it is itself laid out, see comment in NonClientView::Layout. } +NonClientFrameView::NonClientFrameView() : inactive_rendering_disabled_(false) { +} + } // namespace views diff --git a/chromium/ui/views/window/non_client_view.h b/chromium/ui/views/window/non_client_view.h index 2c3b1d9fe49..77181426418 100644 --- a/chromium/ui/views/window/non_client_view.h +++ b/chromium/ui/views/window/non_client_view.h @@ -37,12 +37,18 @@ class VIEWS_EXPORT NonClientFrameView : public View { kClientEdgeThickness = 1, }; + virtual ~NonClientFrameView(); + // Sets whether the window should be rendered as active regardless of the // actual active state. Used when bubbles become active to make their parent // appear active. A value of true makes the window render as active always, // false gives normal behavior. void SetInactiveRenderingDisabled(bool disable); + // Used to determine if the frame should be painted as active. Keyed off the + // window's actual active state and |inactive_rendering_disabled_|. + bool ShouldPaintAsActive() const; + // Helper for non-client view implementations to determine which area of the // window border the specified |point| falls within. The other parameters are // the size of the sizing edges, and whether or not the window can be @@ -74,28 +80,18 @@ class VIEWS_EXPORT NonClientFrameView : public View { // Overridden from View: virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; - virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; virtual const char* GetClassName() const OVERRIDE; protected: virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; - NonClientFrameView() : paint_as_active_(false) {} - - // Used to determine if the frame should be painted as active. Keyed off the - // window's actual active state and the override, see - // SetInactiveRenderingDisabled() above. - bool ShouldPaintAsActive() const; - - // Invoked from SetInactiveRenderingDisabled(). This implementation invokes - // SchedulesPaint as necessary. - virtual void ShouldPaintAsActiveChanged(); + NonClientFrameView(); private: - // True when the non-client view should always be rendered as if the window - // were active, regardless of whether or not the top level window actually - // is active. - bool paint_as_active_; + // Prevents the non-client frame view from being rendered as inactive when + // true. + bool inactive_rendering_disabled_; }; //////////////////////////////////////////////////////////////////////////////// @@ -166,8 +162,6 @@ class VIEWS_EXPORT NonClientView : public View { // Prevents the window from being rendered as deactivated when |disable| is // true, until called with |disable| false. Used when a sub-window is to be // shown that shouldn't visually de-activate the window. - // Subclasses can override this to perform additional actions when this value - // changes. void SetInactiveRenderingDisabled(bool disable); // Returns the bounds of the window required to display the content area at @@ -208,14 +202,14 @@ class VIEWS_EXPORT NonClientView : public View { void LayoutFrameView(); // Set the accessible name of this view. - void SetAccessibleName(const string16& name); + void SetAccessibleName(const base::string16& name); // NonClientView, View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual gfx::Size GetMinimumSize() OVERRIDE; - virtual gfx::Size GetMaximumSize() OVERRIDE; + virtual gfx::Size GetPreferredSize() const OVERRIDE; + virtual gfx::Size GetMinimumSize() const OVERRIDE; + virtual gfx::Size GetMaximumSize() const OVERRIDE; virtual void Layout() OVERRIDE; - virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; virtual const char* GetClassName() const OVERRIDE; virtual views::View* GetEventHandlerForRect(const gfx::Rect& rect) OVERRIDE; @@ -243,7 +237,7 @@ class VIEWS_EXPORT NonClientView : public View { View* overlay_view_; // The accessible name of this view. - string16 accessible_name_; + base::string16 accessible_name_; DISALLOW_COPY_AND_ASSIGN(NonClientView); }; diff --git a/chromium/ui/views/window/window_button_order_provider.cc b/chromium/ui/views/window/window_button_order_provider.cc new file mode 100644 index 00000000000..b1ac70e4727 --- /dev/null +++ b/chromium/ui/views/window/window_button_order_provider.cc @@ -0,0 +1,41 @@ +// 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 "ui/views/window/window_button_order_provider.h" + +namespace views { + +// static +WindowButtonOrderProvider* WindowButtonOrderProvider::instance_ = NULL; + +/////////////////////////////////////////////////////////////////////////////// +// WindowButtonOrderProvider, public: + +// static +WindowButtonOrderProvider* WindowButtonOrderProvider::GetInstance() { + if (!instance_) + instance_ = new WindowButtonOrderProvider; + return instance_; +} + +/////////////////////////////////////////////////////////////////////////////// +// WindowButtonOrderProvider, protected: + +WindowButtonOrderProvider::WindowButtonOrderProvider() { + trailing_buttons_.push_back(views::FRAME_BUTTON_MINIMIZE); + trailing_buttons_.push_back(views::FRAME_BUTTON_MAXIMIZE); + trailing_buttons_.push_back(views::FRAME_BUTTON_CLOSE); +} + +WindowButtonOrderProvider::~WindowButtonOrderProvider() { +} + +void WindowButtonOrderProvider::SetWindowButtonOrder( + const std::vector<views::FrameButton>& leading_buttons, + const std::vector<views::FrameButton>& trailing_buttons) { + leading_buttons_ = leading_buttons; + trailing_buttons_ = trailing_buttons; +} + +} // namespace views diff --git a/chromium/ui/views/window/window_button_order_provider.h b/chromium/ui/views/window/window_button_order_provider.h new file mode 100644 index 00000000000..f50a49f0fb7 --- /dev/null +++ b/chromium/ui/views/window/window_button_order_provider.h @@ -0,0 +1,56 @@ +// 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. + +#ifndef UI_VIEWS_WINDOW_WINDOW_BUTTON_ORDER_PROVIDER_H_ +#define UI_VIEWS_WINDOW_WINDOW_BUTTON_ORDER_PROVIDER_H_ + +#include <vector> + +#include "base/macros.h" +#include "ui/views/views_export.h" +#include "ui/views/window/frame_buttons.h" + +namespace views { + +// Stores the ordering of window control buttons. Provides a default ordering +// of |FRAME_BUTTON_MINIMZE|, |FRAME_BUTTON_MAXIMIZE|, |FRAME_BUTTON_CLOSE|, +// where all controls are on the trailing end of a window. +// +// On Linux users can provide configuration files to control the ordering. This +// configuration is checked and overrides the defaults. +class VIEWS_EXPORT WindowButtonOrderProvider { + public: + static WindowButtonOrderProvider* GetInstance(); + + const std::vector<views::FrameButton>& leading_buttons() const { + return leading_buttons_; + } + + const std::vector<views::FrameButton>& trailing_buttons() const { + return trailing_buttons_; + } + + void SetWindowButtonOrder( + const std::vector<views::FrameButton>& leading_buttons, + const std::vector<views::FrameButton>& trailing_buttons); + + protected: + WindowButtonOrderProvider(); + virtual ~WindowButtonOrderProvider(); + + private: + static WindowButtonOrderProvider* instance_; + + // Layout arrangement of the window caption buttons. On linux these will be + // set via a WindowButtonOrderObserver. On other platforms a default + // arrangement of a trailing minimize, maximize, close, will be set. + std::vector<views::FrameButton> leading_buttons_; + std::vector<views::FrameButton> trailing_buttons_; + + DISALLOW_COPY_AND_ASSIGN(WindowButtonOrderProvider); +}; + +} // namespace views + +#endif // UI_VIEWS_WINDOW_WINDOW_BUTTON_ORDER_PROVIDER_H_ |