From c42974c96b9dff2d42f5f8a49012e150ab73eb33 Mon Sep 17 00:00:00 2001 From: "sky@google.com" Date: Tue, 16 Dec 2008 17:52:08 +0000 Subject: Fixes info bubble painting bug. This was happening because we were using layered windows incorrectly. According to the docs if you invoke SetLayeredWindowAttributes, then you shouldn't invoke UpdateLayeredWindow (unless you remove then add the WS_EX_LAYERED style bit). My approach here is to disable the backing buffer for the info bubble. I had problems toggling the WS_EX_LAYERED at the end up the animation. The text field would not paint when I did this... BUG=5351 TEST=bookmark a page. When the bubble appears press shift-tab and make sure you see a focus rect around the remove link. Review URL: http://codereview.chromium.org/14131 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7063 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/views/info_bubble.cc | 17 +++++++++++------ chrome/views/widget_win.cc | 31 +++++++++++++++++++++++++------ chrome/views/widget_win.h | 18 ++++++++++++++++-- 3 files changed, 52 insertions(+), 14 deletions(-) (limited to 'chrome') diff --git a/chrome/browser/views/info_bubble.cc b/chrome/browser/views/info_bubble.cc index d034a1d..cef17bb 100644 --- a/chrome/browser/views/info_bubble.cc +++ b/chrome/browser/views/info_bubble.cc @@ -108,6 +108,9 @@ void InfoBubble::Init(HWND parent_hwnd, } set_window_style(WS_POPUP | WS_CLIPCHILDREN); set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); + // Because we're going to change the alpha value of the layered window we + // don't want to use the offscreen buffer provided by WidgetWin. + SetUseLayeredBuffer(false); content_view_ = CreateContentView(content); gfx::Rect bounds = content_view_-> CalculateWindowBounds(parent_hwnd, position_relative_to); @@ -122,11 +125,6 @@ void InfoBubble::Init(HWND parent_hwnd, gfx::Rect parented_bounds = content_view_-> CalculateWindowBounds(parent_hwnd, position_relative_to); - // Set our initial alpha to zero so we don't flicker at the user. This - // doesn't trigger UpdateLayeredWindow, which would explode our native - // controls. - SetLayeredAlpha(kMinimumAlpha); - if (bounds != parented_bounds) { SetWindowPos(NULL, parented_bounds.x(), parented_bounds.y(), parented_bounds.width(), parented_bounds.height(), @@ -142,6 +140,12 @@ void InfoBubble::Init(HWND parent_hwnd, false, false), this); + // Set initial alpha value of the layered window. + SetLayeredWindowAttributes(GetHWND(), + RGB(0xFF, 0xFF, 0xFF), + kMinimumAlpha, + LWA_ALPHA); + fade_animation_.reset(new SlideAnimation(this)); fade_animation_->Show(); } @@ -159,7 +163,8 @@ void InfoBubble::AnimationProgressed(const Animation* animation) { RGB(0xFF, 0xFF, 0xFF), alpha, LWA_ALPHA); - content_view_->SchedulePaint(); + // Don't need to invoke paint as SetLayeredWindowAttributes handles that for + // us. } bool InfoBubble::AcceleratorPressed(const views::Accelerator& accelerator) { diff --git a/chrome/views/widget_win.cc b/chrome/views/widget_win.cc index cd0e913..31f7a47 100644 --- a/chrome/views/widget_win.cc +++ b/chrome/views/widget_win.cc @@ -120,7 +120,7 @@ WidgetWin::WidgetWin() toplevel_(false), window_style_(0), window_ex_style_(kWindowDefaultExStyle), - layered_(false), + use_layered_buffer_(true), layered_alpha_(255), delete_on_destroy_(true), can_update_layered_window_(true), @@ -144,7 +144,8 @@ void WidgetWin::Init(HWND parent, const gfx::Rect& bounds, // See if the style has been overridden. opaque_ = !(window_ex_style_ & WS_EX_TRANSPARENT); - layered_ = !!(window_ex_style_ & WS_EX_LAYERED); + use_layered_buffer_ = (use_layered_buffer_ && + !!(window_ex_style_ & WS_EX_LAYERED)); // Force creation of the RootView if it hasn't been created yet. GetRootView(); @@ -246,7 +247,7 @@ HWND WidgetWin::GetHWND() const { } void WidgetWin::PaintNow(const gfx::Rect& update_rect) { - if (layered_) { + if (use_layered_buffer_) { PaintLayeredWindow(); } else if (root_view_->NeedsPainting(false) && IsWindow()) { if (!opaque_ && GetParent()) { @@ -302,6 +303,24 @@ void WidgetWin::SetLayeredAlpha(BYTE layered_alpha) { // UpdateWindowFromContents(contents_->getTopPlatformDevice().getBitmapDC()); } +void WidgetWin::SetUseLayeredBuffer(bool use_layered_buffer) { + if (use_layered_buffer_ == use_layered_buffer) + return; + + use_layered_buffer_ = use_layered_buffer; + if (!hwnd_) + return; + + 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)); + } else { + contents_.reset(NULL); + } +} + static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM l_param) { RootView* root_view = reinterpret_cast(GetProp(hwnd, kRootViewWindowProperty)); @@ -799,7 +818,7 @@ void WidgetWin::AdjustWindowToFitScreenSize() { void WidgetWin::ChangeSize(UINT size_param, const CSize& size) { CRect rect; - if (layered_) { + if (use_layered_buffer_) { GetWindowRect(&rect); SizeContents(rect); } else { @@ -812,7 +831,7 @@ void WidgetWin::ChangeSize(UINT size_param, const CSize& size) { root_view_->Layout(); root_view_->SchedulePaint(); - if (layered_) + if (use_layered_buffer_) PaintNow(gfx::Rect(rect)); } @@ -844,7 +863,7 @@ void WidgetWin::PaintLayeredWindow() { } void WidgetWin::UpdateWindowFromContents(HDC dib_dc) { - DCHECK(layered_); + DCHECK(use_layered_buffer_); if (can_update_layered_window_) { CRect wr; GetWindowRect(&wr); diff --git a/chrome/views/widget_win.h b/chrome/views/widget_win.h index 491d220..40c1f65 100644 --- a/chrome/views/widget_win.h +++ b/chrome/views/widget_win.h @@ -132,6 +132,9 @@ class WidgetWin : public Widget, // opacity if it is on the screen. void SetLayeredAlpha(BYTE layered_alpha); + // See description of use_layered_buffer_ for details. + void SetUseLayeredBuffer(bool use_layered_buffer); + // Disable Layered Window updates by setting to false. void set_can_update_layered_window(bool can_update_layered_window) { can_update_layered_window_ = can_update_layered_window; @@ -547,8 +550,19 @@ class WidgetWin : public Widget, // Style of the class to use. UINT class_style_; - // Whether or not this is a layered window. - bool layered_; + // Should we keep an offscreen buffer? This is initially true and if the + // window has WS_EX_LAYERED then it remains true. You can set this to false + // at any time to ditch the buffer, and similarly set back to true to force + // creation of the buffer. + // + // NOTE: this is intended to be used with a layered window (a window with an + // extended window style of WS_EX_LAYERED). If you are using a layered window + // and NOT changing the layered alpha or anything else, then leave this value + // alone. OTOH if you are invoking SetLayeredWindowAttributes then you'll + // must likely want to set this to false, or after changing the alpha toggle + // the extended style bit to false than back to true. See MSDN for more + // details. + bool use_layered_buffer_; // The default alpha to be applied to the layered window. BYTE layered_alpha_; -- cgit v1.1