15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/non_client_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gfx/rect_conversions.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/rect_based_targeting_utils.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/root_view.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/client_view.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char NonClientFrameView::kViewClassName[] =
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ui/views/window/NonClientFrameView";
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char NonClientView::kViewClassName[] =
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ui/views/window/NonClientView";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The frame view and the client view are always at these specific indices,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because the RootView message dispatch sends messages to items higher in the
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// z-order first and we always want the client view to have first crack at
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handling mouse messages.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFrameViewIndex = 0;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kClientViewIndex = 1;
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// The overlay view is always on top (index == child_count() - 1).
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NonClientView, public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NonClientView::NonClientView()
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : client_view_(NULL),
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      overlay_view_(NULL) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NonClientView::~NonClientView() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This value may have been reset before the window hierarchy shuts down,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so we need to manually remove it.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveChildView(frame_view_.get());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::SetFrameView(NonClientFrameView* frame_view) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See comment in header about ownership.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view->set_owned_by_client();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_view_.get())
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveChildView(frame_view_.get());
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_.reset(frame_view);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parent())
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildViewAt(frame_view_.get(), kFrameViewIndex);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void NonClientView::SetOverlayView(View* view) {
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (overlay_view_)
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    RemoveChildView(overlay_view_);
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!view)
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  overlay_view_ = view;
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (parent())
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AddChildView(overlay_view_);
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NonClientView::CanClose() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return client_view_->CanClose();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::WindowClosing() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_view_->WidgetClosing();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NonClientView::UpdateFrame() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Widget* widget = GetWidget();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetFrameView(widget->CreateNonClientFrameView());
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  widget->ThemeChanged();
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Layout();
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SchedulePaint();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::SetInactiveRenderingDisabled(bool disable) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_->SetInactiveRenderingDisabled(disable);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect NonClientView::GetWindowBoundsForClientBounds(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect client_bounds) const {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_view_->GetWindowBoundsForClientBounds(client_bounds);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NonClientView::NonClientHitTest(const gfx::Point& point) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The NonClientFrameView is responsible for also asking the ClientView.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_view_->NonClientHitTest(point);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::GetWindowMask(const gfx::Size& size,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  gfx::Path* window_mask) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_->GetWindowMask(size, window_mask);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::ResetWindowControls() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_->ResetWindowControls();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::UpdateWindowIcon() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_->UpdateWindowIcon();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::UpdateWindowTitle() {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_->UpdateWindowTitle();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::LayoutFrameView() {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First layout the NonClientFrameView, which determines the size of the
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ClientView...
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_->SetBounds(0, 0, width(), height());
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to manually call Layout here because layout for the frame view can
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change independently of the bounds changing - e.g. after the initial
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // display of the window the metrics of the native window controls can change,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which does not change the bounds of the window but requires a re-layout to
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // trigger a repaint. We override OnBoundsChanged() for the NonClientFrameView
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to do nothing so that SetBounds above doesn't cause Layout to be called
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // twice.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_view_->Layout();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NonClientView::SetAccessibleName(const base::string16& name) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  accessible_name_ = name;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NonClientView, View overrides:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size NonClientView::GetPreferredSize() const {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(pkasting): This should probably be made to look similar to
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetMinimumSize() below.  This will require implementing GetPreferredSize()
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // better in the various frame views.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect client_bounds(gfx::Point(), client_view_->GetPreferredSize());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetWindowBoundsForClientBounds(client_bounds).size();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size NonClientView::GetMinimumSize() const {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_view_->GetMinimumSize();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size NonClientView::GetMaximumSize() const {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_view_->GetMaximumSize();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientView::Layout() {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LayoutFrameView();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Then layout the ClientView, using those bounds.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_view_->SetBoundsRect(frame_view_->GetBoundsForClientView());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to manually call Layout on the ClientView as well for the same
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reason as above.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_view_->Layout();
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (overlay_view_ && overlay_view_->visible())
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    overlay_view_->SetBoundsRect(GetLocalBounds());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void NonClientView::ViewHierarchyChanged(
168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const ViewHierarchyChangedDetails& details) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add our two child views here as we are added to the Widget so that if we
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are subsequently resized all the parent-child relationships are
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // established.
172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (details.is_add && GetWidget() && details.child == this) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildViewAt(frame_view_.get(), kFrameViewIndex);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildViewAt(client_view_, kClientViewIndex);
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (overlay_view_)
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      AddChildView(overlay_view_);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NonClientView::GetAccessibleState(ui::AXViewState* state) {
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  state->role = ui::AX_ROLE_CLIENT;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->name = accessible_name_;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* NonClientView::GetClassName() const {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochView* NonClientView::GetEventHandlerForRect(const gfx::Rect& rect) {
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!UsePointBasedTargeting(rect))
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return View::GetEventHandlerForRect(rect);
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Because of the z-ordering of our child views (the client view is positioned
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // over the non-client frame view, if the client view ever overlaps the frame
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // view visually (as it does for the browser window), then it will eat
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // events for the window controls. We override this method here so that we can
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // detect this condition and re-route the events to the non-client frame view.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The assumption is that the frame view's implementation of HitTest will only
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return true for area not occupied by the client view.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_view_->parent() == this) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // During the reset of the frame_view_ it's possible to be in this code
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // after it's been removed from the view hierarchy but before it's been
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // removed from the NonClientView.
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::RectF rect_in_child_coords_f(rect);
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    View::ConvertRectToTarget(this, frame_view_.get(), &rect_in_child_coords_f);
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Rect rect_in_child_coords = gfx::ToEnclosingRect(
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        rect_in_child_coords_f);
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (frame_view_->HitTestRect(rect_in_child_coords))
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return frame_view_->GetEventHandlerForRect(rect_in_child_coords);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return View::GetEventHandlerForRect(rect);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochView* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) {
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The same logic as for |GetEventHandlerForRect()| applies here.
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (frame_view_->parent() == this) {
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // During the reset of the frame_view_ it's possible to be in this code
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // after it's been removed from the view hierarchy but before it's been
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // removed from the NonClientView.
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point point_in_child_coords(point);
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    View::ConvertPointToTarget(this, frame_view_.get(), &point_in_child_coords);
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    View* handler =
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        frame_view_->GetTooltipHandlerForPoint(point_in_child_coords);
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (handler)
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return handler;
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return View::GetTooltipHandlerForPoint(point);
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NonClientFrameView, public:
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NonClientFrameView::~NonClientFrameView() {
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientFrameView::SetInactiveRenderingDisabled(bool disable) {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (inactive_rendering_disabled_ == disable)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool should_paint_as_active_old = ShouldPaintAsActive();
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  inactive_rendering_disabled_ = disable;
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The widget schedules a paint when the activation changes.
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (should_paint_as_active_old != ShouldPaintAsActive())
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SchedulePaint();
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NonClientFrameView::ShouldPaintAsActive() const {
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return inactive_rendering_disabled_ || GetWidget()->IsActive();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NonClientFrameView::GetHTComponentForFrame(const gfx::Point& point,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int top_resize_border_height,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int resize_border_thickness,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int top_resize_corner_height,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int resize_corner_width,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               bool can_resize) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tricky: In XP, native behavior is to return HTTOPLEFT and HTTOPRIGHT for
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a |resize_corner_size|-length strip of both the side and top borders, but
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only to return HTBOTTOMLEFT/HTBOTTOMRIGHT along the bottom border + corner
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (not the side border).  Vista goes further and doesn't return these on any
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the side borders.  We allow callers to match either behavior.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int component;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (point.x() < resize_border_thickness) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (point.y() < top_resize_corner_height)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTTOPLEFT;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (point.y() >= (height() - resize_border_thickness))
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTBOTTOMLEFT;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTLEFT;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (point.x() >= (width() - resize_border_thickness)) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (point.y() < top_resize_corner_height)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTTOPRIGHT;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (point.y() >= (height() - resize_border_thickness))
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTBOTTOMRIGHT;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTRIGHT;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (point.y() < top_resize_border_height) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (point.x() < resize_corner_width)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTTOPLEFT;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (point.x() >= (width() - resize_corner_width))
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTTOPRIGHT;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTTOP;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (point.y() >= (height() - resize_border_thickness)) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (point.x() < resize_corner_width)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTBOTTOMLEFT;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (point.x() >= (width() - resize_corner_width))
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTBOTTOMRIGHT;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      component = HTBOTTOM;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HTNOWHERE;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the window can't be resized, there are no resize boundaries, just
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window borders.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return can_resize ? component : HTBORDER;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NonClientFrameView, View overrides:
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NonClientFrameView::HitTestRect(const gfx::Rect& rect) const {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For the default case, we assume the non-client frame view never overlaps
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the client view.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !GetWidget()->client_view()->bounds().Intersects(rect);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NonClientFrameView, protected:
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NonClientFrameView::GetAccessibleState(ui::AXViewState* state) {
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  state->role = ui::AX_ROLE_CLIENT;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* NonClientFrameView::GetClassName() const {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NonClientFrameView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden to do nothing. The NonClientView manually calls Layout on the
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FrameView when it is itself laid out, see comment in NonClientView::Layout.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NonClientFrameView::NonClientFrameView() : inactive_rendering_disabled_(false) {
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
332