summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-15 19:21:57 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-15 19:21:57 +0000
commit9f36b348f2408118d42d219c8a4fa04877ed3b83 (patch)
treebc33b026905d139ad739b0c4345fc5cb97a2ed1c
parent6ef0feb87c69e28e81dd7ca0e45dc402f181619a (diff)
downloadchromium_src-9f36b348f2408118d42d219c8a4fa04877ed3b83.zip
chromium_src-9f36b348f2408118d42d219c8a4fa04877ed3b83.tar.gz
chromium_src-9f36b348f2408118d42d219c8a4fa04877ed3b83.tar.bz2
Fix a whole category of frame switching bugs relating to the window z-order being screwed up screwed up when DWM is toggled or themes are installed or reset.
The first part of the fix was to remove the hack I put in to hide then show the window while the frame type change occurs. The hack was to work around the fact that upon returning to glass from non-glass, the area identified by BrowserFrameWin::OnNCCalcSize as client was filled with solid black vs. transparent black. I don't know why this fix works, but returning a client size for the opaque frame as 1 pixel different to the window rect causes the blackness bug to not occur, so that's what I did (in addition to removing the hack). I also had to put in a couple of fixes to accommodate the pixel turd we gain in the opaque frame. I renamed ChangeSize to LayoutRootView. When we're using the opaque frame, since the views system is rendering the entire content of the window all the time I always size the widget to the window rect rather than the client rect. http://crbug.com/15424 TEST=change the frame type by: - turning on/off aero glass - installing a theme, then resetting - running an app that forces the DWM off, e.g. the O3D plugin The frame should appear correct after the transition in either direction, and window z-order should be preserved. Review URL: http://codereview.chromium.org/266013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29164 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/views/frame/browser_frame_win.cc43
-rw-r--r--chrome/browser/views/frame/browser_frame_win.h1
-rw-r--r--views/widget/widget_win.cc14
-rw-r--r--views/widget/widget_win.h12
-rw-r--r--views/window/window_win.cc22
5 files changed, 63 insertions, 29 deletions
diff --git a/chrome/browser/views/frame/browser_frame_win.cc b/chrome/browser/views/frame/browser_frame_win.cc
index 4315346..2616dfb 100644
--- a/chrome/browser/views/frame/browser_frame_win.cc
+++ b/chrome/browser/views/frame/browser_frame_win.cc
@@ -182,12 +182,17 @@ LRESULT BrowserFrameWin::OnNCActivate(BOOL active) {
}
LRESULT BrowserFrameWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
- // We don't adjust the client area unless we're a tabbed browser window and
- // are using the native frame.
- if (!GetNonClientView()->UseNativeFrame() ||
- !browser_view_->IsBrowserTypeNormal()) {
+ // 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] :
@@ -221,8 +226,22 @@ LRESULT BrowserFrameWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
--client_rect->bottom;
}
} else if (!browser_view_->IsFullscreen()) {
- // We draw our own client edge over part of the default frame would be.
- border_thickness = GetSystemMetrics(SM_CXSIZEFRAME) - kClientEdgeThickness;
+ 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;
@@ -301,6 +320,10 @@ ThemeProvider* BrowserFrameWin::GetDefaultThemeProvider() const {
return profile_->GetThemeProvider();
}
+bool BrowserFrameWin::SizeRootViewToWindowRect() const {
+ return !GetNonClientView()->UseNativeFrame();
+}
+
///////////////////////////////////////////////////////////////////////////////
// BrowserFrame, views::CustomFrameWindow overrides:
@@ -317,8 +340,10 @@ views::NonClientFrameView* BrowserFrameWin::CreateFrameViewForWindow() {
}
void BrowserFrameWin::UpdateFrameAfterFrameChange() {
- WindowWin::UpdateFrameAfterFrameChange();
+ // We need to update the glass region on or off before the base class adjusts
+ // the window region.
UpdateDWMFrame();
+ WindowWin::UpdateFrameAfterFrameChange();
}
views::RootView* BrowserFrameWin::CreateRootView() {
@@ -352,8 +377,6 @@ void BrowserFrameWin::UpdateDWMFrame() {
}
} else {
// For popup and app windows we want to use the default margins.
- margins.cxLeftWidth = margins.cxRightWidth = margins.cyTopHeight =
- margins.cyBottomHeight = 0;
}
DwmExtendFrameIntoClientArea(GetNativeView(), &margins);
}
diff --git a/chrome/browser/views/frame/browser_frame_win.h b/chrome/browser/views/frame/browser_frame_win.h
index dc23eb7..df59f36 100644
--- a/chrome/browser/views/frame/browser_frame_win.h
+++ b/chrome/browser/views/frame/browser_frame_win.h
@@ -64,6 +64,7 @@ class BrowserFrameWin : public BrowserFrame, public views::WindowWin {
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 a4f2181..3d9987c 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -342,9 +342,7 @@ void WidgetWin::SetUseLayeredBuffer(bool use_layered_buffer) {
if (use_layered_buffer_) {
// Force creation of the buffer at the right size.
- RECT wr;
- GetWindowRect(&wr);
- ChangeSize(0, CSize(wr.right - wr.left, wr.bottom - wr.top));
+ LayoutRootView();
} else {
contents_.reset(NULL);
}
@@ -808,7 +806,7 @@ void WidgetWin::OnSettingChange(UINT flags, const wchar_t* section) {
}
void WidgetWin::OnSize(UINT param, const CSize& size) {
- ChangeSize(param, size);
+ LayoutRootView();
}
void WidgetWin::OnSysCommand(UINT notification_code, CPoint click) {
@@ -951,15 +949,17 @@ void WidgetWin::ProcessMouseExited() {
active_mouse_tracking_flags_ = 0;
}
-void WidgetWin::ChangeSize(UINT size_param, const CSize& size) {
+void WidgetWin::LayoutRootView() {
CRect rect;
- if (use_layered_buffer_) {
+ if (SizeRootViewToWindowRect() || use_layered_buffer_) {
GetWindowRect(&rect);
- SizeContents(rect);
} else {
GetClientRect(&rect);
}
+ if (use_layered_buffer_)
+ SizeContents(rect);
+
// Resizing changes the size of the view hierarchy and thus forces a
// complete relayout.
root_view_->SetBounds(0, 0, rect.Width(), rect.Height());
diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h
index 40b3387..f8ba2a5 100644
--- a/views/widget/widget_win.h
+++ b/views/widget/widget_win.h
@@ -387,6 +387,13 @@ 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; }
+
// Start tracking all mouse events so that this window gets sent mouse leave
// messages too.
void TrackMouseEvents(DWORD mouse_tracking_flags);
@@ -403,8 +410,9 @@ class WidgetWin : public app::WindowImpl,
void ProcessMouseMoved(const CPoint& point, UINT flags, bool is_nonclient);
void ProcessMouseExited();
- // Handles re-laying out content in response to a window size change.
- virtual void ChangeSize(UINT size_param, const CSize& size);
+ // Lays out the root view to fit the appropriate area within the widget.
+ // Called when the window size or non client metrics change.
+ void LayoutRootView();
// Returns whether capture should be released on mouse release. The default
// is true.
diff --git a/views/window/window_win.cc b/views/window/window_win.cc
index 27ff3df..4daa279 100644
--- a/views/window/window_win.cc
+++ b/views/window/window_win.cc
@@ -190,14 +190,6 @@ static BOOL CALLBACK SendDwmCompositionChanged(HWND window, LPARAM param) {
} // namespace
void WindowWin::FrameTypeChanged() {
- WINDOWPLACEMENT wp = {0};
- GetWindowPlacement(GetNativeWindow(), &wp);
- Hide();
-
- // Update the non-client view with the correct frame view for the active frame
- // type.
- non_client_view_->UpdateFrame();
-
if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
// We need to toggle the rendering policy of the DWM/glass frame as we
// change from opaque to glass. "Non client rendering enabled" means that
@@ -217,11 +209,19 @@ void WindowWin::FrameTypeChanged() {
SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
SWP_NOOWNERZORDER | SWP_NOACTIVATE);
+ // The frame type change results in the client rect changing size, but this
+ // does not explicitly send a WM_SIZE, so we need to force the root view to
+ // be resized now.
+ LayoutRootView();
+
+ // Update the non-client view with the correct frame view for the active frame
+ // type.
+ non_client_view_->UpdateFrame();
+
// WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want
// to notify our children too, since we can have MDI child windows who need to
// update their appearance.
EnumChildWindows(GetNativeView(), &SendDwmCompositionChanged, NULL);
- SetWindowPlacement(GetNativeWindow(), &wp);
}
////////////////////////////////////////////////////////////////////////////////
@@ -789,6 +789,8 @@ static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) {
void WindowWin::OnNCPaint(HRGN rgn) {
// We only do non-client painting if we're not using the native frame.
+ // It's required to avoid some native painting artifacts from appearing when
+ // the window is resized.
if (non_client_view_->UseNativeFrame()) {
WidgetWin::OnNCPaint(rgn);
return;
@@ -1004,7 +1006,7 @@ void WindowWin::OnSize(UINT size_param, const CSize& new_size) {
// and maximized bounds are the same, then we need to layout (because we
// layout differently when maximized).
SaveWindowPosition();
- ChangeSize(size_param, new_size);
+ LayoutRootView();
RedrawWindow(GetNativeView(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
// ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've