diff options
author | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-26 22:21:33 +0000 |
---|---|---|
committer | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-26 22:21:33 +0000 |
commit | f60d96e82acd547ac834b93cd68865b66ab5b4da (patch) | |
tree | 39ed109f14436569c10a4b174ef05b8a9f2e23d9 | |
parent | 64dd7528390cfa04d8992714480358c056b508e9 (diff) | |
download | chromium_src-f60d96e82acd547ac834b93cd68865b66ab5b4da.zip chromium_src-f60d96e82acd547ac834b93cd68865b66ab5b4da.tar.gz chromium_src-f60d96e82acd547ac834b93cd68865b66ab5b4da.tar.bz2 |
Support resizing detached panels on Windows via system-resizing.
BUG=none
TEST=Manual test by resizing detached panels
Review URL: https://chromiumcodereview.appspot.com/9858028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129021 0039d316-1c4b-4281-b951-d872f2087c98
5 files changed, 139 insertions, 44 deletions
diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.cc b/chrome/browser/ui/panels/panel_browser_frame_view.cc index b38d57f9..6d10d99 100644 --- a/chrome/browser/ui/panels/panel_browser_frame_view.cc +++ b/chrome/browser/ui/panels/panel_browser_frame_view.cc @@ -53,13 +53,24 @@ const int kTitlebarHeight = 24; // The thickness in pixels of the border. #if defined(USE_AURA) // No border inside the window frame; see comment in PaintFrameBorder(). -const int kBorderThickness = 0; +const int kResizableBorderThickness = 0; +const int kNonResizableBorderThickness = 0; #else -const int kBorderThickness = 1; +const int kResizableBorderThickness = 4; +const int kNonResizableBorderThickness = 1; #endif -// No client edge is present. -const int kPanelClientEdgeThickness = 0; +// Client edge is only present on thick border when the panel is resizable. +const int kResizableClientEdgeThickness = 1; +const int kNonResizableClientEdgeThickness = 0; + +// In the window corners, the resize areas don't actually expand bigger, but the +// 16 px at the end of each edge triggers diagonal resizing. +const int kResizeAreaCornerSize = 16; + +// Colors used to draw client edges. These are experimental values. +const SkColor kClientEdgeColor = SkColorSetRGB(210, 225, 246); +const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); // The spacing in pixels between the icon and the left border. const int kIconAndBorderSpacing = 4; @@ -203,6 +214,18 @@ const EdgeResources& GetFrameEdges() { return *edges; } +const EdgeResources& GetClientEdges() { + static EdgeResources* edges = NULL; + if (!edges) { + edges = new EdgeResources( + IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, + IDR_APP_TOP_RIGHT, IDR_CONTENT_RIGHT_SIDE, + IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER, + IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE); + } + return *edges; +} + const gfx::Font& GetTitleFont() { static gfx::Font* font = NULL; if (!font) { @@ -213,30 +236,36 @@ const gfx::Font& GetTitleFont() { } const SkPaint& GetActiveBackgroundDefaultPaint() { - static SkPaint* paint = NULL; - if (!paint) { - paint = CreateGradientPaint(kActiveBackgroundDefaultColorStart, - kActiveBackgroundDefaultColorEnd); - } + static SkPaint* paint = NULL;
+ if (!paint) {
+ paint = CreateGradientPaint(kActiveBackgroundDefaultColorStart,
+ kActiveBackgroundDefaultColorEnd);
+ }
return *paint; } -const SkPaint& GetInactiveBackgroundDefaultPaint() { - static SkPaint* paint = NULL; - if (!paint) { - paint = CreateGradientPaint(kInactiveBackgroundDefaultColorStart, - kInactiveBackgroundDefaultColorEnd); - } - return *paint; +const SkPaint& GetInactiveBackgroundDefaultPaint() {
+ static SkPaint* paint = NULL;
+ if (!paint) {
+ paint = CreateGradientPaint(kInactiveBackgroundDefaultColorStart,
+ kInactiveBackgroundDefaultColorEnd);
+ }
+ return *paint;
+}
+
+const SkPaint& GetAttentionBackgroundDefaultPaint() {
+ static SkPaint* paint = NULL;
+ if (!paint) {
+ paint = CreateGradientPaint(kAttentionBackgroundDefaultColorStart,
+ kAttentionBackgroundDefaultColorEnd);
+ }
+ return *paint;
} -const SkPaint& GetAttentionBackgroundDefaultPaint() { - static SkPaint* paint = NULL; - if (!paint) { - paint = CreateGradientPaint(kAttentionBackgroundDefaultColorStart, - kAttentionBackgroundDefaultColorEnd); - } - return *paint; +bool IsHitTestValueForResizing(int hc) { + return hc == HTLEFT || hc == HTRIGHT || hc == HTTOP || hc == HTBOTTOM || + hc == HTTOPLEFT || hc == HTTOPRIGHT || hc == HTBOTTOMLEFT || + hc == HTBOTTOMRIGHT; } } // namespace @@ -438,8 +467,8 @@ int PanelBrowserFrameView::NonClientHitTest(const gfx::Point& point) { int window_component = GetHTComponentForFrame(point, NonClientBorderThickness(), NonClientBorderThickness(), - 0, 0, - frame()->widget_delegate()->CanResize()); + kResizeAreaCornerSize, kResizeAreaCornerSize, + CanResize()); // Fall back to the caption if no other component matches. return (window_component == HTNOWHERE) ? HTCAPTION : window_component; } @@ -482,16 +511,18 @@ void PanelBrowserFrameView::OnPaint(gfx::Canvas* canvas) { UpdateControlStyles(paint_state); PaintFrameBorder(canvas); + PaintClientEdge(canvas); } void PanelBrowserFrameView::OnThemeChanged() { } gfx::Size PanelBrowserFrameView::GetMinimumSize() { - // This makes the panel be able to shrink to very small, like 4-pixel lines. - // Since the panel cannot be resized by the user, we do not need to enforce - // the minimum size. - return gfx::Size(); + return panel_browser_view_->panel()->min_size(); +} + +gfx::Size PanelBrowserFrameView::GetMaximumSize() { + return panel_browser_view_->panel()->max_size(); } void PanelBrowserFrameView::Layout() { @@ -533,7 +564,7 @@ void PanelBrowserFrameView::Layout() { if (show_close_button) { gfx::Size close_button_size = close_button_->GetPreferredSize(); close_button_->SetBounds( - width() - kBorderThickness - kCloseButtonAndBorderSpacing - + width() - NonClientBorderThickness() - kCloseButtonAndBorderSpacing - close_button_size.width(), (NonClientTopBorderHeight() - close_button_size.height()) / 2, close_button_size.width(), @@ -566,7 +597,7 @@ void PanelBrowserFrameView::Layout() { // Layout the icon. int icon_y = (NonClientTopBorderHeight() - kIconSize) / 2; title_icon_->SetBounds( - kBorderThickness + kIconAndBorderSpacing, + NonClientBorderThickness() + kIconAndBorderSpacing, icon_y, kIconSize, kIconSize); @@ -597,9 +628,14 @@ void PanelBrowserFrameView::GetAccessibleState(ui::AccessibleViewState* state) { } bool PanelBrowserFrameView::OnMousePressed(const views::MouseEvent& event) { + gfx::Point mouse_location = event.location(); + + if (CanResize() && + IsHitTestValueForResizing(NonClientHitTest(mouse_location))) + return BrowserNonClientFrameView::OnMousePressed(event); + // |event.location| is in the view's coordinate system. Convert it to the // screen coordinate system. - gfx::Point mouse_location = event.location(); views::View::ConvertPointToScreen(this, &mouse_location); if (event.IsOnlyLeftMouseButton() && @@ -692,11 +728,14 @@ void PanelBrowserFrameView::AnimationCanceled(const ui::Animation* animation) { } int PanelBrowserFrameView::NonClientBorderThickness() const { - return kBorderThickness + kPanelClientEdgeThickness; + if (CanResize()) + return kResizableBorderThickness + kResizableClientEdgeThickness; + else + return kNonResizableBorderThickness + kNonResizableClientEdgeThickness; } int PanelBrowserFrameView::NonClientTopBorderHeight() const { - return kBorderThickness + kTitlebarHeight + kPanelClientEdgeThickness; + return NonClientBorderThickness() + kTitlebarHeight; } gfx::Size PanelBrowserFrameView::NonClientAreaSize() const { @@ -705,7 +744,7 @@ gfx::Size PanelBrowserFrameView::NonClientAreaSize() const { } int PanelBrowserFrameView::IconOnlyWidth() const { - return kBorderThickness * 2 + kIconAndBorderSpacing * 2 + kIconSize; + return NonClientBorderThickness() * 2 + kIconAndBorderSpacing * 2 + kIconSize; } gfx::Size PanelBrowserFrameView::IconOnlySize() const { @@ -764,6 +803,25 @@ const SkPaint& PanelBrowserFrameView::GetDefaultFrameTheme( } } +SkColor PanelBrowserFrameView::GetFrameColor(PaintState paint_state) const { + bool use_default_color = UsingDefaultTheme(); + ui::ThemeProvider* theme_provider = GetThemeProvider(); + switch (paint_state) { + case PAINT_AS_INACTIVE: { + return use_default_color ? kInactiveBackgroundDefaultColorEnd : + theme_provider->GetColor(ThemeService::COLOR_FRAME_INACTIVE); + } case PAINT_AS_ACTIVE: { + return use_default_color ? kActiveBackgroundDefaultColorEnd : + theme_provider->GetColor(ThemeService::COLOR_FRAME); + } case PAINT_FOR_ATTENTION: { + return kAttentionBackgroundDefaultColorEnd; + } default: { + NOTREACHED(); + return SkColor(); + } + } +} + SkBitmap* PanelBrowserFrameView::GetFrameTheme(PaintState paint_state) const { switch (paint_state) { case PAINT_AS_INACTIVE: @@ -796,13 +854,18 @@ void PanelBrowserFrameView::UpdateControlStyles(PaintState paint_state) { } void PanelBrowserFrameView::PaintFrameBorder(gfx::Canvas* canvas) { - // Paint the background. + // Fill with the frame color first so we have a constant background for + // areas not covered by the theme image. + canvas->FillRect(gfx::Rect(0, 0, width(), height()), + GetFrameColor(paint_state_)); + + // Paint the background using the theme. if (paint_state_ == PAINT_FOR_ATTENTION || UsingDefaultTheme()) { const SkPaint& paint = GetDefaultFrameTheme(paint_state_); canvas->DrawRect(gfx::Rect(0, 0, width(), kTitlebarHeight), paint); } else { SkBitmap* bitmap = GetFrameTheme(paint_state_); - canvas->TileImageInt(*bitmap, 0, 0, width(), kTitlebarHeight); + canvas->TileImageInt(*bitmap, 0, 0, width(), bitmap->height()); } #if defined(USE_AURA) @@ -855,14 +918,32 @@ void PanelBrowserFrameView::PaintFrameBorder(gfx::Canvas* canvas) { frame_edges.bottom_left->height()); // Draw the divider between the titlebar and the client area. - if (height() > kTitlebarHeight) { - canvas->DrawRect(gfx::Rect(kBorderThickness, kTitlebarHeight, - width() - 1 - 2 * kBorderThickness, - kBorderThickness), kDividerColor); + if (height() > kTitlebarHeight && !CanResize()) { + canvas->DrawRect(gfx::Rect(NonClientBorderThickness(), kTitlebarHeight, + width() - 1 - 2 * NonClientBorderThickness(), + NonClientBorderThickness()), kDividerColor); } #endif // !defined(USE_AURA) } +void PanelBrowserFrameView::PaintClientEdge(gfx::Canvas* canvas) { +#if !defined(USE_AURA) + // No need to draw client edges when a non-resizable panel that has thin + // border. + if (!CanResize()) + return; + + gfx::Rect client_edge_bounds(client_view_bounds_); + client_edge_bounds.Inset(-kResizableClientEdgeThickness, + -kResizableClientEdgeThickness); + gfx::Rect frame_shadow_bounds(client_edge_bounds); + frame_shadow_bounds.Inset(-kFrameShadowThickness, -kFrameShadowThickness); + + canvas->FillRect(frame_shadow_bounds, kContentsBorderShadow); + canvas->FillRect(client_edge_bounds, kClientEdgeColor); +#endif // !defined(USE_AURA) +} + string16 PanelBrowserFrameView::GetTitleText() const { return frame()->widget_delegate()->GetWindowTitle(); } @@ -942,3 +1023,7 @@ bool PanelBrowserFrameView::EnsureSettingsMenuCreated() { settings_menu_runner_.reset(new views::MenuRunner(settings_menu_)); return true; } + +bool PanelBrowserFrameView::CanResize() const { + return panel_browser_view_->panel()->CanResizeByMouse(); +} diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.h b/chrome/browser/ui/panels/panel_browser_frame_view.h index 152a9c9..92a8eb8 100644 --- a/chrome/browser/ui/panels/panel_browser_frame_view.h +++ b/chrome/browser/ui/panels/panel_browser_frame_view.h @@ -78,6 +78,7 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; virtual void OnThemeChanged() OVERRIDE; virtual gfx::Size GetMinimumSize() OVERRIDE; + virtual gfx::Size GetMaximumSize() OVERRIDE; virtual void Layout() OVERRIDE; virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE; @@ -150,6 +151,7 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, // Custom draw the frame. void PaintFrameBorder(gfx::Canvas* canvas); + void PaintClientEdge(gfx::Canvas* canvas); // Called by MouseWatcher to notify if the mouse enters or leaves the window. void OnMouseEnterOrLeaveWindow(bool mouse_entered); @@ -158,6 +160,7 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, SkColor GetDefaultTitleColor(PaintState paint_state) const; SkColor GetTitleColor(PaintState paint_state) const; const SkPaint& GetDefaultFrameTheme(PaintState paint_state) const; + SkColor GetFrameColor(PaintState paint_state) const; SkBitmap* GetFrameTheme(PaintState paint_state) const; // Make settings button visible if either of the conditions is met: @@ -173,6 +176,8 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView, string16 GetTitleText() const; + bool CanResize() const; + #ifdef UNIT_TEST PanelSettingsMenuModel* settings_menu_model() const { return settings_menu_model_.get(); diff --git a/chrome/browser/ui/panels/panel_browser_view.cc b/chrome/browser/ui/panels/panel_browser_view.cc index b0282ac..9c2e3e0 100644 --- a/chrome/browser/ui/panels/panel_browser_view.cc +++ b/chrome/browser/ui/panels/panel_browser_view.cc @@ -118,7 +118,7 @@ void PanelBrowserView::Deactivate() { } bool PanelBrowserView::CanResize() const { - return false; + return true; } bool PanelBrowserView::CanMaximize() const { @@ -273,6 +273,10 @@ bool PanelBrowserView::WillProcessWorkAreaChange() const { return true; } +void PanelBrowserView::OnWindowEndUserBoundsChange() { + bounds_ = GetBounds(); +} + void PanelBrowserView::ShowPanel() { Show(); } @@ -588,6 +592,8 @@ void PanelBrowserView::SetPanelAppIconVisibility(bool visible) { void PanelBrowserView::SetPanelAlwaysOnTop(bool on_top) { GetWidget()->SetAlwaysOnTop(on_top); + GetWidget()->non_client_view()->Layout(); + GetWidget()->client_view()->Layout(); } bool PanelBrowserView::IsAnimatingBounds() const { diff --git a/chrome/browser/ui/panels/panel_browser_view.h b/chrome/browser/ui/panels/panel_browser_view.h index 883a9ed..cdb07d9 100644 --- a/chrome/browser/ui/panels/panel_browser_view.h +++ b/chrome/browser/ui/panels/panel_browser_view.h @@ -79,6 +79,7 @@ class PanelBrowserView : public BrowserView, virtual void OnDisplayChanged() OVERRIDE; virtual void OnWorkAreaChanged() OVERRIDE; virtual bool WillProcessWorkAreaChange() const OVERRIDE; + virtual void OnWindowEndUserBoundsChange() OVERRIDE; // Overridden from views::Widget::Observer virtual void OnWidgetActivationChanged(views::Widget* widget, diff --git a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc index ece694f..1f7bcc5 100644 --- a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc +++ b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc @@ -404,7 +404,6 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanelActive) { LONG styles = ::GetWindowLong(native_window, GWL_STYLE); EXPECT_EQ(0, styles & WS_MAXIMIZEBOX); EXPECT_EQ(0, styles & WS_MINIMIZEBOX); - EXPECT_EQ(0, styles & WS_THICKFRAME); LONG ext_styles = ::GetWindowLong(native_window, GWL_EXSTYLE); EXPECT_EQ(WS_EX_TOPMOST, ext_styles & WS_EX_TOPMOST); @@ -429,7 +428,6 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanelInactive) { LONG styles = ::GetWindowLong(native_window, GWL_STYLE); EXPECT_EQ(0, styles & WS_MAXIMIZEBOX); EXPECT_EQ(0, styles & WS_MINIMIZEBOX); - EXPECT_EQ(0, styles & WS_THICKFRAME); LONG ext_styles = ::GetWindowLong(native_window, GWL_EXSTYLE); EXPECT_EQ(WS_EX_TOPMOST, ext_styles & WS_EX_TOPMOST); |