diff options
-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 { |