diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-23 07:12:26 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-23 07:12:26 +0000 |
commit | c38ba0250a72f17c2b5caed4dc96dcca8db927b2 (patch) | |
tree | 2b96576c37cb39ef75d2d4f30d69c4cc049527a4 | |
parent | 1c12ae7b1d3af2578e0fa8411bf70e5e627eebfe (diff) | |
download | chromium_src-c38ba0250a72f17c2b5caed4dc96dcca8db927b2.zip chromium_src-c38ba0250a72f17c2b5caed4dc96dcca8db927b2.tar.gz chromium_src-c38ba0250a72f17c2b5caed4dc96dcca8db927b2.tar.bz2 |
Make sure the RootView is sized to the correct bounds when the opaque frame is maximized.It seems that now, when an opaque frame is maximized we also need to add the SM_CXSIZEFRAME to the top of the client rect. I don't know why, it's just is.I reworked the way Widget allows subclasses to handle sizing of the RootView... I delegate responsibility for determining the RootView's bounds to a helper virtual function which BrowserFrameWin overrides. This seems cleaner to me. I make sure this handling only occurs when the window is not maximized.http://crbug.com/25227TEST=use to a theme or switch off glass on vista or use Xp. Maximize the browser window. The tabs should be entirely visible.
Review URL: http://codereview.chromium.org/304007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29882 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | app/gfx/insets.h | 3 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_frame_win.cc | 89 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_frame_win.h | 5 | ||||
-rw-r--r-- | views/widget/widget_win.cc | 29 | ||||
-rw-r--r-- | views/widget/widget_win.h | 10 | ||||
-rw-r--r-- | views/window/window_win.cc | 80 | ||||
-rw-r--r-- | views/window/window_win.h | 8 |
7 files changed, 114 insertions, 110 deletions
diff --git a/app/gfx/insets.h b/app/gfx/insets.h index 6a4ac05..6b8e9b1 100644 --- a/app/gfx/insets.h +++ b/app/gfx/insets.h @@ -33,6 +33,9 @@ class Insets { // top and bottom insets. int height() const { return top_ + bottom_; } + // Returns true if the insets are empty. + bool empty() const { return width() == 0 && height() == 0; } + void Set(int top, int left, int bottom, int right) { top_ = top; left_ = left; diff --git a/chrome/browser/views/frame/browser_frame_win.cc b/chrome/browser/views/frame/browser_frame_win.cc index 2616dfb..f9c1bbb 100644 --- a/chrome/browser/views/frame/browser_frame_win.cc +++ b/chrome/browser/views/frame/browser_frame_win.cc @@ -119,7 +119,18 @@ bool BrowserFrameWin::AlwaysUseNativeFrame() const { } /////////////////////////////////////////////////////////////////////////////// -// BrowserFrame, views::WidgetWin overrides: +// BrowserFrame, views::WindowWin overrides: + +gfx::Insets BrowserFrameWin::GetClientAreaInsets() const { + if (!GetNonClientView()->UseNativeFrame()) + return WindowWin::GetClientAreaInsets(); + + int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); + // We draw our own client edge over part of the default frame. + if (!IsMaximized()) + border_thickness -= kClientEdgeThickness; + return gfx::Insets(0, border_thickness, border_thickness, border_thickness); +} bool BrowserFrameWin::GetAccelerator(int cmd_id, views::Accelerator* accelerator) { @@ -181,78 +192,6 @@ LRESULT BrowserFrameWin::OnNCActivate(BOOL active) { return WindowWin::OnNCActivate(active); } -LRESULT BrowserFrameWin::OnNCCalcSize(BOOL mode, LPARAM l_param) { - // This class' client rect calculations are specific to the tabbed browser - // window. When the glass frame is active, the client area is reported to be - // a rectangle that touches the top of the window and is inset from the left, - // right and bottom edges. The client rect touches the top because the - // tabstrip is painted over the caption at a custom offset. - // When the glass frame is not active, the client area is reported to be the - // entire window rect, except for the cases noted below. - // For non-tabbed browser windows, we use the default handling from the - // views system. - if (!browser_view_->IsBrowserTypeNormal()) - return WindowWin::OnNCCalcSize(mode, l_param); - - RECT* client_rect = mode ? - &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] : - reinterpret_cast<RECT*>(l_param); - int border_thickness = 0; - if (browser_view_->IsMaximized()) { - // Make the maximized mode client rect fit the screen exactly, by - // subtracting the border Windows automatically adds for maximized mode. - border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); - // Find all auto-hide taskbars along the screen edges and adjust in by the - // thickness of the auto-hide taskbar on each such edge, so the window isn't - // treated as a "fullscreen app", which would cause the taskbars to - // disappear. - HMONITOR monitor = MonitorFromWindow(GetNativeView(), - MONITOR_DEFAULTTONULL); - if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor)) - client_rect->left += win_util::kAutoHideTaskbarThicknessPx; - if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor)) - client_rect->right -= win_util::kAutoHideTaskbarThicknessPx; - if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor)) { - client_rect->bottom -= win_util::kAutoHideTaskbarThicknessPx; - } else if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) { - // Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of - // WM_NCHITTEST, having any nonclient area atop the window causes the - // caption buttons to draw onscreen but not respond to mouse hover/clicks. - // So for a taskbar at the screen top, we can't push the client_rect->top - // down; instead, we move the bottom up by one pixel, which is the - // smallest change we can make and still get a client area less than the - // screen size. This is visibly ugly, but there seems to be no better - // solution. - --client_rect->bottom; - } - } else if (!browser_view_->IsFullscreen()) { - if (GetNonClientView()->UseNativeFrame()) { - // We draw our own client edge over part of the default frame. - border_thickness = - GetSystemMetrics(SM_CXSIZEFRAME) - kClientEdgeThickness; - } else { - // This is weird, but highly essential. If we don't offset the bottom edge - // of the client rect, the window client area and window area will match, - // and when returning to glass rendering mode from non-glass, the client - // area will not paint black as transparent. This is because (and I don't - // know why) the client area goes from matching the window rect to being - // something else. If the client area is not the window rect in both - // modes, the blackness doesn't occur. Because of this, we need to tell - // the RootView to lay out to fit the window rect, rather than the client - // rect when using the opaque frame. See SizeRootViewToWindowRect. - --client_rect->bottom; - } - } - client_rect->left += border_thickness; - client_rect->right -= border_thickness; - client_rect->bottom -= border_thickness; - - // We'd like to return WVR_REDRAW in some cases here, but because we almost - // always have nonclient area (except in fullscreen mode, where it doesn't - // matter), we can't. See comments in window.cc:OnNCCalcSize() for more info. - return 0; -} - LRESULT BrowserFrameWin::OnNCHitTest(const CPoint& pt) { // Only do DWM hit-testing when we are using the native frame. if (GetNonClientView()->UseNativeFrame()) { @@ -320,10 +259,6 @@ ThemeProvider* BrowserFrameWin::GetDefaultThemeProvider() const { return profile_->GetThemeProvider(); } -bool BrowserFrameWin::SizeRootViewToWindowRect() const { - return !GetNonClientView()->UseNativeFrame(); -} - /////////////////////////////////////////////////////////////////////////////// // BrowserFrame, views::CustomFrameWindow overrides: diff --git a/chrome/browser/views/frame/browser_frame_win.h b/chrome/browser/views/frame/browser_frame_win.h index df59f36..789795b 100644 --- a/chrome/browser/views/frame/browser_frame_win.h +++ b/chrome/browser/views/frame/browser_frame_win.h @@ -47,7 +47,8 @@ class BrowserFrameWin : public BrowserFrame, public views::WindowWin { virtual bool AlwaysUseNativeFrame() const; protected: - // Overridden from views::WidgetWin: + // Overridden from views::WindowWin: + virtual gfx::Insets GetClientAreaInsets() const; virtual bool GetAccelerator(int cmd_id, views::Accelerator* accelerator); virtual void OnEndSession(BOOL ending, UINT logoff); virtual void OnEnterSizeMove(); @@ -59,12 +60,10 @@ class BrowserFrameWin : public BrowserFrame, public views::WindowWin { virtual void OnMove(const CPoint& point); virtual void OnMoving(UINT param, LPRECT new_bounds); virtual LRESULT OnNCActivate(BOOL active); - virtual LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param); virtual LRESULT OnNCHitTest(const CPoint& pt); virtual void OnWindowPosChanged(WINDOWPOS* window_pos); virtual ThemeProvider* GetThemeProvider() const; virtual ThemeProvider* GetDefaultThemeProvider() const; - virtual bool SizeRootViewToWindowRect() const; // Overridden from views::Window: virtual int GetShowState() const; diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index 485f1ae..15a10f2 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -834,6 +834,16 @@ void WidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) { SetMsgHandled(FALSE); } +gfx::Size WidgetWin::GetRootViewSize() const { + CRect rect; + if (use_layered_buffer_) + GetWindowRect(&rect); + else + GetClientRect(&rect); + + return gfx::Size(rect.Width(), rect.Height()); +} + /////////////////////////////////////////////////////////////////////////////// // WidgetWin, protected: @@ -950,23 +960,18 @@ void WidgetWin::ProcessMouseExited() { } void WidgetWin::LayoutRootView() { - CRect rect; - if (SizeRootViewToWindowRect() || use_layered_buffer_) { - GetWindowRect(&rect); - } else { - GetClientRect(&rect); - } + gfx::Size size(GetRootViewSize()); if (use_layered_buffer_) - SizeContents(rect); + SizeContents(size); // Resizing changes the size of the view hierarchy and thus forces a // complete relayout. - root_view_->SetBounds(0, 0, rect.Width(), rect.Height()); + root_view_->SetBounds(0, 0, size.width(), size.height()); root_view_->SchedulePaint(); if (use_layered_buffer_) - PaintNow(gfx::Rect(rect)); + PaintNow(gfx::Rect(0, 0, size.width(), size.height())); } bool WidgetWin::ReleaseCaptureOnMouseReleased() { @@ -995,9 +1000,9 @@ Window* WidgetWin::GetWindowImpl(HWND hwnd) { return NULL; } -void WidgetWin::SizeContents(const CRect& window_rect) { - contents_.reset(new gfx::Canvas(window_rect.Width(), - window_rect.Height(), +void WidgetWin::SizeContents(const gfx::Size& window_size) { + contents_.reset(new gfx::Canvas(window_size.width(), + window_size.height(), false)); } diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h index f8ba2a5..4f79a76 100644 --- a/views/widget/widget_win.h +++ b/views/widget/widget_win.h @@ -387,12 +387,8 @@ class WidgetWin : public app::WindowImpl, // behavior. virtual void OnFinalMessage(HWND window); - // Returns true if the RootView should be sized to the window rect instead of - // the client rect when the widget is resized. This is true if the widget's - // WM_NCCALCSIZE handler returns a client rect that differs from the window - // rect but the painted content of the window should still fill the entire - // visible window. - virtual bool SizeRootViewToWindowRect() const { return false; } + // Returns the size that the RootView should be set to in LayoutRootView(). + virtual gfx::Size GetRootViewSize() const; // Start tracking all mouse events so that this window gets sent mouse leave // messages too. @@ -459,7 +455,7 @@ class WidgetWin : public app::WindowImpl, // Resize the bitmap used to contain the contents of the layered window. This // recreates the entire bitmap. - void SizeContents(const CRect& window_rect); + void SizeContents(const gfx::Size& window_size); // Paint into a DIB and then update the layered window with its contents. void PaintLayeredWindow(); diff --git a/views/window/window_win.cc b/views/window/window_win.cc index 98c4aa7..f77b806 100644 --- a/views/window/window_win.cc +++ b/views/window/window_win.cc @@ -528,6 +528,33 @@ void WindowWin::SizeWindowToDefault() { false); } +gfx::Insets WindowWin::GetClientAreaInsets() const { + // Returning an empty Insets object causes the default handling in + // WidgetWin::OnNCCalcSize() to be invoked. + if (GetNonClientView()->UseNativeFrame()) + return gfx::Insets(); + + if (IsMaximized()) { + // Windows automatically adds a standard width border to all sides when a + // window is maximized. + int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); + return gfx::Insets(border_thickness, border_thickness, border_thickness, + border_thickness); + } + // This is weird, but highly essential. If we don't offset the bottom edge + // of the client rect, the window client area and window area will match, + // and when returning to glass rendering mode from non-glass, the client + // area will not paint black as transparent. This is because (and I don't + // know why) the client area goes from matching the window rect to being + // something else. If the client area is not the window rect in both + // modes, the blackness doesn't occur. Because of this, we need to tell + // the RootView to lay out to fit the window rect, rather than the client + // rect when using the opaque frame. See GetRootViewSize. + // Note: this is only required for non-fullscreen windows. Note that + // fullscreen windows are in restored state, not maximized. + return gfx::Insets(0, 0, IsFullscreen() ? 0 : 1, 0); +} + void WindowWin::RunSystemMenu(const gfx::Point& point) { // We need to reset and clean up any currently created system menu objects. // We need to call this otherwise there's a small chance that we aren't going @@ -702,20 +729,20 @@ LRESULT WindowWin::OnNCActivate(BOOL active) { } LRESULT WindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) { - // We only need to adjust the client size/paint handling when we're not using - // the native frame. - if (non_client_view_->UseNativeFrame()) + // We only override WM_NCCALCSIZE if we want non-standard non-client edge + // width. + gfx::Insets insets = GetClientAreaInsets(); + if (insets.empty()) return WidgetWin::OnNCCalcSize(mode, l_param); RECT* client_rect = mode ? &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] : reinterpret_cast<RECT*>(l_param); + client_rect->left += insets.left(); + client_rect->top += insets.top(); + client_rect->bottom -= insets.bottom(); + client_rect->right -= insets.right(); if (IsMaximized()) { - // Make the maximized mode client rect fit the screen exactly, by - // subtracting the border Windows automatically adds for maximized mode. - int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); - InflateRect(client_rect, -border_thickness, -border_thickness); - // Find all auto-hide taskbars along the screen edges and adjust in by the // thickness of the auto-hide taskbar on each such edge, so the window isn't // treated as a "fullscreen app", which would cause the taskbars to @@ -724,8 +751,22 @@ LRESULT WindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) { MONITOR_DEFAULTTONULL); if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor)) client_rect->left += win_util::kAutoHideTaskbarThicknessPx; - if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) - client_rect->top += win_util::kAutoHideTaskbarThicknessPx; + if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) { + if (GetNonClientView()->UseNativeFrame()) { + // Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of + // WM_NCHITTEST, having any nonclient area atop the window causes the + // caption buttons to draw onscreen but not respond to mouse + // hover/clicks. + // So for a taskbar at the screen top, we can't push the + // client_rect->top down; instead, we move the bottom up by one pixel, + // which is the smallest change we can make and still get a client area + // less than the screen size. This is visibly ugly, but there seems to + // be no better solution. + --client_rect->bottom; + } else { + client_rect->top += win_util::kAutoHideTaskbarThicknessPx; + } + } if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor)) client_rect->right -= win_util::kAutoHideTaskbarThicknessPx; if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor)) @@ -741,6 +782,11 @@ LRESULT WindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) { // Returning WVR_REDRAW avoids an extra paint before that of the old client // pixels in the (now wrong) location, and thus makes actions like resizing a // window from the left edge look slightly less broken. + // We special case when left or top insets are 0, since these conditions + // actually require another repaint to correct the layout after glass gets + // turned on and off. + if (insets.left() == 0 || insets.top() == 0) + return 0; return mode ? WVR_REDRAW : 0; } @@ -1125,6 +1171,20 @@ void WindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) { WidgetWin::OnWindowPosChanging(window_pos); } +gfx::Size WindowWin::GetRootViewSize() const { + // The native frame and maximized modes need to supply the client rect as + // determined by the relevant WM_NCCALCSIZE handling, so we just use the + // default handling which does this. + if (GetNonClientView()->UseNativeFrame() || IsMaximized()) + return WidgetWin::GetRootViewSize(); + + // When using an opaque frame, we consider the entire window rect to be client + // area visually. + CRect rect; + GetWindowRect(&rect); + return gfx::Size(rect.Width(), rect.Height()); +} + //////////////////////////////////////////////////////////////////////////////// // WindowWin, private: diff --git a/views/window/window_win.h b/views/window/window_win.h index 96bed16..19a92d4 100644 --- a/views/window/window_win.h +++ b/views/window/window_win.h @@ -102,6 +102,11 @@ class WindowWin : public WidgetWin, // Sizes the window to the default size specified by its ClientView. virtual void SizeWindowToDefault(); + // Returns the insets of the client area relative to the non-client area of + // the window. Override this function instead of OnNCCalcSize, which is + // crazily complicated. + virtual gfx::Insets GetClientAreaInsets() const; + // Shows the system menu at the specified screen point. void RunSystemMenu(const gfx::Point& point); @@ -119,7 +124,7 @@ class WindowWin : public WidgetWin, virtual void OnInitMenu(HMENU menu); virtual void OnMouseLeave(); virtual LRESULT OnNCActivate(BOOL active); - virtual LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param); + LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param); // Don't override. virtual LRESULT OnNCHitTest(const CPoint& point); virtual void OnNCPaint(HRGN rgn); virtual void OnNCLButtonDown(UINT ht_component, const CPoint& point); @@ -136,6 +141,7 @@ class WindowWin : public WidgetWin, virtual void OnWindowPosChanging(WINDOWPOS* window_pos); virtual Window* GetWindow() { return this; } virtual const Window* GetWindow() const { return this; } + virtual gfx::Size GetRootViewSize() const; // Accessor for disable_inactive_rendering_. bool disable_inactive_rendering() const { |