summaryrefslogtreecommitdiffstats
path: root/views/window/non_client_view.cc
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-08 00:34:05 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-08 00:34:05 +0000
commit2362e4fe2905ab75d3230ebc3e307ae53e2b8362 (patch)
treee6d88357a2021811e0e354f618247217be8bb3da /views/window/non_client_view.cc
parentdb23ac3e713dc17509b2b15d3ee634968da45715 (diff)
downloadchromium_src-2362e4fe2905ab75d3230ebc3e307ae53e2b8362.zip
chromium_src-2362e4fe2905ab75d3230ebc3e307ae53e2b8362.tar.gz
chromium_src-2362e4fe2905ab75d3230ebc3e307ae53e2b8362.tar.bz2
Move src/chrome/views to src/views. RS=darin http://crbug.com/11387
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15604 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/window/non_client_view.cc')
-rw-r--r--views/window/non_client_view.cc255
1 files changed, 255 insertions, 0 deletions
diff --git a/views/window/non_client_view.cc b/views/window/non_client_view.cc
new file mode 100644
index 0000000..9a06cfc
--- /dev/null
+++ b/views/window/non_client_view.cc
@@ -0,0 +1,255 @@
+// 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 "views/window/non_client_view.h"
+
+#include "chrome/common/win_util.h"
+#include "views/widget/root_view.h"
+#include "views/widget/widget.h"
+#include "views/window/window.h"
+
+namespace views {
+
+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(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();
+}
+
+void NonClientView::WindowClosing() {
+ client_view_->WindowClosing();
+}
+
+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 {
+ // 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_;
+}
+
+void NonClientView::DisableInactiveRendering(bool disable) {
+ frame_view_->DisableInactiveRendering(disable);
+}
+
+gfx::Rect NonClientView::GetWindowBoundsForClientBounds(
+ const gfx::Rect client_bounds) const {
+ return frame_view_->GetWindowBoundsForClientBounds(client_bounds);
+}
+
+gfx::Point NonClientView::GetSystemMenuPoint() const {
+ return frame_view_->GetSystemMenuPoint();
+}
+
+int NonClientView::NonClientHitTest(const gfx::Point& 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();
+}
+
+void NonClientView::LayoutFrameView() {
+ // First layout the NonClientFrameView, which determines the size of the
+ // ClientView...
+ frame_view_->SetBounds(0, 0, width(), height());
+
+ // We need to manually call Layout here because layout for the frame view can
+ // change independently of the bounds changing - e.g. after the initial
+ // display of the window the metrics of the native window controls can change,
+ // which does not change the bounds of the window but requires a re-layout to
+ // trigger a repaint. We override DidChangeBounds for the NonClientFrameView
+ // to do nothing so that SetBounds above doesn't cause Layout to be called
+ // twice.
+ frame_view_->Layout();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NonClientView, View overrides:
+
+gfx::Size NonClientView::GetPreferredSize() {
+ // TODO(pkasting): This should probably be made to look similar to
+ // GetMinimumSize() below. This will require implementing GetPreferredSize()
+ // better in the various frame views.
+ gfx::Rect client_bounds(gfx::Point(), client_view_->GetPreferredSize());
+ return GetWindowBoundsForClientBounds(client_bounds).size();
+}
+
+gfx::Size NonClientView::GetMinimumSize() {
+ return frame_view_->GetMinimumSize();
+}
+
+void NonClientView::Layout() {
+ LayoutFrameView();
+
+ // Then layout the ClientView, using those bounds.
+ client_view_->SetBounds(frame_view_->GetBoundsForClientView());
+
+ // We need to manually call Layout on the ClientView as well for the same
+ // reason as above.
+ client_view_->Layout();
+}
+
+void NonClientView::ViewHierarchyChanged(bool is_add, View* parent,
+ View* child) {
+ // 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_);
+ }
+}
+
+views::View* NonClientView::GetViewForPoint(const gfx::Point& point) {
+ return GetViewForPoint(point, false);
+}
+
+views::View* NonClientView::GetViewForPoint(const gfx::Point& point,
+ bool can_create_floating) {
+ // Because of the z-ordering of our child views (the client view is positioned
+ // over the non-client frame view, if the client view ever overlaps the frame
+ // view visually (as it does for the browser window), then it will eat mouse
+ // events for the window controls. We override this method here so that we can
+ // detect this condition and re-route the events to the non-client frame view.
+ // The assumption is that the frame view's implementation of HitTest will only
+ // return true for area not occupied by the client view.
+ gfx::Point point_in_child_coords(point);
+ View::ConvertPointToView(this, frame_view_.get(), &point_in_child_coords);
+ if (frame_view_->HitTest(point_in_child_coords))
+ return frame_view_->GetViewForPoint(point);
+
+ return View::GetViewForPoint(point, can_create_floating);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameView, View overrides:
+
+bool NonClientFrameView::HitTest(const gfx::Point& l) const {
+ // For the default case, we assume the non-client frame view never overlaps
+ // the client view.
+ return !GetWindow()->GetClientView()->bounds().Contains(l);
+}
+
+void NonClientFrameView::DidChangeBounds(const gfx::Rect& previous,
+ const gfx::Rect& current) {
+ // Overridden to do nothing. The NonClientView manually calls Layout on the
+ // FrameView when it is itself laid out, see comment in NonClientView::Layout.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 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
+ // (not the side border). Vista goes further and doesn't return these on any
+ // of the side borders. We allow callers to match either behavior.
+ int component;
+ if (point.x() < resize_border_thickness) {
+ if (point.y() < top_resize_corner_height)
+ component = HTTOPLEFT;
+ else if (point.y() >= (height() - resize_border_thickness))
+ component = HTBOTTOMLEFT;
+ else
+ component = HTLEFT;
+ } else if (point.x() >= (width() - resize_border_thickness)) {
+ if (point.y() < top_resize_corner_height)
+ component = HTTOPRIGHT;
+ else if (point.y() >= (height() - resize_border_thickness))
+ component = HTBOTTOMRIGHT;
+ else
+ component = HTRIGHT;
+ } else if (point.y() < top_resize_border_height) {
+ if (point.x() < resize_corner_width)
+ component = HTTOPLEFT;
+ else if (point.x() >= (width() - resize_corner_width))
+ component = HTTOPRIGHT;
+ else
+ component = HTTOP;
+ } else if (point.y() >= (height() - resize_border_thickness)) {
+ if (point.x() < resize_corner_width)
+ component = HTBOTTOMLEFT;
+ else if (point.x() >= (width() - resize_corner_width))
+ component = HTBOTTOMRIGHT;
+ else
+ component = HTBOTTOM;
+ } else {
+ return HTNOWHERE;
+ }
+
+ // If the window can't be resized, there are no resize boundaries, just
+ // window borders.
+ return can_resize ? component : HTBORDER;
+}
+
+} // namespace views