Index: chrome/views/non_client_view.cc |
=================================================================== |
--- chrome/views/non_client_view.cc (revision 10688) |
+++ chrome/views/non_client_view.cc (working copy) |
@@ -3,22 +3,48 @@ |
// 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 { |
return client_view_->CanClose(); |
} |
@@ -27,41 +53,84 @@ |
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 @@ |
} |
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: |
+// NonClientFrameView, 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) { |
+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 |