glass_app_window_frame_view_win.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file.
48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/ui/views/apps/glass_app_window_frame_view_win.h"
68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "apps/ui/native_app_window.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/hit_test.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gfx/win/dpi.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/widget/widget.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/widget/widget_delegate.h"
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace {
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)const int kResizeAreaCornerSize = 16;
168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace
188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const char GlassAppWindowFrameViewWin::kViewClassName[] =
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    "ui/views/apps/GlassAppWindowFrameViewWin";
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)GlassAppWindowFrameViewWin::GlassAppWindowFrameViewWin(
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    apps::NativeAppWindow* window,
248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    views::Widget* widget)
258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : window_(window), widget_(widget) {
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)GlassAppWindowFrameViewWin::~GlassAppWindowFrameViewWin() {
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)gfx::Insets GlassAppWindowFrameViewWin::GetGlassInsets() const {
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // If 1 is not subtracted, they are too big. There is possibly some reason
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // for that.
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Also make sure the insets don't go below 1, as bad things happen when they
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // do.
368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int caption_height = std::max(0,
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      gfx::win::GetSystemMetricsInDIP(SM_CYSMICON) +
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          gfx::win::GetSystemMetricsInDIP(SM_CYSIZEFRAME) - 1);
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int frame_size =
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      std::max(1, gfx::win::GetSystemMetricsInDIP(SM_CXSIZEFRAME) - 1);
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return gfx::Insets(
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      frame_size + caption_height, frame_size, frame_size, frame_size);
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)gfx::Rect GlassAppWindowFrameViewWin::GetBoundsForClientView() const {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (widget_->IsFullscreen())
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return bounds();
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  gfx::Insets insets = GetGlassInsets();
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return gfx::Rect(insets.left(),
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   insets.top(),
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   std::max(0, width() - insets.left() - insets.right()),
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   std::max(0, height() - insets.top() - insets.bottom()));
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)gfx::Rect GlassAppWindowFrameViewWin::GetWindowBoundsForClientBounds(
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const gfx::Rect& client_bounds) const {
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Insets insets = GetGlassInsets();
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Our bounds are not the same as the window's due to the offset added by
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // AppWindowDesktopWindowTreeHostWin::GetClientAreaInsets. So account for it
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // here.
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  insets += gfx::Insets(0, 0, 1, 1);
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return gfx::Rect(client_bounds.x() - insets.left(),
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   client_bounds.y() - insets.top(),
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   client_bounds.width() + insets.left() + insets.right(),
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   client_bounds.height() + insets.top() + insets.bottom());
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int GlassAppWindowFrameViewWin::NonClientHitTest(const gfx::Point& point) {
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (widget_->IsFullscreen())
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return HTCLIENT;
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!bounds().Contains(point))
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return HTNOWHERE;
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Check the frame first, as we allow a small area overlapping the contents
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // to be used for resize handles.
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool can_ever_resize = widget_->widget_delegate()
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                             ? widget_->widget_delegate()->CanResize()
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                             : false;
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Don't allow overlapping resize handles when the window is maximized or
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // fullscreen, as it can't be resized in those states.
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int resize_border = gfx::win::GetSystemMetricsInDIP(SM_CXSIZEFRAME);
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int frame_component =
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetHTComponentForFrame(point,
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             resize_border,
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             resize_border,
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             kResizeAreaCornerSize - resize_border,
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             kResizeAreaCornerSize - resize_border,
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             can_ever_resize);
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (frame_component != HTNOWHERE)
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return frame_component;
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int client_component = widget_->client_view()->NonClientHitTest(point);
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (client_component != HTNOWHERE)
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return client_component;
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Caption is a safe default.
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return HTCAPTION;
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void GlassAppWindowFrameViewWin::GetWindowMask(const gfx::Size& size,
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                               gfx::Path* window_mask) {
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We got nothing to say about no window mask.
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)gfx::Size GlassAppWindowFrameViewWin::GetPreferredSize() const {
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Size pref = widget_->client_view()->GetPreferredSize();
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Rect bounds(0, 0, pref.width(), pref.height());
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return widget_->non_client_view()
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ->GetWindowBoundsForClientBounds(bounds)
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      .size();
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char* GlassAppWindowFrameViewWin::GetClassName() const {
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return kViewClassName;
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)gfx::Size GlassAppWindowFrameViewWin::GetMinimumSize() const {
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Size min_size = widget_->client_view()->GetMinimumSize();
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  gfx::Rect client_bounds = GetBoundsForClientView();
1238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  min_size.Enlarge(width() - client_bounds.width(),
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                   height() - client_bounds.height());
1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return min_size;
1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)gfx::Size GlassAppWindowFrameViewWin::GetMaximumSize() const {
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  gfx::Size max_size = widget_->client_view()->GetMaximumSize();
1308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Add to the client maximum size the height of any title bar and borders.
1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  gfx::Size client_size = GetBoundsForClientView().size();
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (max_size.width())
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    max_size.Enlarge(width() - client_size.width(), 0);
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (max_size.height())
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    max_size.Enlarge(0, height() - client_size.height());
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return max_size;
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)