diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-03 00:28:00 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-03 00:28:00 +0000 |
commit | 32670b07a6c42634f446e3d471f42a9fb40090f2 (patch) | |
tree | 77b15435f3a436d54fcaa5cb4c0d4371a007fad6 /chrome/views/non_client_view.cc | |
parent | a0e5688cc11f7f5e835b5c1a75c17ce4a28a1527 (diff) | |
download | chromium_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/non_client_view.cc')
-rw-r--r-- | chrome/views/non_client_view.cc | 135 |
1 files changed, 106 insertions, 29 deletions
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 |