summaryrefslogtreecommitdiffstats
path: root/chrome/views
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-03 00:28:00 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-03 00:28:00 +0000
commit32670b07a6c42634f446e3d471f42a9fb40090f2 (patch)
tree77b15435f3a436d54fcaa5cb4c0d4371a007fad6 /chrome/views
parenta0e5688cc11f7f5e835b5c1a75c17ce4a28a1527 (diff)
downloadchromium_src-32670b07a6c42634f446e3d471f42a9fb40090f2.zip
chromium_src-32670b07a6c42634f446e3d471f42a9fb40090f2.tar.gz
chromium_src-32670b07a6c42634f446e3d471f42a9fb40090f2.tar.bz2
Support DWM switching.
This completes the collapsing of window types and browser frames around a single class: views::Window. CustomFrameWindow is removed with this change. The Browser window is represented by a single views::Window subclass: BrowserFrame, which replaces both AeroGlassFrame and OpaqueFrame. NonClientView is now a container of two sibling classes - the Window's ClientView (in the Browser's case, BrowserView), and a NonClientFrameView subclass, which provides the rendering for the non-client portions of the window. These Views are siblings rather than the ClientView a child of the NonClientFrameView because when the DWM is toggled, the ClientView would have to be re-parented. Many Views make the assumption they are only inserted into a View hierarchy once, and so this is problematic. By having the views be siblings, this is avoided. With this in mind, all of the former NonClientViews now become NonClientFrameView subclasses: DefaultNonClientView -> CustomFrameView (non-existent, NonClientView) -> NativeFrameView AeroGlassNonClientView -> GlassBrowserFrameView OpaqueNonClientView -> OpaqueBrowserFrameView The latter two derive from NonClientFrameView via BrowserNonClientFrameView, which adds some extras. I also had to modify the TabRenderer class to know how to drop its cache of tab background images when the theme changes since it uses different ones for Glass and non-Glass. This change also fixes a few non-client flicker issues relating to window non-client activation by using more ScopedRedrawLocks. (Touches info_bubble.cc, window.cc) Bugs fixed: http://crbug.com/153 http://crbug.com/747 http://crbug.com/2371 http://crbug.com/3264 http://crbug.com/8234 Plumbing for http://crbug.com/8247 Design docs: http://dev.chromium.org/developers/design-documents/views-windowing http://dev.chromium.org/developers/design-documents/browser-window Review URL: http://codereview.chromium.org/27317 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10757 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/views')
-rw-r--r--chrome/views/custom_frame_view.cc (renamed from chrome/views/default_non_client_view.cc)167
-rw-r--r--chrome/views/custom_frame_view.h (renamed from chrome/views/default_non_client_view.h)47
-rw-r--r--chrome/views/custom_frame_window.cc506
-rw-r--r--chrome/views/custom_frame_window.h103
-rw-r--r--chrome/views/native_frame_view.cc61
-rw-r--r--chrome/views/native_frame_view.h38
-rw-r--r--chrome/views/non_client_view.cc135
-rw-r--r--chrome/views/non_client_view.h186
-rw-r--r--chrome/views/root_view.cc4
-rw-r--r--chrome/views/root_view.h4
-rw-r--r--chrome/views/view.cc6
-rw-r--r--chrome/views/view.h8
-rw-r--r--chrome/views/views.vcproj20
-rw-r--r--chrome/views/widget.h8
-rw-r--r--chrome/views/widget_win.cc2
-rw-r--r--chrome/views/widget_win.h19
-rw-r--r--chrome/views/window.cc159
-rw-r--r--chrome/views/window.h76
18 files changed, 639 insertions, 910 deletions
diff --git a/chrome/views/default_non_client_view.cc b/chrome/views/custom_frame_view.cc
index e3998a5..54303f6 100644
--- a/chrome/views/default_non_client_view.cc
+++ b/chrome/views/custom_frame_view.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/views/default_non_client_view.h"
+#include "chrome/views/custom_frame_view.h"
#include "base/win_util.h"
#include "chrome/common/gfx/path.h"
@@ -11,6 +11,7 @@
#include "chrome/common/resource_bundle.h"
#include "chrome/common/win_util.h"
#include "chrome/views/client_view.h"
+#include "chrome/views/window_delegate.h"
#include "grit/theme_resources.h"
namespace views {
@@ -165,9 +166,9 @@ SkBitmap* ActiveWindowResources::standard_frame_bitmaps_[];
SkBitmap* InactiveWindowResources::standard_frame_bitmaps_[];
// static
-WindowResources* DefaultNonClientView::active_resources_ = NULL;
-WindowResources* DefaultNonClientView::inactive_resources_ = NULL;
-ChromeFont DefaultNonClientView::title_font_;
+WindowResources* CustomFrameView::active_resources_ = NULL;
+WindowResources* CustomFrameView::inactive_resources_ = NULL;
+ChromeFont CustomFrameView::title_font_;
namespace {
// The frame border is only visible in restored mode and is hardcoded to 4 px on
@@ -214,19 +215,17 @@ const int kCaptionTopSpacing = 1;
}
///////////////////////////////////////////////////////////////////////////////
-// DefaultNonClientView, public:
+// CustomFrameView, public:
-DefaultNonClientView::DefaultNonClientView(
- CustomFrameWindow* container)
- : NonClientView(),
- client_view_(NULL),
+CustomFrameView::CustomFrameView(Window* frame)
+ : NonClientFrameView(),
close_button_(new Button),
restore_button_(new Button),
maximize_button_(new Button),
minimize_button_(new Button),
system_menu_button_(new Button),
should_show_minmax_buttons_(false),
- container_(container) {
+ frame_(frame) {
InitClass();
WindowResources* resources = active_resources_;
@@ -261,49 +260,39 @@ DefaultNonClientView::DefaultNonClientView(
minimize_button_->SetListener(this, -1);
AddChildView(minimize_button_);
- should_show_minmax_buttons_ = container->window_delegate()->CanMaximize();
+ should_show_minmax_buttons_ = frame_->window_delegate()->CanMaximize();
AddChildView(system_menu_button_);
}
-DefaultNonClientView::~DefaultNonClientView() {
+CustomFrameView::~CustomFrameView() {
}
///////////////////////////////////////////////////////////////////////////////
-// DefaultNonClientView, CustomFrameWindow::NonClientView implementation:
+// CustomFrameView, NonClientFrameView implementation:
-gfx::Rect DefaultNonClientView::CalculateClientAreaBounds(int width,
- int height) const {
- int top_height = NonClientTopBorderHeight();
- int border_thickness = NonClientBorderThickness();
- return gfx::Rect(border_thickness, top_height,
- std::max(0, width - (2 * border_thickness)),
- std::max(0, height - top_height - border_thickness));
+gfx::Rect CustomFrameView::GetBoundsForClientView() const {
+ return client_view_bounds_;
}
-gfx::Size DefaultNonClientView::CalculateWindowSizeForClientSize(
- int width,
- int height) const {
+gfx::Rect CustomFrameView::GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const {
+ int top_height = NonClientTopBorderHeight();
int border_thickness = NonClientBorderThickness();
- return gfx::Size(width + (2 * border_thickness),
- height + NonClientTopBorderHeight() + border_thickness);
+ return gfx::Rect(std::max(0, client_bounds.x() - border_thickness),
+ std::max(0, client_bounds.y() - top_height),
+ client_bounds.width() + (2 * border_thickness),
+ client_bounds.height() + top_height + border_thickness);
}
-gfx::Point DefaultNonClientView::GetSystemMenuPoint() const {
+gfx::Point CustomFrameView::GetSystemMenuPoint() const {
gfx::Point system_menu_point(FrameBorderThickness(),
NonClientTopBorderHeight() - BottomEdgeThicknessWithinNonClientHeight());
ConvertPointToScreen(this, &system_menu_point);
return system_menu_point;
}
-int DefaultNonClientView::NonClientHitTest(const gfx::Point& point) {
- if (!bounds().Contains(point))
- return HTNOWHERE;
-
- int frame_component = container_->client_view()->NonClientHitTest(point);
- if (frame_component != HTNOWHERE)
- return frame_component;
-
+int CustomFrameView::NonClientHitTest(const gfx::Point& point) {
// Then see if the point is within any of the window controls.
if (close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(point))
return HTCLOSE;
@@ -322,13 +311,13 @@ int DefaultNonClientView::NonClientHitTest(const gfx::Point& point) {
int window_component = GetHTComponentForFrame(point, FrameBorderThickness(),
NonClientBorderThickness(), kResizeAreaCornerSize, kResizeAreaCornerSize,
- container_->window_delegate()->CanResize());
+ frame_->window_delegate()->CanResize());
// Fall back to the caption if no other component matches.
return (window_component == HTNOWHERE) ? HTCAPTION : window_component;
}
-void DefaultNonClientView::GetWindowMask(const gfx::Size& size,
- gfx::Path* window_mask) {
+void CustomFrameView::GetWindowMask(const gfx::Size& size,
+ gfx::Path* window_mask) {
DCHECK(window_mask);
// Redefine the window visible region for the new size.
@@ -350,11 +339,11 @@ void DefaultNonClientView::GetWindowMask(const gfx::Size& size,
window_mask->close();
}
-void DefaultNonClientView::EnableClose(bool enable) {
+void CustomFrameView::EnableClose(bool enable) {
close_button_->SetEnabled(enable);
}
-void DefaultNonClientView::ResetWindowControls() {
+void CustomFrameView::ResetWindowControls() {
restore_button_->SetState(Button::BS_NORMAL);
minimize_button_->SetState(Button::BS_NORMAL);
maximize_button_->SetState(Button::BS_NORMAL);
@@ -362,79 +351,71 @@ void DefaultNonClientView::ResetWindowControls() {
}
///////////////////////////////////////////////////////////////////////////////
-// DefaultNonClientView, View overrides:
+// CustomFrameView, View overrides:
-void DefaultNonClientView::Paint(ChromeCanvas* canvas) {
- if (container_->IsMaximized())
+void CustomFrameView::Paint(ChromeCanvas* canvas) {
+ if (frame_->IsMaximized())
PaintMaximizedFrameBorder(canvas);
else
PaintRestoredFrameBorder(canvas);
PaintTitleBar(canvas);
- if (!container_->IsMaximized())
+ if (!frame_->IsMaximized())
PaintRestoredClientEdge(canvas);
}
-void DefaultNonClientView::Layout() {
+void CustomFrameView::Layout() {
LayoutWindowControls();
LayoutTitleBar();
LayoutClientView();
}
-gfx::Size DefaultNonClientView::GetPreferredSize() {
- gfx::Size pref = client_view_->GetPreferredSize();
+gfx::Size CustomFrameView::GetPreferredSize() {
+ gfx::Size pref = frame_->client_view()->GetPreferredSize();
DCHECK(pref.width() > 0 && pref.height() > 0);
- return CalculateWindowSizeForClientSize(pref.width(), pref.height());
-}
-
-void DefaultNonClientView::ViewHierarchyChanged(bool is_add,
- View* parent,
- View* child) {
- // Add our Client View as we are added to the Widget so that if we are
- // subsequently resized all the parent-child relationships are established.
- if (is_add && GetWidget() && child == this)
- AddChildView(container_->client_view());
+ gfx::Rect bounds(0, 0, pref.width(), pref.height());
+ return frame_->GetWindowBoundsForClientBounds(bounds).size();
}
///////////////////////////////////////////////////////////////////////////////
-// DefaultNonClientView, BaseButton::ButtonListener implementation:
+// CustomFrameView, BaseButton::ButtonListener implementation:
-void DefaultNonClientView::ButtonPressed(BaseButton* sender) {
+void CustomFrameView::ButtonPressed(BaseButton* sender) {
if (sender == close_button_)
- container_->ExecuteSystemMenuCommand(SC_CLOSE);
+ frame_->ExecuteSystemMenuCommand(SC_CLOSE);
else if (sender == minimize_button_)
- container_->ExecuteSystemMenuCommand(SC_MINIMIZE);
+ frame_->ExecuteSystemMenuCommand(SC_MINIMIZE);
else if (sender == maximize_button_)
- container_->ExecuteSystemMenuCommand(SC_MAXIMIZE);
+ frame_->ExecuteSystemMenuCommand(SC_MAXIMIZE);
else if (sender == restore_button_)
- container_->ExecuteSystemMenuCommand(SC_RESTORE);
+ frame_->ExecuteSystemMenuCommand(SC_RESTORE);
}
///////////////////////////////////////////////////////////////////////////////
-// DefaultNonClientView, private:
+// CustomFrameView, private:
-int DefaultNonClientView::FrameBorderThickness() const {
- return container_->IsMaximized() ?
+int CustomFrameView::FrameBorderThickness() const {
+ return frame_->IsMaximized() ?
GetSystemMetrics(SM_CXSIZEFRAME) : kFrameBorderThickness;
}
-int DefaultNonClientView::NonClientBorderThickness() const {
+int CustomFrameView::NonClientBorderThickness() const {
// In maximized mode, we don't show a client edge.
return FrameBorderThickness() +
- (container_->IsMaximized() ? 0 : kClientEdgeThickness);
+ (frame_->IsMaximized() ? 0 : kClientEdgeThickness);
}
-int DefaultNonClientView::NonClientTopBorderHeight() const {
+int CustomFrameView::NonClientTopBorderHeight() const {
int title_top_spacing, title_thickness;
return TitleCoordinates(&title_top_spacing, &title_thickness);
}
-int DefaultNonClientView::BottomEdgeThicknessWithinNonClientHeight() const {
+int CustomFrameView::BottomEdgeThicknessWithinNonClientHeight() const {
return kFrameShadowThickness +
- (container_->IsMaximized() ? 0 : kClientEdgeThickness);
+ (frame_->IsMaximized() ? 0 : kClientEdgeThickness);
}
-int DefaultNonClientView::TitleCoordinates(int* title_top_spacing,
- int* title_thickness) const {
+int CustomFrameView::TitleCoordinates(int* title_top_spacing,
+ int* title_thickness) const {
int frame_thickness = FrameBorderThickness();
int min_titlebar_height = kTitlebarMinimumHeight + frame_thickness;
*title_top_spacing = frame_thickness + kTitleTopSpacing;
@@ -445,7 +426,7 @@ int DefaultNonClientView::TitleCoordinates(int* title_top_spacing,
// since while it's part of the bottom spacing it will be added in at the end.
int title_bottom_spacing =
kFrameBorderThickness + kTitleTopSpacing - kFrameShadowThickness;
- if (container_->IsMaximized()) {
+ if (frame_->IsMaximized()) {
// When we maximize, the top border appears to be chopped off; shift the
// title down to stay centered within the remaining space.
int title_adjust = (kFrameBorderThickness / 2);
@@ -458,7 +439,7 @@ int DefaultNonClientView::TitleCoordinates(int* title_top_spacing,
BottomEdgeThicknessWithinNonClientHeight();
}
-void DefaultNonClientView::PaintRestoredFrameBorder(ChromeCanvas* canvas) {
+void CustomFrameView::PaintRestoredFrameBorder(ChromeCanvas* canvas) {
SkBitmap* top_left_corner = resources()->GetPartBitmap(FRAME_TOP_LEFT_CORNER);
SkBitmap* top_right_corner =
resources()->GetPartBitmap(FRAME_TOP_RIGHT_CORNER);
@@ -502,7 +483,7 @@ void DefaultNonClientView::PaintRestoredFrameBorder(ChromeCanvas* canvas) {
height() - top_left_corner->height() - bottom_left_corner->height());
}
-void DefaultNonClientView::PaintMaximizedFrameBorder(
+void CustomFrameView::PaintMaximizedFrameBorder(
ChromeCanvas* canvas) {
SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE);
canvas->TileImageInt(*top_edge, 0, FrameBorderThickness(), width(),
@@ -513,11 +494,11 @@ void DefaultNonClientView::PaintMaximizedFrameBorder(
SkBitmap* titlebar_bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP);
int edge_height = titlebar_bottom->height() - kClientEdgeThickness;
canvas->TileImageInt(*titlebar_bottom, 0,
- container_->client_view()->y() - edge_height, width(), edge_height);
+ frame_->client_view()->y() - edge_height, width(), edge_height);
}
-void DefaultNonClientView::PaintTitleBar(ChromeCanvas* canvas) {
- WindowDelegate* d = container_->window_delegate();
+void CustomFrameView::PaintTitleBar(ChromeCanvas* canvas) {
+ WindowDelegate* d = frame_->window_delegate();
// It seems like in some conditions we can be asked to paint after the window
// that contains us is WM_DESTROYed. At this point, our delegate is NULL. The
@@ -530,8 +511,8 @@ void DefaultNonClientView::PaintTitleBar(ChromeCanvas* canvas) {
title_bounds_.width(), title_bounds_.height());
}
-void DefaultNonClientView::PaintRestoredClientEdge(ChromeCanvas* canvas) {
- gfx::Rect client_area_bounds = container_->client_view()->bounds();
+void CustomFrameView::PaintRestoredClientEdge(ChromeCanvas* canvas) {
+ gfx::Rect client_area_bounds = frame_->client_view()->bounds();
int client_area_top = client_area_bounds.y();
SkBitmap* top_left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT);
@@ -577,11 +558,11 @@ void DefaultNonClientView::PaintRestoredClientEdge(ChromeCanvas* canvas) {
client_area_top, left->width(), client_area_height);
}
-void DefaultNonClientView::LayoutWindowControls() {
+void CustomFrameView::LayoutWindowControls() {
close_button_->SetImageAlignment(Button::ALIGN_LEFT, Button::ALIGN_BOTTOM);
// Maximized buttons start at window top so that even if their images aren't
// drawn flush with the screen edge, they still obey Fitts' Law.
- bool is_maximized = container_->IsMaximized();
+ bool is_maximized = frame_->IsMaximized();
int frame_thickness = FrameBorderThickness();
int caption_y = is_maximized ? frame_thickness : kCaptionTopSpacing;
int top_extra_height = is_maximized ? kCaptionTopSpacing : 0;
@@ -600,7 +581,7 @@ void DefaultNonClientView::LayoutWindowControls() {
// When the window is restored, we show a maximized button; otherwise, we show
// a restore button.
- bool is_restored = !is_maximized && !container_->IsMinimized();
+ bool is_restored = !is_maximized && !frame_->IsMinimized();
views::Button* invisible_button = is_restored ?
restore_button_ : maximize_button_;
invisible_button->SetVisible(false);
@@ -645,7 +626,7 @@ void DefaultNonClientView::LayoutWindowControls() {
active_resources_->GetPartBitmap(pushed_part));
}
-void DefaultNonClientView::LayoutTitleBar() {
+void CustomFrameView::LayoutTitleBar() {
// Always lay out the icon, even when it's not present, so we can lay out the
// window title based on its position.
int frame_thickness = FrameBorderThickness();
@@ -671,10 +652,10 @@ void DefaultNonClientView::LayoutTitleBar() {
// the remaining space. Because the apparent shape of our border is simpler,
// using the same positioning makes things look slightly uncentered with
// restored windows, so we come up to compensate.
- if (!container_->IsMaximized())
+ if (!frame_->IsMaximized())
icon_y -= kIconRestoredAdjust;
- views::WindowDelegate* d = container_->window_delegate();
+ views::WindowDelegate* d = frame_->window_delegate();
if (!d->ShouldShowWindowIcon())
icon_size = 0;
system_menu_button_->SetBounds(icon_x, icon_y, icon_size, icon_size);
@@ -690,13 +671,18 @@ void DefaultNonClientView::LayoutTitleBar() {
std::max(0, title_right - title_x), title_font_.height());
}
-void DefaultNonClientView::LayoutClientView() {
- container_->client_view()->SetBounds(CalculateClientAreaBounds(width(),
- height()));
+void CustomFrameView::LayoutClientView() {
+ int top_height = NonClientTopBorderHeight();
+ int border_thickness = NonClientBorderThickness();
+ client_view_bounds_.SetRect(
+ border_thickness,
+ top_height,
+ std::max(0, width() - (2 * border_thickness)),
+ std::max(0, height() - top_height - border_thickness));
}
// static
-void DefaultNonClientView::InitClass() {
+void CustomFrameView::InitClass() {
static bool initialized = false;
if (!initialized) {
active_resources_ = new ActiveWindowResources;
@@ -709,3 +695,4 @@ void DefaultNonClientView::InitClass() {
}
} // namespace views
+
diff --git a/chrome/views/default_non_client_view.h b/chrome/views/custom_frame_view.h
index 2c46fca..0a34f2d 100644
--- a/chrome/views/default_non_client_view.h
+++ b/chrome/views/custom_frame_view.h
@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_VIEWS_DEFAULT_NON_CLIENT_VIEW_H_
-#define CHROME_VIEWS_DEFAULT_NON_CLIENT_VIEW_H_
+#ifndef CHROME_VIEWS_CUSTOM_FRAME_VIEW_H_
+#define CHROME_VIEWS_CUSTOM_FRAME_VIEW_H_
-#include "base/basictypes.h"
#include "chrome/views/button.h"
-#include "chrome/views/custom_frame_window.h"
#include "chrome/views/non_client_view.h"
+#include "chrome/views/window.h"
#include "chrome/views/window_resources.h"
namespace gfx{
@@ -21,26 +20,24 @@ class ChromeFont;
namespace views {
-class ClientView;
-
///////////////////////////////////////////////////////////////////////////////
//
-// DefaultNonClientView
+// CustomFrameView
//
-// A ChromeView that provides the "frame" for CustomFrameWindows. This means
+// A ChromeView that provides the non client frame for Windows. This means
// rendering the non-standard window caption, border, and controls.
//
////////////////////////////////////////////////////////////////////////////////
-class DefaultNonClientView : public NonClientView,
- public BaseButton::ButtonListener {
+class CustomFrameView : public NonClientFrameView,
+ public BaseButton::ButtonListener {
public:
- explicit DefaultNonClientView(CustomFrameWindow* container);
- virtual ~DefaultNonClientView();
+ explicit CustomFrameView(Window* frame);
+ virtual ~CustomFrameView();
- // Overridden from views::NonClientView:
- virtual gfx::Rect CalculateClientAreaBounds(int width, int height) const;
- virtual gfx::Size CalculateWindowSizeForClientSize(int width,
- int height) const;
+ // Overridden from views::NonClientFrameView:
+ virtual gfx::Rect GetBoundsForClientView() const;
+ virtual gfx::Rect GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const;
virtual gfx::Point GetSystemMenuPoint() const;
virtual int NonClientHitTest(const gfx::Point& point);
virtual void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask);
@@ -51,7 +48,6 @@ class DefaultNonClientView : public NonClientView,
virtual void Paint(ChromeCanvas* canvas);
virtual void Layout();
virtual gfx::Size GetPreferredSize();
- virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
// BaseButton::ButtonListener implementation:
virtual void ButtonPressed(BaseButton* sender);
@@ -91,14 +87,12 @@ class DefaultNonClientView : public NonClientView,
// Returns the resource collection to be used when rendering the window.
WindowResources* resources() const {
- return container_->is_active() || paint_as_active() ? active_resources_
- : inactive_resources_;
+ return frame_->is_active() || paint_as_active() ? active_resources_
+ : inactive_resources_;
}
- // The View that provides the background for the window, and optionally
- // dialog buttons. Note: the non-client view does _not_ own this view, the
- // container does.
- ClientView* client_view_;
+ // The bounds of the client view, in this view's coordinates.
+ gfx::Rect client_view_bounds_;
// The layout rect of the title, if visible.
gfx::Rect title_bounds_;
@@ -112,7 +106,7 @@ class DefaultNonClientView : public NonClientView,
bool should_show_minmax_buttons_;
// The window that owns this view.
- CustomFrameWindow* container_;
+ Window* frame_;
// Initialize various static resources.
static void InitClass();
@@ -120,9 +114,10 @@ class DefaultNonClientView : public NonClientView,
static WindowResources* inactive_resources_;
static ChromeFont title_font_;
- DISALLOW_COPY_AND_ASSIGN(DefaultNonClientView);
+ DISALLOW_EVIL_CONSTRUCTORS(CustomFrameView);
};
} // namespace views
-#endif // CHROME_VIEWS_DEFAULT_NON_CLIENT_VIEW_H_
+#endif // #ifndef CHROME_VIEWS_CUSTOM_FRAME_VIEW_H_
+
diff --git a/chrome/views/custom_frame_window.cc b/chrome/views/custom_frame_window.cc
deleted file mode 100644
index 0ae6158..0000000
--- a/chrome/views/custom_frame_window.cc
+++ /dev/null
@@ -1,506 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/views/custom_frame_window.h"
-
-#include "base/gfx/point.h"
-#include "base/gfx/size.h"
-#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/common/gfx/path.h"
-#include "chrome/common/l10n_util.h"
-#include "chrome/common/win_util.h"
-#include "chrome/views/client_view.h"
-#include "chrome/views/default_non_client_view.h"
-#include "chrome/views/root_view.h"
-#include "chrome/views/window_delegate.h"
-#include "grit/generated_resources.h"
-
-namespace views {
-
-// A scoping class that prevents a window from being able to redraw in response
-// to invalidations that may occur within it for the lifetime of the object.
-//
-// Why would we want such a thing? Well, it turns out Windows has some
-// "unorthodox" behavior when it comes to painting its non-client areas.
-// Occasionally, Windows will paint portions of the default non-client area
-// right over the top of the custom frame. This is not simply fixed by handling
-// WM_NCPAINT/WM_PAINT, with some investigation it turns out that this
-// rendering is being done *inside* the default implementation of some message
-// handlers and functions:
-// . WM_SETTEXT
-// . WM_SETICON
-// . WM_NCLBUTTONDOWN
-// . EnableMenuItem, called from our WM_INITMENU handler
-// The solution is to handle these messages and call DefWindowProc ourselves,
-// but prevent the window from being able to update itself for the duration of
-// the call. We do this with this class, which automatically calls its
-// associated CustomFrameWindow's lock and unlock functions as it is created
-// and destroyed. See documentation in those methods for the technique used.
-//
-// IMPORTANT: Do not use this scoping object for large scopes or periods of
-// time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh).
-//
-// I would love to hear Raymond Chen's explanation for all this. And maybe a
-// list of other messages that this applies to ;-)
-class CustomFrameWindow::ScopedRedrawLock {
- public:
- explicit ScopedRedrawLock(CustomFrameWindow* window) : window_(window) {
- window_->LockUpdates();
- }
-
- ~ScopedRedrawLock() {
- window_->UnlockUpdates();
- }
-
- private:
- // The window having its style changed.
- CustomFrameWindow* window_;
-};
-
-HCURSOR CustomFrameWindow::resize_cursors_[6];
-
-///////////////////////////////////////////////////////////////////////////////
-// CustomFrameWindow, public:
-
-CustomFrameWindow::CustomFrameWindow(WindowDelegate* window_delegate)
- : Window(window_delegate),
- is_active_(false),
- lock_updates_(false),
- saved_window_style_(0) {
- InitClass();
- non_client_view_ = new DefaultNonClientView(this);
-}
-
-CustomFrameWindow::CustomFrameWindow(WindowDelegate* window_delegate,
- NonClientView* non_client_view)
- : Window(window_delegate) {
- InitClass();
- non_client_view_ = non_client_view;
-}
-
-CustomFrameWindow::~CustomFrameWindow() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// CustomFrameWindow, Window overrides:
-
-void CustomFrameWindow::Init(HWND parent, const gfx::Rect& bounds) {
- // TODO(beng): (Cleanup) Right now, the only way to specify a different
- // non-client view is to subclass this object and provide one
- // by setting this member before calling Init.
- if (!non_client_view_)
- non_client_view_ = new DefaultNonClientView(this);
- Window::Init(parent, bounds);
-
- ResetWindowRegion();
-}
-
-void CustomFrameWindow::UpdateWindowTitle() {
- // Layout winds up causing the title to be re-validated during
- // string measurement.
- non_client_view_->Layout();
- // Must call the base class too so that places like the Task Bar get updated.
- Window::UpdateWindowTitle();
-}
-
-void CustomFrameWindow::UpdateWindowIcon() {
- // The icon will be re-validated during painting.
- non_client_view_->SchedulePaint();
- // Call the base class so that places like the Task Bar get updated.
- Window::UpdateWindowIcon();
-}
-
-void CustomFrameWindow::EnableClose(bool enable) {
- non_client_view_->EnableClose(enable);
- // Make sure the SysMenu changes to reflect this change as well.
- Window::EnableClose(enable);
-}
-
-void CustomFrameWindow::DisableInactiveRendering(bool disable) {
- Window::DisableInactiveRendering(disable);
- non_client_view_->set_paint_as_active(disable);
- if (!disable)
- non_client_view_->SchedulePaint();
-}
-
-void CustomFrameWindow::SizeWindowToDefault() {
- gfx::Size pref = client_view()->GetPreferredSize();
- DCHECK(pref.width() > 0 && pref.height() > 0);
- gfx::Size window_size =
- non_client_view_->CalculateWindowSizeForClientSize(pref.width(),
- pref.height());
- win_util::CenterAndSizeWindow(owning_window(), GetHWND(),
- window_size.ToSIZE(), false);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// CustomFrameWindow, WidgetWin overrides:
-
-static void EnableMenuItem(HMENU menu, UINT command, bool enabled) {
- UINT flags = MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
- EnableMenuItem(menu, command, flags);
-}
-
-void CustomFrameWindow::OnInitMenu(HMENU menu) {
- bool is_minimized = IsMinimized();
- bool is_maximized = IsMaximized();
- bool is_restored = !is_minimized && !is_maximized;
-
- ScopedRedrawLock lock(this);
- EnableMenuItem(menu, SC_RESTORE, !is_restored);
- EnableMenuItem(menu, SC_MOVE, is_restored);
- EnableMenuItem(menu, SC_SIZE, window_delegate()->CanResize() && is_restored);
- EnableMenuItem(menu, SC_MAXIMIZE,
- window_delegate()->CanMaximize() && !is_maximized);
- EnableMenuItem(menu, SC_MINIMIZE,
- window_delegate()->CanMaximize() && !is_minimized);
-}
-
-void CustomFrameWindow::OnMouseLeave() {
- bool process_mouse_exited = true;
- POINT pt;
- if (GetCursorPos(&pt)) {
- LRESULT ht_component =
- ::SendMessage(GetHWND(), WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y));
- if (ht_component != HTNOWHERE) {
- // If the mouse moved into a part of the window's non-client area, then
- // don't send a mouse exited event since the mouse is still within the
- // bounds of the ChromeView that's rendering the frame. Note that we do
- // _NOT_ do this for windows with native frames, since in that case the
- // mouse really will have left the bounds of the RootView.
- process_mouse_exited = false;
- }
- }
-
- if (process_mouse_exited)
- ProcessMouseExited();
-}
-
-LRESULT CustomFrameWindow::OnNCActivate(BOOL active) {
- is_active_ = !!active;
-
- // We can get WM_NCACTIVATE before we're actually visible. If we're not
- // visible, no need to paint.
- if (IsWindowVisible(GetHWND())) {
- non_client_view_->SchedulePaint();
- // We need to force a paint now, as a user dragging a window will block
- // painting operations while the move is in progress.
- PaintNow(root_view_->GetScheduledPaintRect());
- }
-
- // Defering to our parent as it is important that the NCActivate message gets
- // DefProc'ed or the task bar won't show our process as active.
- // See bug http://crbug.com/4513.
- return Window::OnNCActivate(active);
-}
-
-LRESULT CustomFrameWindow::OnNCCalcSize(BOOL mode, LPARAM l_param) {
- // We need to repaint all when the window bounds change.
- return WVR_REDRAW;
-}
-
-LRESULT CustomFrameWindow::OnNCHitTest(const CPoint& point) {
- // NC points are in screen coordinates.
- CPoint temp = point;
- MapWindowPoints(HWND_DESKTOP, GetHWND(), &temp, 1);
- return non_client_view_->NonClientHitTest(gfx::Point(temp.x, temp.y));
-}
-
-struct ClipState {
- // The window being painted.
- HWND parent;
-
- // DC painting to.
- HDC dc;
-
- // Origin of the window in terms of the screen.
- int x;
- int y;
-};
-
-// See comments in OnNCPaint for details of this function.
-static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) {
- ClipState* clip_state = reinterpret_cast<ClipState*>(param);
- if (GetParent(window) == clip_state->parent && IsWindowVisible(window)) {
- RECT bounds;
- GetWindowRect(window, &bounds);
- ExcludeClipRect(clip_state->dc,
- bounds.left - clip_state->x,
- bounds.top - clip_state->y,
- bounds.right - clip_state->x,
- bounds.bottom - clip_state->y);
- }
- return TRUE;
-}
-
-void CustomFrameWindow::OnNCPaint(HRGN rgn) {
- // We have an NC region and need to paint it. We expand the NC region to
- // include the dirty region of the root view. This is done to minimize
- // paints.
- CRect window_rect;
- GetWindowRect(&window_rect);
-
- if (window_rect.Width() != root_view_->width() ||
- window_rect.Height() != root_view_->height()) {
- // If the size of the window differs from the size of the root view it
- // means we're being asked to paint before we've gotten a WM_SIZE. This can
- // happen when the user is interactively resizing the window. To avoid
- // mass flickering we don't do anything here. Once we get the WM_SIZE we'll
- // reset the region of the window which triggers another WM_NCPAINT and
- // all is well.
- return;
- }
-
- CRect dirty_region;
- // A value of 1 indicates paint all.
- if (!rgn || rgn == reinterpret_cast<HRGN>(1)) {
- dirty_region = CRect(0, 0, window_rect.Width(), window_rect.Height());
- } else {
- RECT rgn_bounding_box;
- GetRgnBox(rgn, &rgn_bounding_box);
- if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect))
- return; // Dirty region doesn't intersect window bounds, bale.
-
- // rgn_bounding_box is in screen coordinates. Map it to window coordinates.
- OffsetRect(&dirty_region, -window_rect.left, -window_rect.top);
- }
-
- // In theory GetDCEx should do what we want, but I couldn't get it to work.
- // In particular the docs mentiond DCX_CLIPCHILDREN, but as far as I can tell
- // it doesn't work at all. So, instead we get the DC for the window then
- // manually clip out the children.
- HDC dc = GetWindowDC(GetHWND());
- ClipState clip_state;
- clip_state.x = window_rect.left;
- clip_state.y = window_rect.top;
- clip_state.parent = GetHWND();
- clip_state.dc = dc;
- EnumChildWindows(GetHWND(), &ClipDCToChild,
- reinterpret_cast<LPARAM>(&clip_state));
-
- RootView* root_view = GetRootView();
- CRect old_paint_region = root_view->GetScheduledPaintRectConstrainedToSize();
-
- if (!old_paint_region.IsRectEmpty()) {
- // The root view has a region that needs to be painted. Include it in the
- // region we're going to paint.
-
- CRect tmp = dirty_region;
- UnionRect(&dirty_region, &tmp, &old_paint_region);
- }
-
- root_view->SchedulePaint(gfx::Rect(dirty_region), false);
-
- // ChromeCanvasPaints destructor does the actual painting. As such, wrap the
- // following in a block to force paint to occur so that we can release the dc.
- {
- ChromeCanvasPaint canvas(dc, opaque(), dirty_region.left, dirty_region.top,
- dirty_region.Width(), dirty_region.Height());
-
- root_view->ProcessPaint(&canvas);
- }
-
- ReleaseDC(GetHWND(), dc);
-}
-
-void CustomFrameWindow::OnNCLButtonDown(UINT ht_component,
- const CPoint& point) {
- switch (ht_component) {
- case HTCLOSE:
- case HTMINBUTTON:
- case HTMAXBUTTON: {
- // When the mouse is pressed down in these specific non-client areas, we
- // need to tell the RootView to send the mouse pressed event (which sets
- // capture, allowing subsequent WM_LBUTTONUP (note, _not_ WM_NCLBUTTONUP)
- // to fire so that the appropriate WM_SYSCOMMAND can be sent by the
- // applicable button's ButtonListener. We _have_ to do this this way
- // rather than letting Windows just send the syscommand itself (as would
- // happen if we never did this dance) because for some insane reason
- // DefWindowProc for WM_NCLBUTTONDOWN also renders the pressed window
- // control button appearance, in the Windows classic style, over our
- // view! Ick! By handling this message we prevent Windows from doing this
- // undesirable thing, but that means we need to roll the sys-command
- // handling ourselves.
- ProcessNCMousePress(point, MK_LBUTTON);
- return;
- }
- default:
- Window::OnNCLButtonDown(ht_component, point);
- /*
- if (!IsMsgHandled()) {
- // Window::OnNCLButtonDown set the message as unhandled. This normally
- // means WidgetWin::ProcessWindowMessage will pass it to
- // DefWindowProc. Sadly, DefWindowProc for WM_NCLBUTTONDOWN does weird
- // non-client painting, so we need to call it directly here inside a
- // scoped update lock.
- ScopedRedrawLock lock(this);
- DefWindowProc(GetHWND(), WM_NCLBUTTONDOWN, ht_component,
- MAKELPARAM(point.x, point.y));
- SetMsgHandled(TRUE);
- }
- */
- break;
- }
-}
-
-LRESULT CustomFrameWindow::OnNCUAHDrawCaption(UINT msg, WPARAM w_param,
- LPARAM l_param) {
- // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
- // an explanation about why we need to handle this message.
- SetMsgHandled(TRUE);
- return 0;
-}
-
-LRESULT CustomFrameWindow::OnNCUAHDrawFrame(UINT msg, WPARAM w_param,
- LPARAM l_param) {
- // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
- // an explanation about why we need to handle this message.
- SetMsgHandled(TRUE);
- return 0;
-}
-
-LRESULT CustomFrameWindow::OnSetCursor(HWND window, UINT hittest_code,
- UINT message) {
- int index = RC_NORMAL;
- switch (hittest_code) {
- case HTTOP:
- case HTBOTTOM:
- index = RC_VERTICAL;
- break;
- case HTTOPLEFT:
- case HTBOTTOMRIGHT:
- index = RC_NWSE;
- break;
- case HTTOPRIGHT:
- case HTBOTTOMLEFT:
- index = RC_NESW;
- break;
- case HTLEFT:
- case HTRIGHT:
- index = RC_HORIZONTAL;
- break;
- case HTCAPTION:
- case HTCLIENT:
- index = RC_NORMAL;
- break;
- }
- SetCursor(resize_cursors_[index]);
- return 0;
-}
-
-LRESULT CustomFrameWindow::OnSetIcon(UINT size_type, HICON new_icon) {
- ScopedRedrawLock lock(this);
- return DefWindowProc(GetHWND(), WM_SETICON, size_type,
- reinterpret_cast<LPARAM>(new_icon));
-}
-
-LRESULT CustomFrameWindow::OnSetText(const wchar_t* text) {
- ScopedRedrawLock lock(this);
- return DefWindowProc(GetHWND(), WM_SETTEXT, NULL,
- reinterpret_cast<LPARAM>(text));
-}
-
-void CustomFrameWindow::OnSize(UINT param, const CSize& size) {
- Window::OnSize(param, size);
-
- // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've
- // invoked OnSize we ensure the RootView has been layed out.
- ResetWindowRegion();
-}
-
-void CustomFrameWindow::OnSysCommand(UINT notification_code, CPoint click) {
- // Windows uses the 4 lower order bits of |notification_code| for type-
- // specific information so we must exclude this when comparing.
- static const int sc_mask = 0xFFF0;
- if ((notification_code & sc_mask) == SC_MINIMIZE ||
- (notification_code & sc_mask) == SC_MAXIMIZE ||
- (notification_code & sc_mask) == SC_RESTORE) {
- non_client_view_->ResetWindowControls();
- } else if ((notification_code & sc_mask) == SC_MOVE ||
- (notification_code & sc_mask) == SC_SIZE) {
- if (lock_updates_) {
- // We were locked, before entering a resize or move modal loop. Now that
- // we've begun to move the window, we need to unlock updates so that the
- // sizing/moving feedback can be continuous.
- UnlockUpdates();
- }
- }
- Window::OnSysCommand(notification_code, click);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// CustomFrameWindow, private:
-
-// static
-void CustomFrameWindow::InitClass() {
- static bool initialized = false;
- if (!initialized) {
- resize_cursors_[RC_NORMAL] = LoadCursor(NULL, IDC_ARROW);
- resize_cursors_[RC_VERTICAL] = LoadCursor(NULL, IDC_SIZENS);
- resize_cursors_[RC_HORIZONTAL] = LoadCursor(NULL, IDC_SIZEWE);
- resize_cursors_[RC_NESW] = LoadCursor(NULL, IDC_SIZENESW);
- resize_cursors_[RC_NWSE] = LoadCursor(NULL, IDC_SIZENWSE);
- initialized = true;
- }
-}
-
-void CustomFrameWindow::LockUpdates() {
- lock_updates_ = true;
- saved_window_style_ = GetWindowLong(GetHWND(), GWL_STYLE);
- SetWindowLong(GetHWND(), GWL_STYLE, saved_window_style_ & ~WS_VISIBLE);
-}
-
-void CustomFrameWindow::UnlockUpdates() {
- SetWindowLong(GetHWND(), GWL_STYLE, saved_window_style_);
- lock_updates_ = false;
-}
-
-void CustomFrameWindow::ResetWindowRegion() {
- // Changing the window region is going to force a paint. Only change the
- // window region if the region really differs.
- HRGN current_rgn = CreateRectRgn(0, 0, 0, 0);
- int current_rgn_result = GetWindowRgn(GetHWND(), current_rgn);
-
- CRect window_rect;
- GetWindowRect(&window_rect);
- HRGN new_region;
- if (IsMaximized()) {
- HMONITOR monitor = MonitorFromWindow(GetHWND(), MONITOR_DEFAULTTONEAREST);
- MONITORINFO mi;
- mi.cbSize = sizeof mi;
- GetMonitorInfo(monitor, &mi);
- CRect work_rect = mi.rcWork;
- work_rect.OffsetRect(-window_rect.left, -window_rect.top);
- new_region = CreateRectRgnIndirect(&work_rect);
- } else {
- gfx::Path window_mask;
- non_client_view_->GetWindowMask(gfx::Size(window_rect.Width(),
- window_rect.Height()),
- &window_mask);
- new_region = window_mask.CreateHRGN();
- }
-
- if (current_rgn_result == ERROR || !EqualRgn(current_rgn, new_region)) {
- // SetWindowRgn takes ownership of the HRGN created by CreateHRGN.
- SetWindowRgn(new_region, TRUE);
- } else {
- DeleteObject(new_region);
- }
-
- DeleteObject(current_rgn);
-}
-
-void CustomFrameWindow::ProcessNCMousePress(const CPoint& point, int flags) {
- CPoint temp = point;
- MapWindowPoints(HWND_DESKTOP, GetHWND(), &temp, 1);
- UINT message_flags = 0;
- if ((GetKeyState(VK_CONTROL) & 0x80) == 0x80)
- message_flags |= MK_CONTROL;
- if ((GetKeyState(VK_SHIFT) & 0x80) == 0x80)
- message_flags |= MK_SHIFT;
- message_flags |= flags;
- ProcessMousePressed(temp, message_flags, false, false);
-}
-
-} // namespace views
diff --git a/chrome/views/custom_frame_window.h b/chrome/views/custom_frame_window.h
deleted file mode 100644
index f5b6334..0000000
--- a/chrome/views/custom_frame_window.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_VIEWS_CUSTOM_FRAME_WINDOW_H__
-#define CHROME_VIEWS_CUSTOM_FRAME_WINDOW_H__
-
-#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/views/window.h"
-#include "chrome/views/window_delegate.h"
-
-namespace views {
-
-class NonClientView;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// CustomFrameWindow
-//
-// A CustomFrameWindow is a Window subclass that implements the Chrome-style
-// window frame used on Windows XP and Vista without DWM Composition.
-// See documentation in window.h for more information about the capabilities
-// of this window type.
-//
-////////////////////////////////////////////////////////////////////////////////
-class CustomFrameWindow : public Window {
- public:
- explicit CustomFrameWindow(WindowDelegate* window_delegate);
- CustomFrameWindow(WindowDelegate* window_delegate,
- NonClientView* non_client_view);
- virtual ~CustomFrameWindow();
-
- // Returns whether or not the frame is active.
- bool is_active() const { return is_active_; }
-
- // Overridden from Window:
- virtual void Init(HWND parent, const gfx::Rect& bounds);
- virtual void UpdateWindowTitle();
- virtual void UpdateWindowIcon();
-
- protected:
- // Overridden from Window:
- virtual void SizeWindowToDefault();
- virtual void EnableClose(bool enable);
- virtual void DisableInactiveRendering(bool disable);
-
- // Overridden from WidgetWin:
- virtual void OnInitMenu(HMENU menu);
- virtual void OnMouseLeave();
- virtual LRESULT OnNCActivate(BOOL active);
- virtual LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param);
- virtual LRESULT OnNCHitTest(const CPoint& point);
- virtual void OnNCPaint(HRGN rgn);
- virtual void OnNCLButtonDown(UINT ht_component, const CPoint& point);
- virtual LRESULT OnNCUAHDrawCaption(UINT msg, WPARAM w_param, LPARAM l_param);
- virtual LRESULT OnNCUAHDrawFrame(UINT msg, WPARAM w_param, LPARAM l_param);
- virtual LRESULT OnSetCursor(HWND window, UINT hittest_code, UINT message);
- virtual LRESULT OnSetIcon(UINT size_type, HICON new_icon);
- virtual LRESULT OnSetText(const wchar_t* text);
- virtual void OnSize(UINT param, const CSize& size);
- virtual void OnSysCommand(UINT notification_code, CPoint click);
-
- private:
- class ScopedRedrawLock;
-
- // Lock or unlock the window from being able to redraw itself in response to
- // updates to its invalid region.
- void LockUpdates();
- void UnlockUpdates();
-
- // Resets the window region.
- void ResetWindowRegion();
-
- // Converts a non-client mouse down message to a regular ChromeViews event
- // and handle it. |point| is the mouse position of the message in screen
- // coords. |flags| are flags that would be passed with a WM_L/M/RBUTTON*
- // message and relate to things like which button was pressed. These are
- // combined with flags relating to the current key state.
- void ProcessNCMousePress(const CPoint& point, int flags);
-
- // True if this window is the active top level window.
- bool is_active_;
-
- // True if updates to this window are currently locked.
- bool lock_updates_;
-
- // The window styles of the window before updates were locked.
- DWORD saved_window_style_;
-
- // Static resource initialization.
- static void InitClass();
- enum ResizeCursor {
- RC_NORMAL = 0, RC_VERTICAL, RC_HORIZONTAL, RC_NESW, RC_NWSE
- };
- static HCURSOR resize_cursors_[6];
-
- DISALLOW_EVIL_CONSTRUCTORS(CustomFrameWindow);
-};
-
-} // namespace views
-
-#endif // CHROME_VIEWS_CUSTOM_FRAME_WINDOW_H__
-
diff --git a/chrome/views/native_frame_view.cc b/chrome/views/native_frame_view.cc
new file mode 100644
index 0000000..04f3448
--- /dev/null
+++ b/chrome/views/native_frame_view.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/views/native_frame_view.h"
+
+#include "chrome/views/window.h"
+
+namespace views {
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeFrameView, public:
+
+NativeFrameView::NativeFrameView(Window* frame)
+ : NonClientFrameView(),
+ frame_(frame) {
+}
+
+NativeFrameView::~NativeFrameView() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeFrameView, NonClientFrameView overrides:
+
+gfx::Rect NativeFrameView::GetBoundsForClientView() const {
+ return gfx::Rect(0, 0, width(), height());
+}
+
+gfx::Rect NativeFrameView::GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const {
+ RECT rect = client_bounds.ToRECT();
+ AdjustWindowRectEx(&rect, frame_->window_style(), FALSE,
+ frame_->window_ex_style());
+ return gfx::Rect(rect);
+}
+
+gfx::Point NativeFrameView::GetSystemMenuPoint() const {
+ POINT temp = {0, -kFrameShadowThickness };
+ MapWindowPoints(frame_->GetHWND(), HWND_DESKTOP, &temp, 1);
+ return gfx::Point(temp);
+}
+
+int NativeFrameView::NonClientHitTest(const gfx::Point& point) {
+ return HTNOWHERE;
+}
+
+void NativeFrameView::GetWindowMask(const gfx::Size& size,
+ gfx::Path* window_mask) {
+ // Nothing to do, we use the default window mask.
+}
+
+void NativeFrameView::EnableClose(bool enable) {
+ // Nothing to do, handled automatically by Window.
+}
+
+void NativeFrameView::ResetWindowControls() {
+ // Nothing to do.
+}
+
+} // namespace views
+
diff --git a/chrome/views/native_frame_view.h b/chrome/views/native_frame_view.h
new file mode 100644
index 0000000..aa599ff
--- /dev/null
+++ b/chrome/views/native_frame_view.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_VIEWS_NATIVE_FRAME_VIEW_H_
+#define CHROME_VIEWS_NATIVE_FRAME_VIEW_H_
+
+#include "chrome/views/non_client_view.h"
+
+namespace views {
+
+class NativeFrameView : public NonClientFrameView {
+ public:
+ explicit NativeFrameView(Window* frame);
+ virtual ~NativeFrameView();
+
+ // NonClientFrameView overrides:
+ virtual gfx::Rect GetBoundsForClientView() const;
+ virtual gfx::Rect GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const;
+ virtual gfx::Point GetSystemMenuPoint() const;
+ virtual int NonClientHitTest(const gfx::Point& point);
+ virtual void GetWindowMask(const gfx::Size& size,
+ gfx::Path* window_mask);
+ virtual void EnableClose(bool enable);
+ virtual void ResetWindowControls();
+
+ private:
+ // Our containing frame.
+ Window* frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeFrameView);
+};
+
+} // namespace views
+
+#endif // #ifndef CHROME_VIEWS_NATIVE_FRAME_VIEW_H_
+
diff --git a/chrome/views/non_client_view.cc b/chrome/views/non_client_view.cc
index bb89cb5..166042d 100644
--- a/chrome/views/non_client_view.cc
+++ b/chrome/views/non_client_view.cc
@@ -3,20 +3,46 @@
// found in the LICENSE file.
#include "chrome/views/non_client_view.h"
-#include "chrome/views/widget.h"
+
+#include "chrome/common/win_util.h"
+#include "chrome/views/root_view.h"
+#include "chrome/views/window.h"
namespace views {
-const int NonClientView::kFrameShadowThickness = 1;
-const int NonClientView::kClientEdgeThickness = 1;
+const int NonClientFrameView::kFrameShadowThickness = 1;
+const int NonClientFrameView::kClientEdgeThickness = 1;
+
+// The frame view and the client view are always at these specific indices,
+// because the RootView message dispatch sends messages to items higher in the
+// z-order first and we always want the client view to have first crack at
+// handling mouse messages.
+static const int kFrameViewIndex = 0;
+static const int kClientViewIndex = 1;
////////////////////////////////////////////////////////////////////////////////
// NonClientView, public:
-NonClientView::NonClientView() : paint_as_active_(false) {
+NonClientView::NonClientView(Window* frame)
+ : frame_(frame),
+ client_view_(NULL),
+ use_native_frame_(win_util::ShouldUseVistaFrame()) {
}
NonClientView::~NonClientView() {
+ // This value may have been reset before the window hierarchy shuts down,
+ // so we need to manually remove it.
+ RemoveChildView(frame_view_.get());
+}
+
+void NonClientView::SetFrameView(NonClientFrameView* frame_view) {
+ // See comment in header about ownership.
+ frame_view->SetParentOwned(false);
+ if (frame_view_.get())
+ RemoveChildView(frame_view_.get());
+ frame_view_.reset(frame_view);
+ if (GetParent())
+ AddChildView(kFrameViewIndex, frame_view_.get());
}
bool NonClientView::CanClose() const {
@@ -27,41 +53,84 @@ void NonClientView::WindowClosing() {
client_view_->WindowClosing();
}
+void NonClientView::SystemThemeChanged() {
+ // The window may try to paint in SetUseNativeFrame, and as a result it can
+ // get into a state where it is very unhappy with itself - rendering black
+ // behind the entire client area. This is because for some reason the
+ // SkPorterDuff::kClear_mode erase done in the RootView thinks the window is
+ // still opaque. So, to work around this we hide the window as soon as we can
+ // (now), saving off its placement so it can be properly restored once
+ // everything has settled down.
+ WINDOWPLACEMENT saved_window_placement;
+ saved_window_placement.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(frame_->GetHWND(), &saved_window_placement);
+ frame_->Hide();
+
+ SetUseNativeFrame(win_util::ShouldUseVistaFrame());
+
+ // Now that we've updated the frame, we'll want to restore our saved placement
+ // since the display should have settled down and we can be properly rendered.
+ SetWindowPlacement(frame_->GetHWND(), &saved_window_placement);
+}
+
+void NonClientView::SetUseNativeFrame(bool use_native_frame) {
+ use_native_frame_ = use_native_frame;
+ SetFrameView(frame_->CreateFrameViewForWindow());
+ GetRootView()->ThemeChanged();
+ Layout();
+ SchedulePaint();
+ frame_->UpdateFrameAfterFrameChange();
+}
+
bool NonClientView::UseNativeFrame() const {
- return true;
+ // The frame view may always require a custom frame, e.g. Constrained Windows.
+ bool always_use_custom_frame =
+ frame_view_.get() && frame_view_->AlwaysUseCustomFrame();
+ return !always_use_custom_frame && use_native_frame_;
}
-gfx::Rect NonClientView::CalculateClientAreaBounds(int width,
- int height) const {
- return gfx::Rect();
+void NonClientView::DisableInactiveRendering(bool disable) {
+ frame_view_->DisableInactiveRendering(disable);
}
-gfx::Size NonClientView::CalculateWindowSizeForClientSize(int width,
- int height) const {
- return gfx::Size();
+gfx::Rect NonClientView::GetWindowBoundsForClientBounds(
+ const gfx::Rect client_bounds) const {
+ return frame_view_->GetWindowBoundsForClientBounds(client_bounds);
}
gfx::Point NonClientView::GetSystemMenuPoint() const {
- CPoint temp(0, -kFrameShadowThickness);
- MapWindowPoints(GetWidget()->GetHWND(), HWND_DESKTOP, &temp, 1);
- return gfx::Point(temp);
+ return frame_view_->GetSystemMenuPoint();
}
int NonClientView::NonClientHitTest(const gfx::Point& point) {
- return client_view_->NonClientHitTest(point);
+ // Sanity check.
+ if (!bounds().Contains(point))
+ return HTNOWHERE;
+
+ // The ClientView gets first crack, since it overlays the NonClientFrameView
+ // in the display stack.
+ int frame_component = client_view_->NonClientHitTest(point);
+ if (frame_component != HTNOWHERE)
+ return frame_component;
+
+ // Finally ask the NonClientFrameView. It's at the back of the display stack
+ // so it gets asked last.
+ return frame_view_->NonClientHitTest(point);
}
void NonClientView::GetWindowMask(const gfx::Size& size,
gfx::Path* window_mask) {
+ frame_view_->GetWindowMask(size, window_mask);
}
void NonClientView::EnableClose(bool enable) {
+ frame_view_->EnableClose(enable);
}
void NonClientView::ResetWindowControls() {
+ frame_view_->ResetWindowControls();
}
-
////////////////////////////////////////////////////////////////////////////////
// NonClientView, View overrides:
@@ -70,26 +139,34 @@ gfx::Size NonClientView::GetPreferredSize() {
}
void NonClientView::Layout() {
- client_view_->SetBounds(0, 0, width(), height());
+ // First layout the NonClientFrameView, which determines the size of the
+ // ClientView...
+ frame_view_->SetBounds(0, 0, width(), height());
+
+ // Then layout the ClientView, using those bounds.
+ client_view_->SetBounds(frame_view_->GetBoundsForClientView());
}
void NonClientView::ViewHierarchyChanged(bool is_add, View* parent,
View* child) {
- // Add our Client View as we are added to the Widget so that if we are
- // subsequently resized all the parent-child relationships are established.
- if (is_add && GetWidget() && child == this)
- AddChildView(client_view_);
+ // Add our two child views here as we are added to the Widget so that if we
+ // are subsequently resized all the parent-child relationships are
+ // established.
+ if (is_add && GetWidget() && child == this) {
+ AddChildView(kFrameViewIndex, frame_view_.get());
+ AddChildView(kClientViewIndex, client_view_);
+ }
}
////////////////////////////////////////////////////////////////////////////////
-// NonClientView, protected:
-
-int NonClientView::GetHTComponentForFrame(const gfx::Point& point,
- int top_resize_border_height,
- int resize_border_thickness,
- int top_resize_corner_height,
- int resize_corner_width,
- bool can_resize) {
+// NonClientFrameView, protected:
+
+int NonClientFrameView::GetHTComponentForFrame(const gfx::Point& point,
+ int top_resize_border_height,
+ int resize_border_thickness,
+ int top_resize_corner_height,
+ int resize_corner_width,
+ bool can_resize) {
// Tricky: In XP, native behavior is to return HTTOPLEFT and HTTOPRIGHT for
// a |resize_corner_size|-length strip of both the side and top borders, but
// only to return HTBOTTOMLEFT/HTBOTTOMRIGHT along the bottom border + corner
diff --git a/chrome/views/non_client_view.h b/chrome/views/non_client_view.h
index 1887c2e..f801d6f 100644
--- a/chrome/views/non_client_view.h
+++ b/chrome/views/non_client_view.h
@@ -5,6 +5,7 @@
#ifndef CHROME_VIEWS_NON_CLIENT_VIEW_H_
#define CHROME_VIEWS_NON_CLIENT_VIEW_H_
+#include "base/task.h"
#include "chrome/views/view.h"
#include "chrome/views/client_view.h"
@@ -14,21 +15,15 @@ class Path;
namespace views {
-///////////////////////////////////////////////////////////////////////////////
-// NonClientView
-//
-// An object implementing the NonClientView interface is a View that provides
-// the "non-client" areas of a window. This is the area that typically
-// encompasses the window frame - title bar, sizing borders and window
-// controls. This interface provides methods that allow a specific
-// presentation to define non-client areas for windows hit testing, the shape
-// of the window, and other window-related information.
+////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameView
//
-class NonClientView : public View {
+// An object that subclasses NonClientFrameView is a View that renders and
+// responds to events within the frame portions of the non-client area of a
+// window. This view does _not_ contain the ClientView, but rather is a sibling
+// of it.
+class NonClientFrameView : public views::View {
public:
- NonClientView();
- virtual ~NonClientView();
-
// Various edges of the frame border have a 1 px shadow along their edges; in
// a few cases we shift elements based on this amount for visual appeal.
static const int kFrameShadowThickness;
@@ -36,6 +31,99 @@ class NonClientView : public View {
// frame border.
static const int kClientEdgeThickness;
+ void DisableInactiveRendering(bool disable) {
+ paint_as_active_ = disable;
+ if (!paint_as_active_)
+ SchedulePaint();
+ }
+
+ // Returns the bounds (in this View's parent's coordinates) that the client
+ // view should be laid out within.
+ virtual gfx::Rect GetBoundsForClientView() const = 0;
+
+ // Returns true if this FrameView should always use the custom frame,
+ // regardless of the system settings. An example is the Constrained Window,
+ // which is a child window and must always provide its own frame.
+ virtual bool AlwaysUseCustomFrame() const { return false; }
+
+ virtual gfx::Rect GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const = 0;
+ virtual gfx::Point GetSystemMenuPoint() const = 0;
+ virtual int NonClientHitTest(const gfx::Point& point) = 0;
+ virtual void GetWindowMask(const gfx::Size& size,
+ gfx::Path* window_mask) = 0;
+ virtual void EnableClose(bool enable) = 0;
+ virtual void ResetWindowControls() = 0;
+
+ protected:
+ NonClientFrameView() : paint_as_active_(false) {}
+
+
+ // Helper for non-client view implementations to determine which area of the
+ // window border the specified |point| falls within. The other parameters are
+ // the size of the sizing edges, and whether or not the window can be
+ // resized.
+ int GetHTComponentForFrame(const gfx::Point& point,
+ int top_resize_border_height,
+ int resize_border_thickness,
+ int top_resize_corner_height,
+ int resize_corner_width,
+ bool can_resize);
+
+ // Accessor for paint_as_active_.
+ bool paint_as_active() const { return paint_as_active_; }
+
+ private:
+ // True when the non-client view should always be rendered as if the window
+ // were active, regardless of whether or not the top level window actually
+ // is active.
+ bool paint_as_active_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// NonClientView
+//
+// The NonClientView is the logical root of all Views contained within a
+// Window, except for the RootView which is its parent and of which it is the
+// sole child. The NonClientView has two children, the NonClientFrameView which
+// is responsible for painting and responding to events from the non-client
+// portions of the window, and the ClientView, which is responsible for the
+// same for the client area of the window:
+//
+// +- views::Window ------------------------------------+
+// | +- views::RootView ------------------------------+ |
+// | | +- views::NonClientView ---------------------+ | |
+// | | | +- views::NonClientFrameView subclass ---+ | | |
+// | | | | | | | |
+// | | | | << all painting and event receiving >> | | | |
+// | | | | << of the non-client areas of a >> | | | |
+// | | | | << views::Window. >> | | | |
+// | | | | | | | |
+// | | | +----------------------------------------+ | | |
+// | | | +- views::ClientView or subclass --------+ | | |
+// | | | | | | | |
+// | | | | << all painting and event receiving >> | | | |
+// | | | | << of the client areas of a >> | | | |
+// | | | | << views::Window. >> | | | |
+// | | | | | | | |
+// | | | +----------------------------------------+ | | |
+// | | +--------------------------------------------+ | |
+// | +------------------------------------------------+ |
+// +----------------------------------------------------+
+//
+// The NonClientFrameView and ClientView are siblings because due to theme
+// changes the NonClientFrameView may be replaced with different
+// implementations (e.g. during the switch from DWM/Aero-Glass to Vista Basic/
+// Classic rendering).
+//
+class NonClientView : public View {
+ public:
+ explicit NonClientView(Window* frame);
+ virtual ~NonClientView();
+
+ // Replaces the current NonClientFrameView (if any) with the specified one.
+ void SetFrameView(NonClientFrameView* frame_view);
+
// Returns true if the ClientView determines that the containing window can be
// closed, false otherwise.
bool CanClose() const;
@@ -43,48 +131,52 @@ class NonClientView : public View {
// Called by the containing Window when it is closed.
void WindowClosing();
+ // Called by the window when it receives a theme changed notification. Changes
+ // the content of the NonClientView to match what is required for the current
+ // system theme.
+ void SystemThemeChanged();
+
+ // Changes the frame from native to custom depending on the value of
+ // |use_native_frame|.
+ void SetUseNativeFrame(bool use_native_frame);
+
// Returns true if the native window frame should be used, false if the
// NonClientView provides its own frame implementation.
bool UseNativeFrame() const;
- // Calculates the bounds of the client area of the window assuming the
- // window is sized to |width| and |height|.
- virtual gfx::Rect CalculateClientAreaBounds(int width, int height) const;
+ // Prevents the window from being rendered as deactivated when |disable| is
+ // true, until called with |disable| false. Used when a sub-window is to be
+ // shown that shouldn't visually de-activate the window.
+ // Subclasses can override this to perform additional actions when this value
+ // changes.
+ void DisableInactiveRendering(bool disable);
- // Calculates the size of window required to display a client area of the
- // specified width and height.
- virtual gfx::Size CalculateWindowSizeForClientSize(int width,
- int height) const;
+ // Returns the bounds of the window required to display the content area at
+ // the specified bounds.
+ gfx::Rect GetWindowBoundsForClientBounds(const gfx::Rect client_bounds) const;
// Returns the point, in screen coordinates, where the system menu should
// be shown so it shows up anchored to the system menu icon.
- virtual gfx::Point GetSystemMenuPoint() const;
+ gfx::Point GetSystemMenuPoint() const;
// Determines the windows HT* code when the mouse cursor is at the
// specified point, in window coordinates.
- virtual int NonClientHitTest(const gfx::Point& point);
+ int NonClientHitTest(const gfx::Point& point);
// Returns a mask to be used to clip the top level window for the given
// size. This is used to create the non-rectangular window shape.
- virtual void GetWindowMask(const gfx::Size& size,
- gfx::Path* window_mask);
+ void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask);
// Toggles the enable state for the Close button (and the Close menu item in
// the system menu).
- virtual void EnableClose(bool enable);
+ void EnableClose(bool enable);
// Tells the window controls as rendered by the NonClientView to reset
// themselves to a normal state. This happens in situations where the
// containing window does not receive a normal sequences of messages that
// would lead to the controls returning to this normal state naturally, e.g.
// when the window is maximized, minimized or restored.
- virtual void ResetWindowControls();
-
- // Prevents the non-client view from rendering as inactive when called with
- // |disable| true, until called with false.
- void set_paint_as_active(bool paint_as_active) {
- paint_as_active_ = paint_as_active;
- }
+ void ResetWindowControls();
// Get/Set client_view property.
ClientView* client_view() const { return client_view_; }
@@ -100,30 +192,24 @@ class NonClientView : public View {
// NonClientView, View overrides:
virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
- // Helper for non-client view implementations to determine which area of the
- // window border the specified |point| falls within. The other parameters are
- // the size of the sizing edges, and whether or not the window can be
- // resized.
- int GetHTComponentForFrame(const gfx::Point& point,
- int top_resize_border_height,
- int resize_border_thickness,
- int top_resize_corner_height,
- int resize_corner_width,
- bool can_resize);
-
- // Accessor for paint_as_active_.
- bool paint_as_active() const { return paint_as_active_; }
-
private:
+ // The frame that hosts this NonClientView.
+ Window* frame_;
+
// A ClientView object or subclass, responsible for sizing the contents view
// of the window, hit testing and perhaps other tasks depending on the
// implementation.
ClientView* client_view_;
- // True when the non-client view should always be rendered as if the window
- // were active, regardless of whether or not the top level window actually
- // is active.
- bool paint_as_active_;
+ // The NonClientFrameView that renders the non-client portions of the window.
+ // This object is not owned by the view hierarchy because it can be replaced
+ // dynamically as the system settings change.
+ scoped_ptr<NonClientFrameView> frame_view_;
+
+ // Whether or not we should use the native frame.
+ bool use_native_frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonClientView);
};
} // namespace views
diff --git a/chrome/views/root_view.cc b/chrome/views/root_view.cc
index dfff6e4..8955732 100644
--- a/chrome/views/root_view.cc
+++ b/chrome/views/root_view.cc
@@ -220,6 +220,10 @@ Widget* RootView::GetWidget() const {
return widget_;
}
+void RootView::ThemeChanged() {
+ View::ThemeChanged();
+}
+
/////////////////////////////////////////////////////////////////////////////
//
// RootView - event dispatch and propagation
diff --git a/chrome/views/root_view.h b/chrome/views/root_view.h
index 6538625..103b06d 100644
--- a/chrome/views/root_view.h
+++ b/chrome/views/root_view.h
@@ -83,6 +83,10 @@ class RootView : public View,
// Get the Widget that hosts this View.
virtual Widget* GetWidget() const;
+ // Public API for broadcasting theme change notifications to this View
+ // hierarchy.
+ virtual void ThemeChanged();
+
// The following event methods are overridden to propagate event to the
// control tree
virtual bool OnMousePressed(const MouseEvent& e);
diff --git a/chrome/views/view.cc b/chrome/views/view.cc
index d435ddb..395eabc 100644
--- a/chrome/views/view.cc
+++ b/chrome/views/view.cc
@@ -626,6 +626,12 @@ void View::PropagateAddNotifications(View* parent, View* child) {
ViewHierarchyChangedImpl(true, true, parent, child);
}
+void View::ThemeChanged() {
+ int c = GetChildViewCount();
+ for (int i = c - 1; i >= 0; --i)
+ GetChildViewAt(i)->ThemeChanged();
+}
+
#ifndef NDEBUG
bool View::IsProcessingPaint() const {
return GetParent() && GetParent()->IsProcessingPaint();
diff --git a/chrome/views/view.h b/chrome/views/view.h
index aee08a3..824eb3f 100644
--- a/chrome/views/view.h
+++ b/chrome/views/view.h
@@ -995,6 +995,14 @@ class View : public AcceleratorTarget {
// to find other radio buttons.
int group_;
+ // Called when the UI theme has changed, overriding allows individual Views to
+ // do special cleanup and processing (such as dropping resource caches).
+ // Subclasses that override this method must call the base class
+ // implementation to ensure child views are processed.
+ // Can only be called by subclasses. To dispatch a theme changed notification,
+ // call this method on the RootView.
+ virtual void ThemeChanged();
+
#ifndef NDEBUG
// Returns true if the View is currently processing a paint.
virtual bool IsProcessingPaint() const;
diff --git a/chrome/views/views.vcproj b/chrome/views/views.vcproj
index e937b47..cbc6cd8 100644
--- a/chrome/views/views.vcproj
+++ b/chrome/views/views.vcproj
@@ -254,11 +254,11 @@
>
</File>
<File
- RelativePath=".\custom_frame_window.cc"
+ RelativePath=".\custom_frame_view.cc"
>
</File>
<File
- RelativePath=".\custom_frame_window.h"
+ RelativePath=".\custom_frame_view.h"
>
</File>
<File
@@ -270,14 +270,6 @@
>
</File>
<File
- RelativePath=".\default_non_client_view.cc"
- >
- </File>
- <File
- RelativePath=".\default_non_client_view.h"
- >
- </File>
- <File
RelativePath=".\dialog_client_view.cc"
>
</File>
@@ -418,6 +410,14 @@
>
</File>
<File
+ RelativePath=".\native_frame_view.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\native_frame_view.h"
+ >
+ </File>
+ <File
RelativePath=".\native_scroll_bar.cc"
>
</File>
diff --git a/chrome/views/widget.h b/chrome/views/widget.h
index d135860..0dab65f 100644
--- a/chrome/views/widget.h
+++ b/chrome/views/widget.h
@@ -16,9 +16,10 @@ class Rect;
namespace views {
+class Accelerator;
class RootView;
class TooltipManager;
-class Accelerator;
+class Window;
////////////////////////////////////////////////////////////////////////////////
//
@@ -77,6 +78,11 @@ class Widget {
// no accelerator associated with a given id, which is a common condition.
virtual bool GetAccelerator(int cmd_id,
Accelerator* accelerator) = 0;
+
+ // Returns the Widget as a Window, if such a conversion is possible, or NULL
+ // if it is not.
+ virtual Window* AsWindow() { return NULL; }
+ virtual const Window* AsWindow() const { return NULL; }
};
} // namespace views
diff --git a/chrome/views/widget_win.cc b/chrome/views/widget_win.cc
index 9568a64..0d7edf4 100644
--- a/chrome/views/widget_win.cc
+++ b/chrome/views/widget_win.cc
@@ -566,7 +566,7 @@ void WidgetWin::OnMouseMove(UINT flags, const CPoint& point) {
ProcessMouseMoved(point, flags, false);
}
-LRESULT WidgetWin::OnMouseLeave(UINT uMsg, WPARAM w_param, LPARAM l_param) {
+LRESULT WidgetWin::OnMouseLeave(UINT message, WPARAM w_param, LPARAM l_param) {
tooltip_manager_->OnMouseLeave();
ProcessMouseExited();
return 0;
diff --git a/chrome/views/widget_win.h b/chrome/views/widget_win.h
index 97f9fe4..546e9f7 100644
--- a/chrome/views/widget_win.h
+++ b/chrome/views/widget_win.h
@@ -176,6 +176,9 @@ class WidgetWin : public Widget,
MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)
+ // Vista and newer
+ MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)
+
// Non-atlcrack.h handlers
MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnNCMouseLeave)
@@ -183,6 +186,7 @@ class WidgetWin : public Widget,
// This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU.
MSG_WM_ACTIVATE(OnActivate)
+ MSG_WM_ACTIVATEAPP(OnActivateApp)
MSG_WM_APPCOMMAND(OnAppCommand)
MSG_WM_CANCELMODE(OnCancelMode)
MSG_WM_CAPTURECHANGED(OnCaptureChanged)
@@ -347,7 +351,12 @@ class WidgetWin : public Widget,
// handling to the appropriate Process* function. This is so that
// subclasses can easily override these methods to do different things
// and have a convenient function to call to get the default behavior.
- virtual void OnActivate(UINT action, BOOL minimized, HWND window) { }
+ virtual void OnActivate(UINT action, BOOL minimized, HWND window) {
+ SetMsgHandled(FALSE);
+ }
+ virtual void OnActivateApp(BOOL active, DWORD thread_id) {
+ SetMsgHandled(FALSE);
+ }
virtual LRESULT OnAppCommand(HWND window, short app_command, WORD device,
int keystate) {
SetMsgHandled(FALSE);
@@ -362,6 +371,12 @@ class WidgetWin : public Widget,
// WARNING: If you override this be sure and invoke super, otherwise we'll
// leak a few things.
virtual void OnDestroy();
+ virtual LRESULT OnDwmCompositionChanged(UINT msg,
+ WPARAM w_param,
+ LPARAM l_param) {
+ SetMsgHandled(FALSE);
+ return 0;
+ }
virtual void OnEndSession(BOOL ending, UINT logoff) { SetMsgHandled(FALSE); }
virtual void OnEnterSizeMove() { SetMsgHandled(FALSE); }
virtual void OnExitMenuLoop(BOOL is_track_popup_menu) { SetMsgHandled(FALSE); }
@@ -384,7 +399,7 @@ class WidgetWin : public Widget,
virtual void OnMButtonUp(UINT flags, const CPoint& point);
virtual LRESULT OnMouseActivate(HWND window, UINT hittest_code, UINT message);
virtual void OnMouseMove(UINT flags, const CPoint& point);
- virtual LRESULT OnMouseLeave(UINT uMsg, WPARAM w_param, LPARAM l_param);
+ virtual LRESULT OnMouseLeave(UINT message, WPARAM w_param, LPARAM l_param);
virtual void OnMove(const CPoint& point) { SetMsgHandled(FALSE); }
virtual void OnMoving(UINT param, const LPRECT new_bounds) { }
virtual LRESULT OnMouseWheel(UINT flags, short distance, const CPoint& point);
diff --git a/chrome/views/window.cc b/chrome/views/window.cc
index d4cb905..a879a99 100644
--- a/chrome/views/window.cc
+++ b/chrome/views/window.cc
@@ -16,8 +16,8 @@
#include "chrome/common/resource_bundle.h"
#include "chrome/common/win_util.h"
#include "chrome/views/client_view.h"
-#include "chrome/views/custom_frame_window.h"
-#include "chrome/views/default_non_client_view.h"
+#include "chrome/views/custom_frame_view.h"
+#include "chrome/views/native_frame_view.h"
#include "chrome/views/non_client_view.h"
#include "chrome/views/root_view.h"
#include "chrome/views/window_delegate.h"
@@ -82,12 +82,8 @@ Window::~Window() {
Window* Window::CreateChromeWindow(HWND parent,
const gfx::Rect& bounds,
WindowDelegate* window_delegate) {
- Window* window = NULL;
- if (win_util::ShouldUseVistaFrame()) {
- window = new Window(window_delegate);
- } else {
- window = new CustomFrameWindow(window_delegate);
- }
+ Window* window = new Window(window_delegate);
+ window->non_client_view_->SetFrameView(window->CreateFrameViewForWindow());
window->Init(parent, bounds);
return window;
}
@@ -205,18 +201,9 @@ void Window::EnableClose(bool enable) {
SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER);
}
-void Window::DisableInactiveRendering(bool disable) {
- disable_inactive_rendering_ = disable;
- if (!disable_inactive_rendering_)
- DefWindowProc(GetHWND(), WM_NCACTIVATE, FALSE, 0);
-
- if (!non_client_view_->UseNativeFrame()) {
- // If the non-client view is rendering its own frame, we need to forcibly
- // schedule a paint so it updates when we unset this mode.
- non_client_view_->set_paint_as_active(disable);
- if (!disable)
- non_client_view_->SchedulePaint();
- }
+void Window::DisableInactiveRendering() {
+ disable_inactive_rendering_ = true;
+ non_client_view_->DisableInactiveRendering(disable_inactive_rendering_);
}
void Window::UpdateWindowTitle() {
@@ -262,6 +249,11 @@ void Window::ExecuteSystemMenuCommand(int command) {
SendMessage(GetHWND(), WM_SYSCOMMAND, command, 0);
}
+gfx::Rect Window::GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) {
+ return non_client_view_->GetWindowBoundsForClientBounds(client_bounds);
+}
+
// static
int Window::GetLocalizedContentsWidth(int col_resource_id) {
double chars = _wtof(l10n_util::GetString(col_resource_id).c_str());
@@ -309,7 +301,7 @@ Window::Window(WindowDelegate* window_delegate)
: WidgetWin(),
focus_on_creation_(true),
window_delegate_(window_delegate),
- non_client_view_(new NonClientView),
+ non_client_view_(new NonClientView(this)),
owning_hwnd_(NULL),
minimum_size_(100, 100),
is_modal_(false),
@@ -349,13 +341,13 @@ void Window::Init(HWND parent, const gfx::Rect& bounds) {
WidgetWin::Init(parent, bounds, true);
win_util::SetWindowUserData(GetHWND(), this);
- std::wstring window_title = window_delegate_->GetWindowTitle();
- std::wstring localized_text;
- if (l10n_util::AdjustStringForLocaleDirection(window_title, &localized_text))
- window_title.assign(localized_text);
- SetWindowText(GetHWND(), window_title.c_str());
+ // Create the ClientView, add it to the NonClientView and add the
+ // NonClientView to the RootView. This will cause everything to be parented.
+ non_client_view_->set_client_view(window_delegate_->CreateClientView(this));
+ WidgetWin::SetContentsView(non_client_view_);
+
+ UpdateWindowTitle();
- SetClientView(window_delegate_->CreateClientView(this));
SetInitialBounds(bounds);
InitAlwaysOnTopState();
@@ -366,7 +358,18 @@ void Window::Init(HWND parent, const gfx::Rect& bounds) {
NotificationService::AllSources());
}
- ResetWindowRegion();
+ ResetWindowRegion(false);
+}
+
+NonClientFrameView* Window::CreateFrameViewForWindow() {
+ if (non_client_view_->UseNativeFrame())
+ return new NativeFrameView(this);
+ return new CustomFrameView(this);
+}
+
+void Window::UpdateFrameAfterFrameChange() {
+ // We've either gained or lost a custom window region, so reset it now.
+ ResetWindowRegion(true);
}
void Window::SizeWindowToDefault() {
@@ -398,6 +401,15 @@ void Window::OnActivate(UINT action, BOOL minimized, HWND window) {
SaveWindowPosition();
}
+void Window::OnActivateApp(BOOL active, DWORD thread_id) {
+ if (!active && thread_id != GetCurrentThreadId()) {
+ // Another application was activated, we should reset any state that
+ // disables inactive rendering now.
+ disable_inactive_rendering_ = false;
+ non_client_view_->DisableInactiveRendering(false);
+ }
+}
+
LRESULT Window::OnAppCommand(HWND window, short app_command, WORD device,
int keystate) {
// We treat APPCOMMAND ids as an extension of our command namespace, and just
@@ -426,6 +438,27 @@ void Window::OnDestroy() {
}
namespace {
+static BOOL CALLBACK SendDwmCompositionChanged(HWND window, LPARAM param) {
+ SendMessage(window, WM_DWMCOMPOSITIONCHANGED, 0, 0);
+ return TRUE;
+}
+} // namespace
+
+LRESULT Window::OnDwmCompositionChanged(UINT msg, WPARAM w_param,
+ LPARAM l_param) {
+ // We respond to this in response to WM_DWMCOMPOSITIONCHANGED since that is
+ // the only thing we care about - we don't actually respond to WM_THEMECHANGED
+ // messages.
+ non_client_view_->SystemThemeChanged();
+
+ // 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(GetHWND(), &SendDwmCompositionChanged, NULL);
+ return 0;
+}
+
+namespace {
static void EnableMenuItem(HMENU menu, UINT command, bool enabled) {
UINT flags = MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
EnableMenuItem(menu, command, flags);
@@ -435,10 +468,8 @@ static void EnableMenuItem(HMENU menu, UINT command, bool enabled) {
void Window::OnInitMenu(HMENU menu) {
// We only need to manually enable the system menu if we're not using a native
// frame.
- if (non_client_view_->UseNativeFrame()) {
- SetMsgHandled(FALSE);
- return;
- }
+ if (non_client_view_->UseNativeFrame())
+ WidgetWin::OnInitMenu(menu);
bool is_minimized = IsMinimized();
bool is_maximized = IsMaximized();
@@ -482,12 +513,12 @@ void Window::OnMouseLeave() {
}
LRESULT Window::OnNCActivate(BOOL active) {
+ is_active_ = !!active;
+
// If we're not using the native frame, we need to force a synchronous repaint
// otherwise we'll be left in the wrong activation state until something else
// causes a repaint later.
if (!non_client_view_->UseNativeFrame()) {
- is_active_ = !!active;
-
// We can get WM_NCACTIVATE before we're actually visible. If we're not
// visible, no need to paint.
if (IsWindowVisible(GetHWND())) {
@@ -498,21 +529,26 @@ LRESULT Window::OnNCActivate(BOOL active) {
}
}
+ // If we're active again, we should be allowed to render as inactive, so
+ // tell the non-client view. This must be done independently of the check for
+ // disable_inactive_rendering_ since that check is valid even if the frame
+ // is not active, but this can only be done if we've become active.
+ if (is_active_)
+ non_client_view_->DisableInactiveRendering(false);
+
+ // Reset the disable inactive rendering state since activation has changed.
if (disable_inactive_rendering_) {
disable_inactive_rendering_ = false;
- return DefWindowProc(GetHWND(), WM_NCACTIVATE, TRUE, 0);
+ return CallDefaultNCActivateHandler(TRUE);
}
- // Otherwise just do the default thing.
- return WidgetWin::OnNCActivate(active);
+ return CallDefaultNCActivateHandler(active);
}
LRESULT Window::OnNCCalcSize(BOOL mode, LPARAM l_param) {
// We only need to adjust the client size/paint handling when we're not using
// the native frame.
- if (non_client_view_->UseNativeFrame()) {
- SetMsgHandled(FALSE);
- return 0;
- }
+ if (non_client_view_->UseNativeFrame())
+ return WidgetWin::OnNCCalcSize(mode, l_param);
// We need to repaint all when the window bounds change.
return WVR_REDRAW;
@@ -529,8 +565,7 @@ LRESULT Window::OnNCHitTest(const CPoint& point) {
// Otherwise, we let Windows do all the native frame non-client handling for
// us.
- SetMsgHandled(FALSE);
- return 0;
+ return WidgetWin::OnNCHitTest(point);
}
namespace {
@@ -564,10 +599,8 @@ static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) {
void Window::OnNCPaint(HRGN rgn) {
// We only do non-client painting if we're not using the native frame.
- if (non_client_view_->UseNativeFrame()) {
- SetMsgHandled(FALSE);
- return;
- }
+ if (non_client_view_->UseNativeFrame())
+ return WidgetWin::OnNCPaint(rgn);
// We have an NC region and need to paint it. We expand the NC region to
// include the dirty region of the root view. This is done to minimize
@@ -765,7 +798,7 @@ void Window::OnSize(UINT size_param, const CSize& new_size) {
// ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've
// invoked OnSize we ensure the RootView has been laid out.
- ResetWindowRegion();
+ ResetWindowRegion(false);
}
void Window::OnSysCommand(UINT notification_code, CPoint click) {
@@ -796,17 +829,17 @@ void Window::OnSysCommand(UINT notification_code, CPoint click) {
is_always_on_top_ = !is_always_on_top_;
// Change the menu check state.
- HMENU system_menu = ::GetSystemMenu(GetHWND(), FALSE);
+ HMENU system_menu = GetSystemMenu(GetHWND(), FALSE);
MENUITEMINFO menu_info;
memset(&menu_info, 0, sizeof(MENUITEMINFO));
menu_info.cbSize = sizeof(MENUITEMINFO);
- BOOL r = ::GetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP,
- FALSE, &menu_info);
+ BOOL r = GetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP,
+ FALSE, &menu_info);
DCHECK(r);
menu_info.fMask = MIIM_STATE;
if (is_always_on_top_)
menu_info.fState = MFS_CHECKED;
- r = ::SetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP, FALSE, &menu_info);
+ r = SetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP, FALSE, &menu_info);
// Now change the actual window's behavior.
AlwaysOnTopChanged();
@@ -823,13 +856,6 @@ void Window::OnSysCommand(UINT notification_code, CPoint click) {
////////////////////////////////////////////////////////////////////////////////
// Window, private:
-void Window::SetClientView(ClientView* client_view) {
- DCHECK(client_view && GetHWND());
- non_client_view_->set_client_view(client_view);
- // This will trigger the ClientView to be added by the non-client view.
- WidgetWin::SetContentsView(non_client_view_);
-}
-
void Window::BecomeModal() {
// We implement modality by crawling up the hierarchy of windows starting
// at the owner, disabling all of them so that they don't receive input
@@ -1023,11 +1049,14 @@ void Window::UnlockUpdates() {
lock_updates_ = false;
}
-void Window::ResetWindowRegion() {
+void Window::ResetWindowRegion(bool force) {
// A native frame uses the native window region, and we don't want to mess
// with it.
- if (non_client_view_->UseNativeFrame())
+ if (non_client_view_->UseNativeFrame()) {
+ if (force)
+ SetWindowRgn(NULL, TRUE);
return;
+ }
// Changing the window region is going to force a paint. Only change the
// window region if the region really differs.
@@ -1075,6 +1104,14 @@ void Window::ProcessNCMousePress(const CPoint& point, int flags) {
ProcessMousePressed(temp, message_flags, false, false);
}
+LRESULT Window::CallDefaultNCActivateHandler(BOOL active) {
+ // The DefWindowProc handling for WM_NCACTIVATE renders the classic-look
+ // window title bar directly, so we need to use a redraw lock here to prevent
+ // it from doing so.
+ ScopedRedrawLock lock(this);
+ return DefWindowProc(GetHWND(), WM_NCACTIVATE, active, 0);
+}
+
void Window::InitClass() {
static bool initialized = false;
if (!initialized) {
diff --git a/chrome/views/window.h b/chrome/views/window.h
index b87f0e3..564cfab 100644
--- a/chrome/views/window.h
+++ b/chrome/views/window.h
@@ -68,7 +68,7 @@ class Window : public WidgetWin,
void SetBounds(const gfx::Rect& bounds, HWND other_hwnd);
// Closes the window, ultimately destroying it.
- virtual void Close();
+ void Close();
// Whether or not the window is maximized or minimized.
bool IsMaximized() const;
@@ -76,35 +76,46 @@ class Window : public WidgetWin,
// Toggles the enable state for the Close button (and the Close menu item in
// the system menu).
- virtual void EnableClose(bool enable);
+ void EnableClose(bool enable);
- // Prevents the window from being rendered as deactivated when |disable| is
- // true, until called with |disable| false. Used when a sub-window is to be
- // shown that shouldn't visually de-activate the window.
- // Subclasses can override this to perform additional actions when this value
- // changes.
- virtual void DisableInactiveRendering(bool disable);
-
- WindowDelegate* window_delegate() const { return window_delegate_; }
-
- void set_focus_on_creation(bool focus_on_creation) {
- focus_on_creation_ = focus_on_creation;
- }
+ // Prevents the window from being rendered as deactivated the next time it is.
+ // This state is reset automatically as soon as the window becomes actiated
+ // again. There is no ability to control the state through this API as this
+ // leads to sync problems.
+ void DisableInactiveRendering();
// Tell the window to update its title from the delegate.
- virtual void UpdateWindowTitle();
+ void UpdateWindowTitle();
// Tell the window to update its icon from the delegate.
- virtual void UpdateWindowIcon();
+ void UpdateWindowIcon();
// Executes the specified SC_command.
void ExecuteSystemMenuCommand(int command);
- // The parent of this window.
- HWND owning_window() const { return owning_hwnd_; }
+ // Shortcut to access the determination of whether or not we're using a
+ // native frame. This triggers different rendering modes in certain views and
+ // should be used in preference to calling win_util::ShouldUseVistaFrame.
+ bool UseNativeFrame() const { return non_client_view_->UseNativeFrame(); }
+
+ // Returns the bounds of the window required to display the content area
+ // at the specified bounds.
+ gfx::Rect GetWindowBoundsForClientBounds(const gfx::Rect& client_bounds);
+
+ // Creates an appropriate NonClientFrameView for this window.
+ virtual NonClientFrameView* CreateFrameViewForWindow();
- // Shortcut to access the ClientView associated with this window.
+ // Updates the frame after an event caused it to be changed.
+ virtual void UpdateFrameAfterFrameChange();
+
+ // Accessors and setters for various properties.
+ WindowDelegate* window_delegate() const { return window_delegate_; }
+ HWND owning_window() const { return owning_hwnd_; }
ClientView* client_view() const { return non_client_view_->client_view(); }
+ bool is_active() const { return is_active_; }
+ void set_focus_on_creation(bool focus_on_creation) {
+ focus_on_creation_ = focus_on_creation;
+ }
// Returns the preferred size of the contents view of this window based on
// its localized size data. The width in cols is held in a localized string
@@ -144,25 +155,30 @@ class Window : public WidgetWin,
// Overridden from WidgetWin:
virtual void OnActivate(UINT action, BOOL minimized, HWND window);
+ virtual void OnActivateApp(BOOL active, DWORD thread_id);
virtual LRESULT OnAppCommand(HWND window, short app_command, WORD device,
int keystate);
virtual void OnCommand(UINT notification_code, int command_id, HWND window);
virtual void OnDestroy();
+ virtual LRESULT OnDwmCompositionChanged(UINT msg, WPARAM w_param,
+ LPARAM l_param);
virtual void OnInitMenu(HMENU menu);
virtual void OnMouseLeave();
virtual LRESULT OnNCActivate(BOOL active);
virtual LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param);
virtual LRESULT OnNCHitTest(const CPoint& point);
- virtual LRESULT OnNCUAHDrawCaption(UINT msg, WPARAM w_param, LPARAM l_param);
- virtual LRESULT OnNCUAHDrawFrame(UINT msg, WPARAM w_param, LPARAM l_param);
virtual void OnNCPaint(HRGN rgn);
virtual void OnNCLButtonDown(UINT ht_component, const CPoint& point);
virtual void OnNCRButtonDown(UINT ht_component, const CPoint& point);
+ virtual LRESULT OnNCUAHDrawCaption(UINT msg, WPARAM w_param, LPARAM l_param);
+ virtual LRESULT OnNCUAHDrawFrame(UINT msg, WPARAM w_param, LPARAM l_param);
virtual LRESULT OnSetCursor(HWND window, UINT hittest_code, UINT message);
virtual LRESULT OnSetIcon(UINT size_type, HICON new_icon);
virtual LRESULT OnSetText(const wchar_t* text);
virtual void OnSize(UINT size_param, const CSize& new_size);
virtual void OnSysCommand(UINT notification_code, CPoint click);
+ virtual Window* AsWindow() { return this; }
+ virtual const Window* AsWindow() const { return this; }
// The View that provides the non-client area of the window (title bar,
// window controls, sizing borders etc). To use an implementation other than
@@ -176,15 +192,6 @@ class Window : public WidgetWin,
}
private:
- // Sets the specified view as the ClientView of this Window. The ClientView
- // is responsible for laying out the Window's contents view, as well as
- // performing basic hit-testing, and perhaps other responsibilities depending
- // on the implementation. The Window's view hierarchy takes ownership of the
- // ClientView unless the ClientView specifies otherwise. This must be called
- // only once, and after the native window has been created.
- // This is called by Init. |client_view| cannot be NULL.
- void SetClientView(ClientView* client_view);
-
// Set the window as modal (by disabling all the other windows).
void BecomeModal();
@@ -224,7 +231,9 @@ class Window : public WidgetWin,
void UnlockUpdates();
// Resets the window region for the current window bounds if necessary.
- void ResetWindowRegion();
+ // If |force| is true, the window region is reset to NULL even for native
+ // frame windows.
+ void ResetWindowRegion(bool force);
// Converts a non-client mouse down message to a regular ChromeViews event
// and handle it. |point| is the mouse position of the message in screen
@@ -233,6 +242,11 @@ class Window : public WidgetWin,
// combined with flags relating to the current key state.
void ProcessNCMousePress(const CPoint& point, int flags);
+ // Calls the default WM_NCACTIVATE handler with the specified activation
+ // value, safely wrapping the call in a ScopedRedrawLock to prevent frame
+ // flicker.
+ LRESULT CallDefaultNCActivateHandler(BOOL active);
+
// Static resource initialization.
static void InitClass();
enum ResizeCursor {