summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbeng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-05 00:06:22 +0000
committerbeng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-05 00:06:22 +0000
commitee0b38b16afa0a6d1cfd07df66ec67cee8bac6c8 (patch)
tree558132c0345c91f5b73c0ea03db2b1ce60ce7d69 /chrome
parent4ae627586ecb6184c3b766fd5128709442b17360 (diff)
downloadchromium_src-ee0b38b16afa0a6d1cfd07df66ec67cee8bac6c8.zip
chromium_src-ee0b38b16afa0a6d1cfd07df66ec67cee8bac6c8.tar.gz
chromium_src-ee0b38b16afa0a6d1cfd07df66ec67cee8bac6c8.tar.bz2
Add the AeroGlassFrame and AeroGlassNonClientView for Vista.
Note that AeroGlassFrame needs a NonClientView as well - even though Windows draws most of the frame and its borders, we do some custom rendering in the non-client area, such as the distributor logo, the client edge and toolbar backgrounds. This necessitated allowing Window to support an optional NonClientView. I just jimmied this in for now... can clean up that API later if desired. B=1031854 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@352 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/views/frame/aero_glass_frame.cc138
-rw-r--r--chrome/browser/views/frame/aero_glass_frame.h44
-rw-r--r--chrome/browser/views/frame/aero_glass_non_client_view.cc262
-rw-r--r--chrome/browser/views/frame/aero_glass_non_client_view.h34
-rw-r--r--chrome/browser/views/frame/browser_view2.cc2
-rw-r--r--chrome/browser/views/frame/browser_window_factory.cc51
-rw-r--r--chrome/views/custom_frame_window.cc6
-rw-r--r--chrome/views/custom_frame_window.h6
-rw-r--r--chrome/views/window.cc22
-rw-r--r--chrome/views/window.h7
10 files changed, 519 insertions, 53 deletions
diff --git a/chrome/browser/views/frame/aero_glass_frame.cc b/chrome/browser/views/frame/aero_glass_frame.cc
index 32e7044..b3db14e 100644
--- a/chrome/browser/views/frame/aero_glass_frame.cc
+++ b/chrome/browser/views/frame/aero_glass_frame.cc
@@ -27,13 +27,147 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <dwmapi.h>
+
#include "chrome/browser/views/frame/aero_glass_frame.h"
+#include "chrome/app/theme/theme_resources.h"
+#include "chrome/browser/views/frame/browser_view2.h"
+#include "chrome/browser/views/frame/aero_glass_non_client_view.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/views/window_delegate.h"
+
+// static
+static const int kResizeBorder = 5;
+
+// 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;
+
///////////////////////////////////////////////////////////////////////////////
-// AeroGlassFrame, public:
+// OpaqueFrame, public:
-AeroGlassFrame::AeroGlassFrame() : Window(NULL) {
+AeroGlassFrame::AeroGlassFrame(BrowserView2* browser_view)
+ : Window(browser_view),
+ browser_view_(browser_view),
+ frame_initialized_(false) {
+ non_client_view_ = new AeroGlassNonClientView(this);
+ browser_view_->set_frame(this);
}
AeroGlassFrame::~AeroGlassFrame() {
}
+
+void AeroGlassFrame::Init(const gfx::Rect& bounds) {
+ Window::Init(NULL, bounds);
+}
+
+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);
+ SendMessage(GetHWND(), WM_GETTITLEBARINFOEX, 0, (WPARAM)&titlebar_info);
+
+ RECT wr;
+ GetWindowRect(&wr);
+
+ return wr.right - titlebar_info.rgrect[2].left;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// AeroGlassFrame, BrowserFrame implementation:
+
+ChromeViews::Window* AeroGlassFrame::GetWindow() {
+ return this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// AeroGlassFrame, ChromeViews::HWNDViewContainer implementation:
+
+LRESULT AeroGlassFrame::OnNCActivate(BOOL active) {
+ if (!frame_initialized_) {
+ ::SetWindowPos(GetHWND(), NULL, 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
+ UpdateDWMFrame();
+ frame_initialized_ = true;
+ }
+ return TRUE;
+}
+
+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;
+
+ // 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);
+ return 0;
+}
+
+LRESULT AeroGlassFrame::OnNCHitTest(const CPoint& pt) {
+ LRESULT result;
+ if (DwmDefWindowProc(GetHWND(), WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y),
+ &result)) {
+ return result;
+ }
+ return Window::OnNCHitTest(pt);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// AeroGlassFrame, private:
+
+void AeroGlassFrame::UpdateDWMFrame() {
+ // Nothing to do yet.
+ 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);
+}
diff --git a/chrome/browser/views/frame/aero_glass_frame.h b/chrome/browser/views/frame/aero_glass_frame.h
index 3795098..df0d90ea 100644
--- a/chrome/browser/views/frame/aero_glass_frame.h
+++ b/chrome/browser/views/frame/aero_glass_frame.h
@@ -30,21 +30,55 @@
#ifndef CHROME_BROWSER_VIEWS_FRAME_AERO_GLASS_FRAME_H_
#define CHROME_BROWSER_VIEWS_FRAME_AERO_GLASS_FRAME_H_
+#include "chrome/browser/views/frame/browser_frame.h"
#include "chrome/views/window.h"
+class BrowserView2;
+
///////////////////////////////////////////////////////////////////////////////
// AeroGlassFrame
//
-// AeroGlassFrame is a Window subclass that in conjunction with
-// AeroGlassNonClientView provides the window frame on Windows Vista with
-// DWM desktop compositing is enabled. A standard Windows frame is used.
+// AeroGlassFrame is a Window subclass that provides the window frame on
+// Windows Vista with DWM desktop compositing enabled. The window's non-client
+// areas are drawn by the system.
//
-class AeroGlassFrame : public ChromeViews::Window {
+class AeroGlassFrame : public BrowserFrame,
+ public ChromeViews::Window {
public:
- AeroGlassFrame();
+ explicit AeroGlassFrame(BrowserView2* browser_view);
virtual ~AeroGlassFrame();
+ void Init(const gfx::Rect& bounds);
+
+ bool IsToolbarVisible() const { return true; }
+ bool IsTabStripVisible() const { return true; }
+
+ // 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;
+
+ // Overridden from BrowserFrame:
+ virtual ChromeViews::Window* GetWindow();
+
+ protected:
+ // Overridden from ChromeViews::HWNDViewContainer:
+ virtual LRESULT OnNCActivate(BOOL active);
+ virtual LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param);
+ virtual LRESULT OnNCHitTest(const CPoint& pt);
+
private:
+ // Updates the DWM with the frame bounds.
+ void UpdateDWMFrame();
+
+ // The BrowserView2 is our ClientView. This is a pointer to it.
+ BrowserView2* browser_view_;
+
+ bool frame_initialized_;
+
DISALLOW_EVIL_CONSTRUCTORS(AeroGlassFrame);
};
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 87cd951..e298639 100644
--- a/chrome/browser/views/frame/aero_glass_non_client_view.cc
+++ b/chrome/browser/views/frame/aero_glass_non_client_view.cc
@@ -27,13 +27,107 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
#include "chrome/browser/views/frame/aero_glass_non_client_view.h"
+#include "chrome/app/theme/theme_resources.h"
+#include "chrome/common/gfx/chrome_canvas.h"
+#include "chrome/common/gfx/chrome_font.h"
+#include "chrome/common/gfx/path.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/views/client_view.h"
+#include "chrome/views/window_delegate.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowResources
+//
+// An enumeration of bitmap resources used by this window.
+enum FramePartBitmap {
+ FRAME_PART_BITMAP_FIRST = 0, // must be first.
+
+ // Client Edge Border.
+ FRAME_CLIENT_EDGE_TOP_LEFT,
+ FRAME_CLIENT_EDGE_TOP,
+ FRAME_CLIENT_EDGE_TOP_RIGHT,
+ FRAME_CLIENT_EDGE_RIGHT,
+ FRAME_CLIENT_EDGE_BOTTOM_RIGHT,
+ FRAME_CLIENT_EDGE_BOTTOM,
+ FRAME_CLIENT_EDGE_BOTTOM_LEFT,
+ FRAME_CLIENT_EDGE_LEFT,
+
+ 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 {
+ public:
+ AeroGlassWindowResources() { InitClass(); }
+ virtual ~AeroGlassWindowResources() { }
+
+ // WindowResources implementation:
+ virtual SkBitmap* GetPartBitmap(FramePartBitmap part) const {
+ return standard_frame_bitmaps_[part];
+ }
+ virtual const ChromeFont& GetTitleFont() const {
+ return title_font_;
+ }
+
+ private:
+ static void InitClass() {
+ static bool initialized = false;
+ if (!initialized) {
+ static const int kFramePartBitmapIds[] = {
+ 0,
+ IDR_CONTENT_TOP_LEFT_CORNER, IDR_CONTENT_TOP_CENTER,
+ IDR_CONTENT_TOP_RIGHT_CORNER, IDR_CONTENT_RIGHT_SIDE,
+ IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER,
+ IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE,
+ 0
+ };
+
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) {
+ int id = kFramePartBitmapIds[i];
+ if (id != 0)
+ standard_frame_bitmaps_[i] = rb.GetBitmapNamed(id);
+ }
+ title_font_ =
+ rb.GetFont(ResourceBundle::BaseFont).DeriveFont(1, ChromeFont::BOLD);
+ initialized = true;
+ }
+ }
+
+ static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT];
+ static ChromeFont title_font_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AeroGlassWindowResources);
+};
+
+// static
+SkBitmap* AeroGlassWindowResources::standard_frame_bitmaps_[];
+ChromeFont AeroGlassWindowResources::title_font_;
+
+WindowResources* AeroGlassNonClientView::resources_ = NULL;
+SkBitmap AeroGlassNonClientView::distributor_logo_;
+
+static const int kTitleTopOffset = 6;
+static const int kTitleBottomSpacing = 6;
+static const int kNoTitleTopSpacing = 8;
+static const int kWindowHorizontalBorderSize = 2;
+static const int kWindowVerticalBorderSize = 2;
+static const int kDistributorLogoHorizontalOffset = 7;
+static const int kDistributorLogoVerticalOffset = 3;
+
///////////////////////////////////////////////////////////////////////////////
// AeroGlassNonClientView, public:
-AeroGlassNonClientView::AeroGlassNonClientView() {
+AeroGlassNonClientView::AeroGlassNonClientView(AeroGlassFrame* frame)
+ : frame_(frame) {
+ InitClass();
}
AeroGlassNonClientView::~AeroGlassNonClientView() {
@@ -44,13 +138,18 @@ AeroGlassNonClientView::~AeroGlassNonClientView() {
gfx::Rect AeroGlassNonClientView::CalculateClientAreaBounds(int width,
int height) const {
- return gfx::Rect();
+ int top_margin = CalculateNonClientTopHeight();
+ return gfx::Rect(kWindowHorizontalBorderSize, top_margin,
+ std::max(0, width - (2 * kWindowHorizontalBorderSize)),
+ std::max(0, height - top_margin - kWindowVerticalBorderSize));
}
gfx::Size AeroGlassNonClientView::CalculateWindowSizeForClientSize(
int width,
int height) const {
- return gfx::Size();
+ int top_margin = CalculateNonClientTopHeight();
+ return gfx::Size(width + (2 * kWindowHorizontalBorderSize),
+ height + top_margin + kWindowVerticalBorderSize);
}
CPoint AeroGlassNonClientView::GetSystemMenuPoint() const {
@@ -58,7 +157,16 @@ CPoint AeroGlassNonClientView::GetSystemMenuPoint() const {
}
int AeroGlassNonClientView::NonClientHitTest(const gfx::Point& point) {
- return HTCLIENT;
+ CRect bounds;
+ CPoint test_point = point.ToPOINT();
+
+ // First see if it's within the grow box area, since that overlaps the client
+ // bounds.
+ int component = frame_->client_view()->NonClientHitTest(point);
+ if (component != HTNOWHERE)
+ return component;
+
+ return HTNOWHERE;
}
void AeroGlassNonClientView::GetWindowMask(const gfx::Size& size,
@@ -71,11 +179,151 @@ void AeroGlassNonClientView::EnableClose(bool enable) {
///////////////////////////////////////////////////////////////////////////////
// AeroGlassNonClientView, ChromeViews::View overrides:
+void AeroGlassNonClientView::Paint(ChromeCanvas* canvas) {
+ PaintDistributorLogo(canvas);
+ PaintToolbarBackground(canvas);
+ PaintClientEdge(canvas);
+
+ // TODO(beng): remove this
+ gfx::Rect contents_bounds = frame_->GetContentsBounds();
+ canvas->FillRectInt(SK_ColorGRAY, contents_bounds.x(), contents_bounds.y(),
+ contents_bounds.width(), contents_bounds.height());
+}
+
void AeroGlassNonClientView::Layout() {
+ LayoutDistributorLogo();
+ LayoutClientView();
+}
+
+void AeroGlassNonClientView::GetPreferredSize(CSize* out) {
+ DCHECK(out);
+ frame_->client_view()->GetPreferredSize(out);
+ out->cx += 2 * kWindowHorizontalBorderSize;
+ out->cy += CalculateNonClientTopHeight() + kWindowVerticalBorderSize;
+}
+
+void AeroGlassNonClientView::DidChangeBounds(const CRect& previous,
+ const CRect& current) {
+ Layout();
}
void AeroGlassNonClientView::ViewHierarchyChanged(bool is_add,
- ChromeViews::View* parent,
- ChromeViews::View* child) {
+ ChromeViews::View* parent,
+ ChromeViews::View* child) {
+ if (is_add && child == this) {
+ DCHECK(GetViewContainer());
+ DCHECK(frame_->client_view()->GetParent() != this);
+ AddChildView(frame_->client_view());
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// AeroGlassNonClientView, private:
+
+int AeroGlassNonClientView::CalculateNonClientTopHeight() const {
+ if (frame_->window_delegate()->ShouldShowWindowTitle()) {
+ return kTitleTopOffset + resources_->GetTitleFont().height() +
+ kTitleBottomSpacing;
+ }
+ return kNoTitleTopSpacing;
+}
+
+void AeroGlassNonClientView::PaintDistributorLogo(ChromeCanvas* canvas) {
+ // The distributor logo is only painted when the frame is not maximized.
+ if (!frame_->IsMaximized() && !frame_->IsMinimized()) {
+ canvas->DrawBitmapInt(distributor_logo_, logo_bounds_.x(),
+ logo_bounds_.y());
+ }
}
+void AeroGlassNonClientView::PaintToolbarBackground(ChromeCanvas* canvas) {
+ if (frame_->IsToolbarVisible() || frame_->IsTabStripVisible()) {
+ SkBitmap* toolbar_left =
+ resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT);
+ SkBitmap* toolbar_center =
+ resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP);
+ SkBitmap* toolbar_right =
+ resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT);
+
+ gfx::Rect toolbar_bounds = frame_->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());
+ 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());
+ }
+}
+
+void AeroGlassNonClientView::PaintClientEdge(ChromeCanvas* canvas) {
+ SkBitmap* right = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT);
+ SkBitmap* bottom_right =
+ resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT);
+ SkBitmap* bottom = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM);
+ SkBitmap* bottom_left =
+ resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT);
+ SkBitmap* left = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT);
+
+ // 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();
+ client_area_bounds.SetRect(
+ client_area_bounds.x(),
+ frame_->client_view()->GetY() + toolbar_bounds.bottom() - 1,
+ client_area_bounds.width(),
+ std::max(0, GetHeight() - frame_->client_view()->GetY() -
+ toolbar_bounds.bottom() + 1 - kWindowVerticalBorderSize));
+
+ canvas->TileImageInt(*right, client_area_bounds.right(),
+ client_area_bounds.y(),
+ right->width(), client_area_bounds.height());
+ canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(),
+ client_area_bounds.bottom());
+ canvas->TileImageInt(*bottom, client_area_bounds.x(),
+ client_area_bounds.bottom(),
+ client_area_bounds.width(), bottom_right->height());
+ canvas->DrawBitmapInt(*bottom_left,
+ client_area_bounds.x() - bottom_left->width(),
+ client_area_bounds.bottom());
+ canvas->TileImageInt(*left, client_area_bounds.x() - left->width(),
+ client_area_bounds.y(),
+ left->width(), client_area_bounds.height());
+}
+
+void AeroGlassNonClientView::LayoutDistributorLogo() {
+ int logo_w = distributor_logo_.width();
+ int logo_h = distributor_logo_.height();
+
+ int w = GetWidth();
+ int mbx = frame_->GetMinimizeButtonOffset();
+
+ logo_bounds_.SetRect(
+ GetWidth() - frame_->GetMinimizeButtonOffset() - logo_w,
+ kDistributorLogoVerticalOffset, logo_w, logo_h);
+}
+
+void AeroGlassNonClientView::LayoutClientView() {
+ gfx::Rect client_bounds(
+ CalculateClientAreaBounds(GetWidth(), GetHeight()));
+ frame_->client_view()->SetBounds(client_bounds.ToRECT());
+}
+
+// static
+void AeroGlassNonClientView::InitClass() {
+ static bool initialized = false;
+ if (!initialized) {
+ resources_ = new AeroGlassWindowResources;
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ distributor_logo_ = *rb.GetBitmapNamed(IDR_DISTRIBUTOR_LOGO);
+ initialized = true;
+ }
+}
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 31968e4..eea2e0b 100644
--- a/chrome/browser/views/frame/aero_glass_non_client_view.h
+++ b/chrome/browser/views/frame/aero_glass_non_client_view.h
@@ -30,12 +30,16 @@
#ifndef CHROME_BROWSER_VIEWS_FRAME_AERO_GLASS_NON_CLIENT_VIEW_H_
#define CHROME_BROWSER_VIEWS_FRAME_AERO_GLASS_NON_CLIENT_VIEW_H_
-
+#include "chrome/browser/views/frame/aero_glass_frame.h"
#include "chrome/views/non_client_view.h"
+#include "chrome/views/button.h"
+
+class WindowResources;
class AeroGlassNonClientView : public ChromeViews::NonClientView {
public:
- AeroGlassNonClientView();
+ // Constructs a non-client view for an AeroGlassFrame.
+ explicit AeroGlassNonClientView(AeroGlassFrame* frame);
virtual ~AeroGlassNonClientView();
protected:
@@ -49,12 +53,38 @@ class AeroGlassNonClientView : public ChromeViews::NonClientView {
virtual void EnableClose(bool enable);
// Overridden from ChromeViews::View:
+ virtual void Paint(ChromeCanvas* canvas);
virtual void Layout();
+ virtual void GetPreferredSize(CSize* out);
+ virtual void DidChangeBounds(const CRect& previous, const CRect& current);
virtual void ViewHierarchyChanged(bool is_add,
ChromeViews::View* parent,
ChromeViews::View* child);
private:
+ // Returns the height of the non-client area at the top of the window (the
+ // title bar, etc).
+ int CalculateNonClientTopHeight() const;
+
+ // Paint various sub-components of this view.
+ void PaintDistributorLogo(ChromeCanvas* canvas);
+ void PaintToolbarBackground(ChromeCanvas* canvas);
+ void PaintClientEdge(ChromeCanvas* canvas);
+
+ // Layout various sub-components of this view.
+ void LayoutDistributorLogo();
+ void LayoutClientView();
+
+ // The layout rect of the distributor logo, if visible.
+ gfx::Rect logo_bounds_;
+
+ // The frame that hosts this view.
+ AeroGlassFrame* frame_;
+
+ static void InitClass();
+ static SkBitmap distributor_logo_;
+ static WindowResources* resources_;
+
DISALLOW_EVIL_CONSTRUCTORS(AeroGlassNonClientView);
};
diff --git a/chrome/browser/views/frame/browser_view2.cc b/chrome/browser/views/frame/browser_view2.cc
index bc74d94..af62ab1 100644
--- a/chrome/browser/views/frame/browser_view2.cc
+++ b/chrome/browser/views/frame/browser_view2.cc
@@ -119,7 +119,7 @@ StatusBubble* BrowserView2::GetStatusBubble() {
}
ChromeViews::RootView* BrowserView2::GetRootView() {
- // TODO(beng): get rid of this stupid method.
+ // TODO(beng): Get rid of this stupid method.
return View::GetRootView();
}
diff --git a/chrome/browser/views/frame/browser_window_factory.cc b/chrome/browser/views/frame/browser_window_factory.cc
index 407e215..1897ebcf 100644
--- a/chrome/browser/views/frame/browser_window_factory.cc
+++ b/chrome/browser/views/frame/browser_window_factory.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/frame_util.h"
+#include "chrome/browser/views/frame/aero_glass_frame.h"
#include "chrome/browser/views/frame/browser_frame.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/frame/browser_view2.h"
@@ -62,27 +63,29 @@ BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser,
return window->GetBrowserView();
}
-///////////////////////////////////////////////////////////////////////////////
-// BrowserFrame, public:
-
-// static
-BrowserFrame::FrameType BrowserFrame::GetActiveFrameType() {
- return win_util::ShouldUseVistaFrame() ? BrowserFrame::FRAMETYPE_AERO_GLASS
- : BrowserFrame::FRAMETYPE_OPAQUE;
-}
-
-// static
-BrowserFrame* BrowserFrame::CreateForBrowserView(BrowserFrame::FrameType type,
- BrowserView2* browser_view,
- const gfx::Rect& bounds,
- int show_command) {
- if (type == FRAMETYPE_OPAQUE) {
- OpaqueFrame* frame = new OpaqueFrame(browser_view);
- frame->Init(NULL, bounds);
- return frame;
- } else if (type == FRAMETYPE_AERO_GLASS) {
- NOTREACHED() << "Aero/Glass not supported yet by magic_browzR switch";
- }
- NOTREACHED() << "Unsupported frame type";
- return NULL;
-}
+///////////////////////////////////////////////////////////////////////////////
+// BrowserFrame, public:
+
+// static
+BrowserFrame::FrameType BrowserFrame::GetActiveFrameType() {
+ return win_util::ShouldUseVistaFrame() ? BrowserFrame::FRAMETYPE_AERO_GLASS
+ : BrowserFrame::FRAMETYPE_OPAQUE;
+}
+
+// static
+BrowserFrame* BrowserFrame::CreateForBrowserView(BrowserFrame::FrameType type,
+ BrowserView2* browser_view,
+ const gfx::Rect& bounds,
+ int show_command) {
+ if (type == FRAMETYPE_OPAQUE) {
+ OpaqueFrame* frame = new OpaqueFrame(browser_view);
+ frame->Init(NULL, bounds);
+ return frame;
+ } else if (type == FRAMETYPE_AERO_GLASS) {
+ AeroGlassFrame* frame = new AeroGlassFrame(browser_view);
+ frame->Init(bounds);
+ return frame;
+ }
+ NOTREACHED() << "Unsupported frame type";
+ return NULL;
+}
diff --git a/chrome/views/custom_frame_window.cc b/chrome/views/custom_frame_window.cc
index 928947e..0acf4b3 100644
--- a/chrome/views/custom_frame_window.cc
+++ b/chrome/views/custom_frame_window.cc
@@ -833,16 +833,16 @@ void DefaultNonClientView::InitClass() {
CustomFrameWindow::CustomFrameWindow(WindowDelegate* window_delegate)
: Window(window_delegate),
- non_client_view_(new DefaultNonClientView(this)),
is_active_(false) {
InitClass();
+ non_client_view_ = new DefaultNonClientView(this);
}
CustomFrameWindow::CustomFrameWindow(WindowDelegate* window_delegate,
NonClientView* non_client_view)
- : Window(window_delegate),
- non_client_view_(non_client_view) {
+ : Window(window_delegate) {
InitClass();
+ non_client_view_ = non_client_view;
}
CustomFrameWindow::~CustomFrameWindow() {
diff --git a/chrome/views/custom_frame_window.h b/chrome/views/custom_frame_window.h
index d61b6b8..b94cde3 100644
--- a/chrome/views/custom_frame_window.h
+++ b/chrome/views/custom_frame_window.h
@@ -86,12 +86,6 @@ class CustomFrameWindow : public Window {
virtual LRESULT OnSetCursor(HWND window, UINT hittest_code, UINT message);
virtual void OnSize(UINT param, const CSize& size);
- // The View that provides the non-client area of the window (title bar,
- // window controls, sizing borders etc). To use an implementation other than
- // the default, this class must be subclassed and this value set to the
- // desired implementation before calling |Init|.
- NonClientView* non_client_view_;
-
private:
// Shows the system menu at the specified screen point.
void RunSystemMenu(const CPoint& point);
diff --git a/chrome/views/window.cc b/chrome/views/window.cc
index 4ace937..7047d84 100644
--- a/chrome/views/window.cc
+++ b/chrome/views/window.cc
@@ -37,6 +37,7 @@
#include "chrome/common/resource_bundle.h"
#include "chrome/common/win_util.h"
#include "chrome/views/custom_frame_window.h"
+#include "chrome/views/non_client_view.h"
#include "chrome/views/window_delegate.h"
#include "generated_resources.h"
@@ -251,6 +252,7 @@ Window::Window(WindowDelegate* window_delegate)
: HWNDViewContainer(),
focus_on_creation_(true),
window_delegate_(window_delegate),
+ non_client_view_(NULL),
client_view_(NULL),
owning_hwnd_(NULL),
minimum_size_(100, 100),
@@ -300,12 +302,21 @@ void Window::Init(HWND parent, const gfx::Rect& bounds) {
void Window::SetClientView(ClientView* client_view) {
DCHECK(client_view && !client_view_ && GetHWND());
client_view_ = client_view;
- HWNDViewContainer::SetContentsView(client_view_);
+ if (non_client_view_) {
+ // This will trigger the ClientView to be added by the non-client view.
+ HWNDViewContainer::SetContentsView(non_client_view_);
+ } else {
+ HWNDViewContainer::SetContentsView(client_view_);
+ }
}
void Window::SizeWindowToDefault() {
CSize pref(0, 0);
- client_view_->GetPreferredSize(&pref);
+ if (non_client_view_) {
+ non_client_view_->GetPreferredSize(&pref);
+ } else {
+ client_view_->GetPreferredSize(&pref);
+ }
DCHECK(pref.cx > 0 && pref.cy > 0);
// CenterAndSizeWindow adjusts the window size to accommodate the non-client
// area.
@@ -343,7 +354,12 @@ LRESULT Window::OnNCHitTest(const CPoint& point) {
// of the non-client area.
CPoint temp = point;
MapWindowPoints(HWND_DESKTOP, GetHWND(), &temp, 1);
- int component = client_view_->NonClientHitTest(gfx::Point(temp));
+ int component = HTNOWHERE;
+ if (non_client_view_) {
+ component = non_client_view_->NonClientHitTest(gfx::Point(temp));
+ } else {
+ component = client_view_->NonClientHitTest(gfx::Point(temp));
+ }
if (component != HTNOWHERE)
return component;
diff --git a/chrome/views/window.h b/chrome/views/window.h
index a941cb2..d098938 100644
--- a/chrome/views/window.h
+++ b/chrome/views/window.h
@@ -44,6 +44,7 @@ namespace ChromeViews {
class ClientView;
class Client;
+class NonClientView;
class WindowDelegate;
////////////////////////////////////////////////////////////////////////////////
@@ -174,6 +175,12 @@ class Window : public HWNDViewContainer {
virtual void OnSize(UINT size_param, const CSize& new_size);
virtual void OnSysCommand(UINT notification_code, CPoint click);
+ // The View that provides the non-client area of the window (title bar,
+ // window controls, sizing borders etc). To use an implementation other than
+ // the default, this class must be subclassed and this value set to the
+ // desired implementation before calling |Init|.
+ NonClientView* non_client_view_;
+
private:
// Set the window as modal (by disabling all the other windows).
void BecomeModal();