diff options
author | beng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-25 22:11:49 +0000 |
---|---|---|
committer | beng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-25 22:11:49 +0000 |
commit | 65bd67d12cbbf73a0c7842750bd30639ddad2306 (patch) | |
tree | c498514b6a1a3d3e50b62498a09fd642cb9aa139 | |
parent | c62b56cde3acdd5d16896795739d7ce894c6e1a7 (diff) | |
download | chromium_src-65bd67d12cbbf73a0c7842750bd30639ddad2306.zip chromium_src-65bd67d12cbbf73a0c7842750bd30639ddad2306.tar.gz chromium_src-65bd67d12cbbf73a0c7842750bd30639ddad2306.tar.bz2 |
Make the AeroGlassFrame better:
- client edge rendering is now pixel-perfect for all BrowserTypes.
- fix NCCALCSIZE handling that was making our top-right corner less than perfectly round
- make system menu work
- remove some unnecessary functions
B=1031854
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1340 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/views/frame/aero_glass_frame.cc | 133 | ||||
-rw-r--r-- | chrome/browser/views/frame/aero_glass_frame.h | 9 | ||||
-rw-r--r-- | chrome/browser/views/frame/aero_glass_non_client_view.cc | 158 | ||||
-rw-r--r-- | chrome/browser/views/frame/aero_glass_non_client_view.h | 10 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view2.cc | 69 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view2.h | 10 | ||||
-rw-r--r-- | chrome/browser/views/frame/opaque_frame.cc | 19 | ||||
-rw-r--r-- | chrome/browser/views/frame/opaque_frame.h | 9 | ||||
-rw-r--r-- | chrome/browser/views/frame/opaque_non_client_view.cc | 11 | ||||
-rw-r--r-- | chrome/views/custom_frame_window.cc | 31 | ||||
-rw-r--r-- | chrome/views/custom_frame_window.h | 9 | ||||
-rw-r--r-- | chrome/views/hwnd_view_container.h | 2 | ||||
-rw-r--r-- | chrome/views/window.cc | 40 | ||||
-rw-r--r-- | chrome/views/window.h | 8 | ||||
-rw-r--r-- | chrome/views/window_delegate.h | 5 |
15 files changed, 307 insertions, 216 deletions
diff --git a/chrome/browser/views/frame/aero_glass_frame.cc b/chrome/browser/views/frame/aero_glass_frame.cc index 6a417b5..3278521 100644 --- a/chrome/browser/views/frame/aero_glass_frame.cc +++ b/chrome/browser/views/frame/aero_glass_frame.cc @@ -14,15 +14,15 @@ #include "chrome/views/window_delegate.h" // static -static const int kResizeBorder = 5; +// The width of the sizing borders. +static const int kResizeBorder = 8; // By how much the toolbar overlaps with the tab strip. -static const int kToolbarOverlapVertOffset = 3; - -// The DWM puts a light border around the client area - we need to -// take this border size into account when we reduce its size so that -// we don't draw our content border dropshadow images over the top. -static const int kDwmBorderSize = 1; +static const int kToolbarOverlapVertOffset = 5; +// This is the width of the default client edge provided by Windows. In some +// circumstances we provide our own client edge, so we use this width to +// remove it. +static const int kWindowsDWMBevelSize = 2; /////////////////////////////////////////////////////////////////////////////// // AeroGlassFrame, public: @@ -31,7 +31,7 @@ AeroGlassFrame::AeroGlassFrame(BrowserView2* browser_view) : Window(browser_view), browser_view_(browser_view), frame_initialized_(false) { - non_client_view_ = new AeroGlassNonClientView(this); + non_client_view_ = new AeroGlassNonClientView(this, browser_view); browser_view_->set_frame(this); } @@ -42,22 +42,6 @@ void AeroGlassFrame::Init(const gfx::Rect& bounds) { Window::Init(NULL, bounds); } -bool AeroGlassFrame::IsTabStripVisible() const { - return browser_view_->IsTabStripVisible(); -} - -bool AeroGlassFrame::IsToolbarVisible() const { - return browser_view_->IsToolbarVisible(); -} - -gfx::Rect AeroGlassFrame::GetToolbarBounds() const { - return browser_view_->GetToolbarBounds(); -} - -gfx::Rect AeroGlassFrame::GetContentsBounds() const { - return browser_view_->GetClientAreaBounds(); -} - int AeroGlassFrame::GetMinimizeButtonOffset() const { TITLEBARINFOEX titlebar_info; titlebar_info.cbSize = sizeof(TITLEBARINFOEX); @@ -74,7 +58,9 @@ int AeroGlassFrame::GetMinimizeButtonOffset() const { gfx::Rect AeroGlassFrame::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) { - return gfx::Rect(); + RECT rect = client_bounds.ToRECT(); + AdjustWindowRectEx(&rect, window_style(), FALSE, window_ex_style()); + return gfx::Rect(rect); } void AeroGlassFrame::SizeToContents(const gfx::Rect& contents_bounds) { @@ -100,6 +86,19 @@ void AeroGlassFrame::UpdateWindowIcon() { /////////////////////////////////////////////////////////////////////////////// // AeroGlassFrame, ChromeViews::HWNDViewContainer implementation: +void AeroGlassFrame::OnInitMenuPopup(HMENU menu, UINT position, + BOOL is_system_menu) { + browser_view_->PrepareToRunSystemMenu(menu); +} + +void AeroGlassFrame::OnEndSession(BOOL ending, UINT logoff) { + FrameUtil::EndSession(); +} + +void AeroGlassFrame::OnExitMenuLoop(bool is_track_popup_menu) { + browser_view_->SystemMenuEnded(); +} + LRESULT AeroGlassFrame::OnMouseActivate(HWND window, UINT hittest_code, UINT message) { return browser_view_->ActivateAppModalDialog() ? MA_NOACTIVATEANDEAT @@ -131,25 +130,36 @@ LRESULT AeroGlassFrame::OnNCActivate(BOOL active) { LRESULT AeroGlassFrame::OnNCCalcSize(BOOL mode, LPARAM l_param) { // By default the client side is set to the window size which is what // we want. - if (mode == TRUE) { - // Calculate new NCCALCSIZE_PARAMS based on custom NCA inset. - NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param); - - // Hack necessary to stop black background flicker, we cut out - // resizeborder here to save us from having to do too much - // addition and subtraction in Layout(). We don't cut off the - // top + titlebar as that prevents the window controls from - // highlighting. - pncsp->rgrc[0].left = pncsp->rgrc[0].left + kResizeBorder; - pncsp->rgrc[0].right = pncsp->rgrc[0].right - kResizeBorder; - pncsp->rgrc[0].bottom = pncsp->rgrc[0].bottom - kResizeBorder; + if (browser_view_->IsToolbarVisible() && mode == TRUE) { + // To be on the safe side and avoid side-effects, we only adjust the client + // size to non-standard values when we must - i.e. when we're showing a + // TabStrip. + if (browser_view_->IsTabStripVisible()) { + // Calculate new NCCALCSIZE_PARAMS based on custom NCA inset. + NCCALCSIZE_PARAMS* params = reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param); + + // Hack necessary to stop black background flicker, we cut out + // resizeborder here to save us from having to do too much + // addition and subtraction in Layout(). We don't cut off the + // top + titlebar as that prevents the window controls from + // highlighting. + params->rgrc[0].left += kResizeBorder; + params->rgrc[0].right -= kResizeBorder; + params->rgrc[0].bottom -= kResizeBorder; + + SetMsgHandled(TRUE); + } else { + // We don't adjust the client size for detached popups, so we need to + // tell Windows we didn't handle the message here so that it doesn't + // screw up the non-client area. + SetMsgHandled(FALSE); + } // We need to reset the frame, as Vista resets it whenever it changes // composition modes (and NCCALCSIZE is the closest thing we get to // a reliable message about the change). UpdateDWMFrame(); - SetMsgHandled(TRUE); return 0; } SetMsgHandled(FALSE); @@ -178,10 +188,6 @@ bool AeroGlassFrame::GetAccelerator(int cmd_id, return browser_view_->GetAccelerator(cmd_id, accelerator); } -void AeroGlassFrame::OnEndSession(BOOL ending, UINT logoff) { - FrameUtil::EndSession(); -} - /////////////////////////////////////////////////////////////////////////////// // AeroGlassFrame, private: @@ -190,26 +196,35 @@ void AeroGlassFrame::UpdateDWMFrame() { if (!client_view()) return; - // Note: we don't use DwmEnableBlurBehindWindow because any region not - // included in the glass region is composited source over. This means - // that anything drawn directly with GDI appears fully transparent. - // - // We want this region to extend past our content border images, as they - // may be partially-transparent. - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SkBitmap left_edge = *rb.GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER); - SkBitmap bottom_edge = *rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_CENTER); - SkBitmap right_edge = *rb.GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER); - // TODO(beng): when TabStrip is hooked up, obtain this offset from its // bounds. int toolbar_y = 36; - MARGINS margins = { kDwmBorderSize + left_edge.width(), - kDwmBorderSize + right_edge.width(), - kDwmBorderSize + client_view()->GetY() + - kToolbarOverlapVertOffset + toolbar_y, - kDwmBorderSize + bottom_edge.height() }; - DwmExtendFrameIntoClientArea(GetHWND(), &margins); + + // We only adjust the DWM's glass rendering when we're a browser window or a + // detached popup. App windows get the standard client edge. + if (browser_view_->IsTabStripVisible() || + browser_view_->IsToolbarVisible()) { + // By default, we just want to adjust the glass by the width of the inner + // bevel that aero renders to demarcate the client area. We supply our own + // client edge for the browser window and detached popups, so we don't want + // to show the default one. + int client_edge_left_width = kWindowsDWMBevelSize; + int client_edge_right_width = kWindowsDWMBevelSize; + int client_edge_bottom_height = kWindowsDWMBevelSize; + int client_edge_top_height = kWindowsDWMBevelSize; + if (browser_view_->IsTabStripVisible()) { + client_edge_top_height = + client_view()->GetY() + kToolbarOverlapVertOffset + toolbar_y; + } + + // Now poke the DWM. + MARGINS margins = { client_edge_left_width, client_edge_right_width, + client_edge_top_height, client_edge_bottom_height }; + // Note: we don't use DwmEnableBlurBehindWindow because any region not + // included in the glass region is composited source over. This means + // that anything drawn directly with GDI appears fully transparent. + DwmExtendFrameIntoClientArea(GetHWND(), &margins); + } } AeroGlassNonClientView* AeroGlassFrame::GetAeroGlassNonClientView() const { diff --git a/chrome/browser/views/frame/aero_glass_frame.h b/chrome/browser/views/frame/aero_glass_frame.h index 3edb452..ca109cc 100644 --- a/chrome/browser/views/frame/aero_glass_frame.h +++ b/chrome/browser/views/frame/aero_glass_frame.h @@ -26,13 +26,6 @@ class AeroGlassFrame : public BrowserFrame, void Init(const gfx::Rect& bounds); - bool IsToolbarVisible() const; - bool IsTabStripVisible() const; - - // Returns bounds of various areas within the BrowserView ClientView. - gfx::Rect GetToolbarBounds() const; - gfx::Rect GetContentsBounds() const; - // Determine the distance of the left edge of the minimize button from the // right edge of the window. Used in our Non-Client View's Layout. int GetMinimizeButtonOffset() const; @@ -54,7 +47,9 @@ class AeroGlassFrame : public BrowserFrame, protected: // Overridden from ChromeViews::HWNDViewContainer: + virtual void OnInitMenuPopup(HMENU menu, UINT position, BOOL is_system_menu); virtual void OnEndSession(BOOL ending, UINT logoff); + virtual void OnExitMenuLoop(bool is_track_popup_menu); virtual LRESULT OnMouseActivate(HWND window, UINT hittest_code, UINT message); diff --git a/chrome/browser/views/frame/aero_glass_non_client_view.cc b/chrome/browser/views/frame/aero_glass_non_client_view.cc index 5c40fac..a13f6ed 100644 --- a/chrome/browser/views/frame/aero_glass_non_client_view.cc +++ b/chrome/browser/views/frame/aero_glass_non_client_view.cc @@ -6,6 +6,7 @@ #include "chrome/app/theme/theme_resources.h" #include "chrome/browser/tabs/tab_strip.h" +#include "chrome/browser/views/frame/browser_view2.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/gfx/chrome_font.h" #include "chrome/common/gfx/path.h" @@ -33,18 +34,11 @@ enum FramePartBitmap { FRAME_PART_BITMAP_COUNT // Must be last. }; -class WindowResources { - public: - virtual SkBitmap* GetPartBitmap(FramePartBitmap part) const = 0; - virtual const ChromeFont& GetTitleFont() const = 0; -}; - -class AeroGlassWindowResources : public WindowResources { +class AeroGlassWindowResources { public: AeroGlassWindowResources() { InitClass(); } virtual ~AeroGlassWindowResources() { } - // WindowResources implementation: virtual SkBitmap* GetPartBitmap(FramePartBitmap part) const { return standard_frame_bitmaps_[part]; } @@ -52,6 +46,10 @@ class AeroGlassWindowResources : public WindowResources { return title_font_; } + SkBitmap app_top_left() const { return app_top_left_; } + SkBitmap app_top_center() const { return app_top_center_; } + SkBitmap app_top_right() const { return app_top_right_; } + private: static void InitClass() { static bool initialized = false; @@ -73,12 +71,20 @@ class AeroGlassWindowResources : public WindowResources { } title_font_ = rb.GetFont(ResourceBundle::BaseFont).DeriveFont(1, ChromeFont::BOLD); + + app_top_left_ = *rb.GetBitmapNamed(IDR_APP_TOP_LEFT); + app_top_center_ = *rb.GetBitmapNamed(IDR_APP_TOP_CENTER); + app_top_right_ = *rb.GetBitmapNamed(IDR_APP_TOP_RIGHT); + initialized = true; } } static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; static ChromeFont title_font_; + static SkBitmap app_top_left_; + static SkBitmap app_top_center_; + static SkBitmap app_top_right_; DISALLOW_EVIL_CONSTRUCTORS(AeroGlassWindowResources); }; @@ -86,24 +92,42 @@ class AeroGlassWindowResources : public WindowResources { // static SkBitmap* AeroGlassWindowResources::standard_frame_bitmaps_[]; ChromeFont AeroGlassWindowResources::title_font_; +SkBitmap AeroGlassWindowResources::app_top_left_; +SkBitmap AeroGlassWindowResources::app_top_center_; +SkBitmap AeroGlassWindowResources::app_top_right_; -WindowResources* AeroGlassNonClientView::resources_ = NULL; +AeroGlassWindowResources* AeroGlassNonClientView::resources_ = NULL; SkBitmap AeroGlassNonClientView::distributor_logo_; -static const int kTitleTopOffset = 6; -static const int kTitleBottomSpacing = 6; +// The distance between the top of the TabStrip and the top of the non-client +// area of the window. static const int kNoTitleTopSpacing = 8; +// TODO(beng): figure out what this is for. static const int kWindowHorizontalBorderSize = 2; +// TODO(beng): figure out what this is for. static const int kWindowVerticalBorderSize = 2; +// The horizontal distance between the left of the minimize button and the +// right edge of the distributor logo. static const int kDistributorLogoHorizontalOffset = 7; +// The distance from the top of the non-client view and the top edge of the +// distributor logo. static const int kDistributorLogoVerticalOffset = 3; +// TODO(beng): figure out what this is for. static const int kTitlebarHeight = 14; +// A single pixel. +static const int kPixel = 1; +// The height of the sizing border. +static const int kWindowSizingBorderSize = 8; +// The size (width/height) of the window icon. +static const int kWindowIconSize = 16; /////////////////////////////////////////////////////////////////////////////// // AeroGlassNonClientView, public: -AeroGlassNonClientView::AeroGlassNonClientView(AeroGlassFrame* frame) - : frame_(frame) { +AeroGlassNonClientView::AeroGlassNonClientView(AeroGlassFrame* frame, + BrowserView2* browser_view) + : frame_(frame), + browser_view_(browser_view) { InitClass(); } @@ -132,6 +156,11 @@ gfx::Rect AeroGlassNonClientView::GetBoundsForTabStrip(TabStrip* tabstrip) { gfx::Rect AeroGlassNonClientView::CalculateClientAreaBounds(int width, int height) const { + if (!browser_view_->IsToolbarVisible()) { + // App windows don't have a toolbar. + return gfx::Rect(0, 0, GetWidth(), GetHeight()); + } + int top_margin = CalculateNonClientTopHeight(); return gfx::Rect(kWindowHorizontalBorderSize, top_margin, std::max(0, width - (2 * kWindowHorizontalBorderSize)), @@ -147,19 +176,39 @@ gfx::Size AeroGlassNonClientView::CalculateWindowSizeForClientSize( } CPoint AeroGlassNonClientView::GetSystemMenuPoint() const { - return CPoint(); + CPoint offset(0, 0); + MapWindowPoints(GetViewContainer()->GetHWND(), HWND_DESKTOP, &offset, 1); + return offset; } int AeroGlassNonClientView::NonClientHitTest(const gfx::Point& point) { CRect bounds; CPoint test_point = point.ToPOINT(); - // First see if it's within the grow box area, since that overlaps the client - // bounds. + // See if the client view intersects the non-client area (e.g. blank areas + // of the TabStrip). int component = frame_->client_view()->NonClientHitTest(point); if (component != HTNOWHERE) return component; + // This check is only done when we have a toolbar, which is the only time + // that we have a non-standard non-client area. + if (browser_view_->IsToolbarVisible()) { + // Because we tell Windows that our client area extends all the way to the + // top of the browser window, but our BrowserView doesn't actually go up that + // high, we need to make sure the right hit-test codes are returned for the + // caption area above the tabs and the top sizing border. + int client_view_right = + frame_->client_view()->GetX() + frame_->client_view()->GetWidth(); + if (point.x() >= frame_->client_view()->GetX() || + point.x() < client_view_right) { + if (point.y() < kWindowSizingBorderSize) + return HTTOP; + return HTCAPTION; + } + } + + // Let Windows figure it out. return HTNOWHERE; } @@ -175,11 +224,13 @@ void AeroGlassNonClientView::EnableClose(bool enable) { void AeroGlassNonClientView::Paint(ChromeCanvas* canvas) { PaintDistributorLogo(canvas); - PaintToolbarBackground(canvas); - PaintClientEdge(canvas); + if (browser_view_->IsToolbarVisible()) { + PaintToolbarBackground(canvas); + PaintClientEdge(canvas); + } // TODO(beng): remove this - gfx::Rect contents_bounds = frame_->GetContentsBounds(); + gfx::Rect contents_bounds = browser_view_->GetClientAreaBounds(); canvas->FillRectInt(SK_ColorGRAY, contents_bounds.x(), contents_bounds.y(), contents_bounds.width(), contents_bounds.height()); } @@ -215,10 +266,8 @@ void AeroGlassNonClientView::ViewHierarchyChanged(bool is_add, // AeroGlassNonClientView, private: int AeroGlassNonClientView::CalculateNonClientTopHeight() const { - if (frame_->window_delegate()->ShouldShowWindowTitle()) { - return kTitleTopOffset + resources_->GetTitleFont().height() + - kTitleBottomSpacing; - } + if (frame_->window_delegate()->ShouldShowWindowTitle()) + return browser_view_->IsToolbarVisible() ? 2 : 0; return kNoTitleTopSpacing; } @@ -233,7 +282,8 @@ void AeroGlassNonClientView::PaintDistributorLogo(ChromeCanvas* canvas) { } void AeroGlassNonClientView::PaintToolbarBackground(ChromeCanvas* canvas) { - if (frame_->IsToolbarVisible() || frame_->IsTabStripVisible()) { + if (browser_view_->IsToolbarVisible() || + browser_view_->IsTabStripVisible()) { SkBitmap* toolbar_left = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); SkBitmap* toolbar_center = @@ -241,20 +291,33 @@ void AeroGlassNonClientView::PaintToolbarBackground(ChromeCanvas* canvas) { SkBitmap* toolbar_right = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); - gfx::Rect toolbar_bounds = frame_->GetToolbarBounds(); + gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); gfx::Point topleft(toolbar_bounds.x(), toolbar_bounds.y()); View::ConvertPointToView(frame_->client_view(), this, &topleft); toolbar_bounds.set_x(topleft.x()); toolbar_bounds.set_y(topleft.y()); - canvas->DrawBitmapInt(*toolbar_left, - toolbar_bounds.x() - toolbar_left->width(), - toolbar_bounds.y()); + // We use TileImageInt for the left and right caps to clip the rendering + // to the appropriate height of the toolbar. + canvas->TileImageInt(*toolbar_left, + toolbar_bounds.x() - toolbar_left->width(), + toolbar_bounds.y(), toolbar_left->width(), + toolbar_bounds.height()); canvas->TileImageInt(*toolbar_center, toolbar_bounds.x(), toolbar_bounds.y(), toolbar_bounds.width(), toolbar_center->height()); - canvas->DrawBitmapInt(*toolbar_right, toolbar_bounds.right(), - toolbar_bounds.y()); + canvas->TileImageInt(*toolbar_right, toolbar_bounds.right(), + toolbar_bounds.y(), toolbar_right->width(), + toolbar_bounds.height()); + + if (frame_->window_delegate()->ShouldShowWindowTitle()) { + // Since we're showing the toolbar or the tabstrip, we need to draw a + // single pixel grey line along underneath them to terminate them + // cleanly. + canvas->FillRectInt(SkColorSetRGB(180, 188, 199), toolbar_bounds.x(), + toolbar_bounds.bottom() - 1, toolbar_bounds.width(), + 1); + } } } @@ -270,29 +333,40 @@ void AeroGlassNonClientView::PaintClientEdge(ChromeCanvas* canvas) { // The toolbar renders its own client edge in PaintToolbarBackground, however // there are other bands that need to have a client edge rendered along their // sides, such as the Bookmark bar, infobars, etc. - gfx::Rect toolbar_bounds = frame_->GetToolbarBounds(); - gfx::Rect client_area_bounds = frame_->GetContentsBounds(); + gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); + gfx::Rect client_area_bounds = browser_view_->GetClientAreaBounds(); + // For some reason things don't line up quite right, so we add and subtract + // pixels here and there for aesthetic bliss. + // Enlarge the client area to include the toolbar, since the top edge of + // the client area is the toolbar background and the client edge renders + // the left and right sides of the toolbar background. client_area_bounds.SetRect( client_area_bounds.x(), - frame_->client_view()->GetY() + toolbar_bounds.bottom() - 1, + frame_->client_view()->GetY() + toolbar_bounds.bottom() - kPixel, client_area_bounds.width(), std::max(0, GetHeight() - frame_->client_view()->GetY() - - toolbar_bounds.bottom() + 1 - kWindowVerticalBorderSize)); + toolbar_bounds.bottom() + kPixel)); + int fudge = frame_->window_delegate()->ShouldShowWindowTitle() ? kPixel : 0; canvas->TileImageInt(*right, client_area_bounds.right(), - client_area_bounds.y(), - right->width(), client_area_bounds.height()); + client_area_bounds.y() + fudge, right->width(), + client_area_bounds.height() - bottom_right->height() + + kPixel - fudge); canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(), - client_area_bounds.bottom()); + client_area_bounds.bottom() - bottom_right->height() + + kPixel); canvas->TileImageInt(*bottom, client_area_bounds.x(), - client_area_bounds.bottom(), - client_area_bounds.width(), bottom_right->height()); + client_area_bounds.bottom() - bottom_right->height() + + kPixel, client_area_bounds.width(), + bottom_right->height()); canvas->DrawBitmapInt(*bottom_left, client_area_bounds.x() - bottom_left->width(), - client_area_bounds.bottom()); + client_area_bounds.bottom() - bottom_left->height() + + kPixel); canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), - client_area_bounds.y(), - left->width(), client_area_bounds.height()); + client_area_bounds.y() + fudge, left->width(), + client_area_bounds.height() - bottom_left->height() + + kPixel - fudge); } void AeroGlassNonClientView::LayoutDistributorLogo() { diff --git a/chrome/browser/views/frame/aero_glass_non_client_view.h b/chrome/browser/views/frame/aero_glass_non_client_view.h index 9d813af60..cb39fae 100644 --- a/chrome/browser/views/frame/aero_glass_non_client_view.h +++ b/chrome/browser/views/frame/aero_glass_non_client_view.h @@ -9,12 +9,13 @@ #include "chrome/views/non_client_view.h" #include "chrome/views/button.h" -class WindowResources; +class BrowserView2; +class AeroGlassWindowResources; class AeroGlassNonClientView : public ChromeViews::NonClientView { public: // Constructs a non-client view for an AeroGlassFrame. - explicit AeroGlassNonClientView(AeroGlassFrame* frame); + AeroGlassNonClientView(AeroGlassFrame* frame, BrowserView2* browser_view); virtual ~AeroGlassNonClientView(); gfx::Rect GetBoundsForTabStrip(TabStrip* tabstrip); @@ -58,9 +59,12 @@ class AeroGlassNonClientView : public ChromeViews::NonClientView { // The frame that hosts this view. AeroGlassFrame* frame_; + // The BrowserView2 that we contain. + BrowserView2* browser_view_; + static void InitClass(); static SkBitmap distributor_logo_; - static WindowResources* resources_; + static AeroGlassWindowResources* resources_; DISALLOW_EVIL_CONSTRUCTORS(AeroGlassNonClientView); }; diff --git a/chrome/browser/views/frame/browser_view2.cc b/chrome/browser/views/frame/browser_view2.cc index 3d4d1ed..85e1ae4 100644 --- a/chrome/browser/views/frame/browser_view2.cc +++ b/chrome/browser/views/frame/browser_view2.cc @@ -22,6 +22,7 @@ #include "chrome/common/os_exchange_data.h" #include "chrome/common/pref_names.h" #include "chrome/common/resource_bundle.h" +#include "chrome/common/win_util.h" #include "chrome/views/view.h" #include "chrome/views/window.h" #include "generated_resources.h" @@ -207,9 +208,9 @@ SkBitmap BrowserView2::GetOTRAvatarIcon() { return otr_avatar_; } -void BrowserView2::PrepareToRunSystemMenu(Menu* menu) { - int insertion_index = std::max(0, menu->ItemCount() - 1); - system_menu_.reset(menu); +void BrowserView2::PrepareToRunSystemMenu(HMENU menu) { + system_menu_.reset(new Menu(menu)); + int insertion_index = std::max(0, system_menu_->ItemCount() - 1); // We add the menu items in reverse order so that insertion_index never needs // to change. if (browser_->GetType() == BrowserType::TABBED_BROWSER) { @@ -528,11 +529,13 @@ bool BrowserView2::ShouldShowWindowIcon() const { return SupportsWindowFeature(FEATURE_TITLEBAR); } -void BrowserView2::ExecuteWindowsCommand(int command_id) { - if (browser_->SupportsCommand(command_id) && - browser_->IsCommandEnabled(command_id)) { - browser_->ExecuteCommand(command_id); +bool BrowserView2::ExecuteWindowsCommand(int command_id) { + if (browser_->SupportsCommand(command_id)) { + if (browser_->IsCommandEnabled(command_id)) + browser_->ExecuteCommand(command_id); + return true; } + return false; } void BrowserView2::SaveWindowPosition(const CRect& bounds, @@ -641,26 +644,38 @@ bool BrowserView2::CanClose() const { } int BrowserView2::NonClientHitTest(const gfx::Point& point) { - // First learn about the kind of frame we dwell within... - WINDOWINFO wi; - wi.cbSize = sizeof(wi); - GetWindowInfo(frame_->GetWindow()->GetHWND(), &wi); - - CPoint point_in_view_coords(point.ToPOINT()); - View::ConvertPointToView(GetParent(), this, &point_in_view_coords); - if (IsTabStripVisible() && tabstrip_->HitTest(point_in_view_coords) && - tabstrip_->CanProcessInputEvents()) { + // Since the TabStrip only renders in some parts of the top of the window, + // the un-obscured area is considered to be part of the non-client caption + // area of the window. So we need to treat hit-tests in these regions as + // hit-tests of the titlebar. + + // Determine if the TabStrip exists and is capable of being clicked on. We + // might be a popup window without a TabStrip, or the TabStrip could be + // animating. + if (IsTabStripVisible() && tabstrip_->CanProcessInputEvents()) { ChromeViews::Window* window = frame_->GetWindow(); + CPoint point_in_view_coords(point.ToPOINT()); + View::ConvertPointToView(GetParent(), this, &point_in_view_coords); + + // See if the mouse pointer is within the bounds of the TabStrip. + CPoint point_in_tabstrip_coords(point.ToPOINT()); + View::ConvertPointToView(GetParent(), tabstrip_, &point_in_tabstrip_coords); + if (tabstrip_->HitTest(point_in_tabstrip_coords)) { + if (tabstrip_->PointIsWithinWindowCaption(point_in_view_coords)) + return HTCAPTION; + return HTCLIENT; + } + // The top few pixels of the TabStrip are a drop-shadow - as we're pretty // starved of dragable area, let's give it to window dragging (this also // makes sense visually). - if (!window->IsMaximized() && point_in_view_coords.y < kTabShadowSize) - return HTCAPTION; - - if (tabstrip_->PointIsWithinWindowCaption(point_in_view_coords)) - return HTCAPTION; - - return HTCLIENT; + if (!window->IsMaximized() && + (point_in_view_coords.y < tabstrip_->GetY() + kTabShadowSize)) { + // We return HTNOWHERE as this is a signal to our containing + // NonClientView that it should figure out what the correct hit-test + // code is given the mouse position... + return HTNOWHERE; + } } // If the point's y coordinate is below the top of the toolbar and otherwise @@ -679,10 +694,6 @@ int BrowserView2::NonClientHitTest(const gfx::Point& point) { /////////////////////////////////////////////////////////////////////////////// // BrowserView2, ChromeViews::View overrides: -void BrowserView2::Paint(ChromeCanvas* canvas) { - //canvas->FillRectInt(SK_ColorRED, 0, 0, GetWidth(), GetHeight()); -} - void BrowserView2::Layout() { int top = LayoutTabStrip(); top = LayoutToolbar(top); @@ -809,6 +820,10 @@ int BrowserView2::LayoutToolbar(int top) { CSize ps; toolbar_->GetPreferredSize(&ps); int toolbar_y = top - kToolbarTabStripVerticalOverlap; + // With detached popup windows with the aero glass frame, we need to offset + // by a pixel to make things look good. + if (!IsTabStripVisible() && win_util::ShouldUseVistaFrame()) + ps.cy -= 1; toolbar_->SetBounds(0, toolbar_y, GetWidth(), ps.cy); return toolbar_y + ps.cy; } diff --git a/chrome/browser/views/frame/browser_view2.h b/chrome/browser/views/frame/browser_view2.h index 28ece6f..07ee529 100644 --- a/chrome/browser/views/frame/browser_view2.h +++ b/chrome/browser/views/frame/browser_view2.h @@ -104,10 +104,9 @@ class BrowserView2 : public BrowserWindow, // Retrieves the icon to use in the frame to indicate an OTR window. SkBitmap GetOTRAvatarIcon(); - // Called right before displaying the system menu to allow the - // BrowserView to add or delete entries. BrowserView takes ownership - // of the passed in Menu object. - void PrepareToRunSystemMenu(Menu* menu); + // Called right before displaying the system menu to allow the BrowserView2 + // to add or delete entries. + void PrepareToRunSystemMenu(HMENU menu); // Called after the system menu has ended, and disposes of the // current System menu object. @@ -185,7 +184,7 @@ class BrowserView2 : public BrowserWindow, virtual bool ShouldShowWindowTitle() const; virtual SkBitmap GetWindowIcon(); virtual bool ShouldShowWindowIcon() const; - virtual void ExecuteWindowsCommand(int command_id); + virtual bool ExecuteWindowsCommand(int command_id); virtual void SaveWindowPosition(const CRect& bounds, bool maximized, bool always_on_top); @@ -203,7 +202,6 @@ class BrowserView2 : public BrowserWindow, protected: // Overridden from ChromeViews::View: - virtual void Paint(ChromeCanvas* canvas); virtual void Layout(); virtual void DidChangeBounds(const CRect& previous, const CRect& current); virtual void ViewHierarchyChanged(bool is_add, diff --git a/chrome/browser/views/frame/opaque_frame.cc b/chrome/browser/views/frame/opaque_frame.cc index 2e47c18..e9d840b 100644 --- a/chrome/browser/views/frame/opaque_frame.cc +++ b/chrome/browser/views/frame/opaque_frame.cc @@ -23,22 +23,6 @@ OpaqueFrame::OpaqueFrame(BrowserView2* browser_view) OpaqueFrame::~OpaqueFrame() { } -bool OpaqueFrame::IsTabStripVisible() const { - return browser_view_->IsTabStripVisible(); -} - -bool OpaqueFrame::IsToolbarVisible() const { - return browser_view_->IsToolbarVisible(); -} - -gfx::Rect OpaqueFrame::GetToolbarBounds() const { - return browser_view_->GetToolbarBounds(); -} - -gfx::Rect OpaqueFrame::GetContentsBounds() const { - return browser_view_->GetClientAreaBounds(); -} - /////////////////////////////////////////////////////////////////////////////// // OpaqueFrame, BrowserFrame implementation: @@ -92,8 +76,7 @@ void OpaqueFrame::OnExitMenuLoop(bool is_track_popup_menu) { void OpaqueFrame::OnInitMenuPopup(HMENU menu, UINT position, BOOL is_system_menu) { - Menu* menu_obj = new Menu(menu); - browser_view_->PrepareToRunSystemMenu(menu_obj); + browser_view_->PrepareToRunSystemMenu(menu); } LRESULT OpaqueFrame::OnMouseActivate(HWND window, UINT hittest_code, diff --git a/chrome/browser/views/frame/opaque_frame.h b/chrome/browser/views/frame/opaque_frame.h index ddd6436..5bc1718 100644 --- a/chrome/browser/views/frame/opaque_frame.h +++ b/chrome/browser/views/frame/opaque_frame.h @@ -29,13 +29,6 @@ class OpaqueFrame : public BrowserFrame, explicit OpaqueFrame(BrowserView2* browser_view); virtual ~OpaqueFrame(); - bool IsToolbarVisible() const; - bool IsTabStripVisible() const; - - // Returns bounds of various areas within the BrowserView ClientView. - gfx::Rect GetToolbarBounds() const; - gfx::Rect GetContentsBounds() const; - protected: // Overridden from BrowserFrame: virtual gfx::Rect GetWindowBoundsForClientBounds( @@ -51,8 +44,8 @@ class OpaqueFrame : public BrowserFrame, virtual bool AcceleratorPressed(ChromeViews::Accelerator* accelerator); virtual bool GetAccelerator(int cmd_id, ChromeViews::Accelerator* accelerator); - virtual void OnExitMenuLoop(bool is_track_popup_menu); virtual void OnEndSession(BOOL ending, UINT logoff); + virtual void OnExitMenuLoop(bool is_track_popup_menu); virtual void OnInitMenuPopup(HMENU menu, UINT position, BOOL is_system_menu); virtual LRESULT OnMouseActivate(HWND window, UINT hittest_code, diff --git a/chrome/browser/views/frame/opaque_non_client_view.cc b/chrome/browser/views/frame/opaque_non_client_view.cc index 79d78ed..86691d2 100644 --- a/chrome/browser/views/frame/opaque_non_client_view.cc +++ b/chrome/browser/views/frame/opaque_non_client_view.cc @@ -635,7 +635,7 @@ void OpaqueNonClientView::EnableClose(bool enable) { void OpaqueNonClientView::Paint(ChromeCanvas* canvas) { // Clip the content area out of the rendering. - gfx::Rect contents_bounds = frame_->GetContentsBounds(); + gfx::Rect contents_bounds = browser_view_->GetClientAreaBounds(); SkRect clip; clip.set(SkIntToScalar(contents_bounds.x()), SkIntToScalar(contents_bounds.y()), @@ -809,7 +809,8 @@ void OpaqueNonClientView::PaintTitleBar(ChromeCanvas* canvas) { } void OpaqueNonClientView::PaintToolbarBackground(ChromeCanvas* canvas) { - if (frame_->IsToolbarVisible() || frame_->IsTabStripVisible()) { + if (browser_view_->IsToolbarVisible() || + browser_view_->IsTabStripVisible()) { SkBitmap* toolbar_left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); SkBitmap* toolbar_center = @@ -817,7 +818,7 @@ void OpaqueNonClientView::PaintToolbarBackground(ChromeCanvas* canvas) { SkBitmap* toolbar_right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); - gfx::Rect toolbar_bounds = frame_->GetToolbarBounds(); + gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); gfx::Point topleft(toolbar_bounds.x(), toolbar_bounds.y()); View::ConvertPointToView(frame_->client_view(), this, &topleft); toolbar_bounds.set_x(topleft.x()); @@ -846,8 +847,8 @@ void OpaqueNonClientView::PaintClientEdge(ChromeCanvas* canvas) { // The toolbar renders its own client edge in PaintToolbarBackground, however // there are other bands that need to have a client edge rendered along their // sides, such as the Bookmark bar, infobars, etc. - gfx::Rect toolbar_bounds = frame_->GetToolbarBounds(); - gfx::Rect client_area_bounds = frame_->GetContentsBounds(); + gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); + gfx::Rect client_area_bounds = browser_view_->GetClientAreaBounds(); // For some reason things don't line up quite right, so we add and subtract // pixels here and there for aesthetic bliss. // Enlarge the client area to include the toolbar, since the top edge of diff --git a/chrome/views/custom_frame_window.cc b/chrome/views/custom_frame_window.cc index 24e6200..1842953 100644 --- a/chrome/views/custom_frame_window.cc +++ b/chrome/views/custom_frame_window.cc @@ -826,11 +826,6 @@ CustomFrameWindow::CustomFrameWindow(WindowDelegate* window_delegate, CustomFrameWindow::~CustomFrameWindow() { } -void CustomFrameWindow::ExecuteSystemMenuCommand(int command) { - if (command) - SendMessage(GetHWND(), WM_SYSCOMMAND, command, 0); -} - /////////////////////////////////////////////////////////////////////////////// // CustomFrameWindow, Window overrides: @@ -1083,14 +1078,6 @@ void CustomFrameWindow::OnNCPaint(HRGN rgn) { ReleaseDC(GetHWND(), dc); } -void CustomFrameWindow::OnNCRButtonDown(UINT flags, const CPoint& point) { - if (flags == HTCAPTION || flags == HTSYSMENU) { - RunSystemMenu(point); - } else { - SetMsgHandled(FALSE); - } -} - void CustomFrameWindow::OnNCLButtonDown(UINT ht_component, const CPoint& point) { switch (ht_component) { @@ -1121,11 +1108,10 @@ void CustomFrameWindow::OnNCLButtonDown(UINT ht_component, SetMsgHandled(TRUE); return; } - case HTSYSMENU: - RunSystemMenu(non_client_view_->GetSystemMenuPoint()); + default: + Window::OnNCLButtonDown(ht_component, point); break; } - SetMsgHandled(FALSE); } LRESULT CustomFrameWindow::OnSetCursor(HWND window, UINT hittest_code, @@ -1168,19 +1154,6 @@ void CustomFrameWindow::OnSize(UINT param, const CSize& size) { /////////////////////////////////////////////////////////////////////////////// // CustomFrameWindow, private: -void CustomFrameWindow::RunSystemMenu(const CPoint& 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 - // to get a system menu. We also can't take the return value of this - // function. We need to call it *again* to get a valid HMENU. - ::GetSystemMenu(GetHWND(), TRUE); - HMENU system_menu = ::GetSystemMenu(GetHWND(), FALSE); - int id = ::TrackPopupMenu(system_menu, - TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, - point.x, point.y, 0, GetHWND(), NULL); - ExecuteSystemMenuCommand(id); -} - // static void CustomFrameWindow::InitClass() { static bool initialized = false; diff --git a/chrome/views/custom_frame_window.h b/chrome/views/custom_frame_window.h index e6356e9..d014c91 100644 --- a/chrome/views/custom_frame_window.h +++ b/chrome/views/custom_frame_window.h @@ -30,9 +30,6 @@ class CustomFrameWindow : public Window { NonClientView* non_client_view); virtual ~CustomFrameWindow(); - // Executes the specified SC_command. - void ExecuteSystemMenuCommand(int command); - // Returns whether or not the frame is active. bool is_active() const { return is_active_; } @@ -58,15 +55,11 @@ class CustomFrameWindow : public Window { virtual LRESULT OnNCHitTest(const CPoint& point); virtual LRESULT OnNCMouseMove(UINT flags, const CPoint& point); virtual void OnNCPaint(HRGN rgn); - virtual void OnNCRButtonDown(UINT flags, const CPoint& point); - virtual void OnNCLButtonDown(UINT flags, const CPoint& point); + virtual void OnNCLButtonDown(UINT ht_component, const CPoint& point); virtual LRESULT OnSetCursor(HWND window, UINT hittest_code, UINT message); virtual void OnSize(UINT param, const CSize& size); private: - // Shows the system menu at the specified screen point. - void RunSystemMenu(const CPoint& point); - // Resets the window region. void ResetWindowRegion(); diff --git a/chrome/views/hwnd_view_container.h b/chrome/views/hwnd_view_container.h index c281a66..6073b2d 100644 --- a/chrome/views/hwnd_view_container.h +++ b/chrome/views/hwnd_view_container.h @@ -328,7 +328,7 @@ class HWNDViewContainer : public ViewContainer, virtual void OnCaptureChanged(HWND hwnd); virtual void OnClose(); virtual void OnCommand( - UINT notification_code, int command_id, HWND window) { } + UINT notification_code, int command_id, HWND window) { SetMsgHandled(FALSE); } virtual LRESULT OnCreate(LPCREATESTRUCT create_struct) { return 0; } // WARNING: If you override this be sure and invoke super, otherwise we'll // leak a few things. diff --git a/chrome/views/window.cc b/chrome/views/window.cc index db6174c..6d8327f 100644 --- a/chrome/views/window.cc +++ b/chrome/views/window.cc @@ -172,6 +172,11 @@ void Window::UpdateWindowIcon() { } } +void Window::ExecuteSystemMenuCommand(int command) { + if (command) + SendMessage(GetHWND(), WM_SYSCOMMAND, command, 0); +} + // static bool Window::SaveWindowPositionToPrefService(PrefService* pref_service, const std::wstring& entry, @@ -321,6 +326,19 @@ void Window::SizeWindowToDefault() { win_util::CenterAndSizeWindow(owning_window(), GetHWND(), pref, true); } +void Window::RunSystemMenu(const CPoint& 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 + // to get a system menu. We also can't take the return value of this + // function. We need to call it *again* to get a valid HMENU. + ::GetSystemMenu(GetHWND(), TRUE); + HMENU system_menu = ::GetSystemMenu(GetHWND(), FALSE); + int id = ::TrackPopupMenu(system_menu, + TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, + point.x, point.y, 0, GetHWND(), NULL); + ExecuteSystemMenuCommand(id); +} + /////////////////////////////////////////////////////////////////////////////// // Window, HWNDViewContainer overrides: @@ -330,7 +348,8 @@ void Window::OnActivate(UINT action, BOOL minimized, HWND window) { } void Window::OnCommand(UINT notification_code, int command_id, HWND window) { - window_delegate_->ExecuteWindowsCommand(command_id); + if (!window_delegate_->ExecuteWindowsCommand(command_id)) + HWNDViewContainer::OnCommand(notification_code, command_id, window); } void Window::OnDestroy() { @@ -376,6 +395,21 @@ LRESULT Window::OnNCHitTest(const CPoint& point) { return 0; } +void Window::OnNCLButtonDown(UINT ht_component, const CPoint& point) { + if (non_client_view_ && ht_component == HTSYSMENU) + RunSystemMenu(non_client_view_->GetSystemMenuPoint()); + HWNDViewContainer::OnNCLButtonDown(ht_component, point); +} + +void Window::OnNCRButtonDown(UINT ht_component, const CPoint& point) { + if (ht_component == HTCAPTION || ht_component == HTSYSMENU) { + RunSystemMenu(point); + } else { + HWNDViewContainer::OnNCRButtonDown(ht_component, point); + } +} + + LRESULT Window::OnSetCursor(HWND window, UINT hittest_code, UINT message) { if (hittest_code == HTBOTTOMRIGHT) { // If the mouse was over the resize gripper, make sure the right cursor is @@ -399,6 +433,10 @@ void Window::OnSize(UINT size_param, const CSize& new_size) { } void Window::OnSysCommand(UINT notification_code, CPoint click) { + // First see if the delegate can handle it. + if (window_delegate_->ExecuteWindowsCommand(notification_code)) + return; + if (notification_code == IDC_ALWAYS_ON_TOP) { is_always_on_top_ = !is_always_on_top_; diff --git a/chrome/views/window.h b/chrome/views/window.h index ab3e7a5..ac496bb 100644 --- a/chrome/views/window.h +++ b/chrome/views/window.h @@ -97,6 +97,9 @@ class Window : public HWNDViewContainer { // Tell the window to update its icon from the delegate. virtual void UpdateWindowIcon(); + // Executes the specified SC_command. + void ExecuteSystemMenuCommand(int command); + // The parent of this window. HWND owning_window() const { return owning_hwnd_; } @@ -150,6 +153,9 @@ class Window : public HWNDViewContainer { void set_client_view(ClientView* client_view) { client_view_ = client_view; } + // Shows the system menu at the specified screen point. + void RunSystemMenu(const CPoint& point); + // Overridden from HWNDViewContainer: virtual void OnActivate(UINT action, BOOL minimized, HWND window); virtual void OnCommand(UINT notification_code, int command_id, HWND window); @@ -157,6 +163,8 @@ class Window : public HWNDViewContainer { virtual LRESULT OnEraseBkgnd(HDC dc); virtual LRESULT OnNCActivate(BOOL active); virtual LRESULT OnNCHitTest(const CPoint& point); + virtual void OnNCLButtonDown(UINT ht_component, const CPoint& point); + virtual void OnNCRButtonDown(UINT ht_component, const CPoint& point); virtual LRESULT OnSetCursor(HWND window, UINT hittest_code, UINT message); virtual void OnSize(UINT size_param, const CSize& new_size); virtual void OnSysCommand(UINT notification_code, CPoint click); diff --git a/chrome/views/window_delegate.h b/chrome/views/window_delegate.h index 1ab7add..8abda7c 100644 --- a/chrome/views/window_delegate.h +++ b/chrome/views/window_delegate.h @@ -92,8 +92,9 @@ class WindowDelegate { return false; } - // Execute a command in the window's controller. - virtual void ExecuteWindowsCommand(int command_id) { } + // Execute a command in the window's controller. Returns true if the command + // was handled, false if it was not. + virtual bool ExecuteWindowsCommand(int command_id) { return false; } // Saves the specified bounds, maximized and always on top state as the // window's position to/ be restored the next time it is shown. |