summaryrefslogtreecommitdiffstats
path: root/chromium/ui/views/window
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ui/views/window
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (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')
-rw-r--r--chromium/ui/views/window/client_view.cc12
-rw-r--r--chromium/ui/views/window/client_view.h8
-rw-r--r--chromium/ui/views/window/custom_frame_view.cc245
-rw-r--r--chromium/ui/views/window/custom_frame_view.h33
-rw-r--r--chromium/ui/views/window/custom_frame_view_unittest.cc252
-rw-r--r--chromium/ui/views/window/dialog_client_view.cc61
-rw-r--r--chromium/ui/views/window/dialog_client_view.h3
-rw-r--r--chromium/ui/views/window/dialog_delegate.cc68
-rw-r--r--chromium/ui/views/window/dialog_delegate.h25
-rw-r--r--chromium/ui/views/window/dialog_delegate_unittest.cc40
-rw-r--r--chromium/ui/views/window/frame_background.cc39
-rw-r--r--chromium/ui/views/window/frame_background.h15
-rw-r--r--chromium/ui/views/window/native_frame_view.cc37
-rw-r--r--chromium/ui/views/window/native_frame_view.h9
-rw-r--r--chromium/ui/views/window/non_client_view.cc54
-rw-r--r--chromium/ui/views/window/non_client_view.h40
-rw-r--r--chromium/ui/views/window/window_button_order_provider.cc41
-rw-r--r--chromium/ui/views/window/window_button_order_provider.h56
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_