1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ui/frame/frame_utils.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/ui/base/chromeos_ui_constants.h"
#include "chromeos/ui/base/display_util.h"
#include "chromeos/ui/base/window_properties.h"
#include "chromeos/ui/base/window_state_type.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/hit_test_utils.h"
#include "ui/views/window/non_client_view.h"
namespace chromeos {
using WindowOpacity = views::Widget::InitParams::WindowOpacity;
int FrameBorderNonClientHitTest(views::NonClientFrameView* view,
const gfx::Point& point_in_widget) {
gfx::Rect expanded_bounds = view->bounds();
int outside_bounds = chromeos::kResizeOutsideBoundsSize;
if (aura::Env::GetInstance()->is_touch_down())
outside_bounds *= chromeos::kResizeOutsideBoundsScaleForTouch;
expanded_bounds.Inset(-outside_bounds);
if (!expanded_bounds.Contains(point_in_widget))
return HTNOWHERE;
// Check the frame first, as we allow a small area overlapping the contents
// to be used for resize handles.
views::Widget* widget = view->GetWidget();
bool in_tablet_mode = display::Screen::GetScreen()->InTabletMode();
// Ignore the resize border when maximized or full screen or in (split view)
// tablet mode.
const bool has_resize_border =
!widget->IsMaximized() && !widget->IsFullscreen() && !in_tablet_mode;
const int resize_border_size =
has_resize_border ? chromeos::kResizeInsideBoundsSize : 0;
int frame_component = view->GetHTComponentForFrame(
point_in_widget, gfx::Insets(resize_border_size),
chromeos::kResizeAreaCornerSize, chromeos::kResizeAreaCornerSize,
has_resize_border);
if (frame_component != HTNOWHERE)
return frame_component;
int client_component =
widget->client_view()->NonClientHitTest(point_in_widget);
if (client_component != HTNOWHERE)
return client_component;
// Check if it intersects with children (frame caption button, back button,
// etc.).
int hit_test_component =
views::GetHitTestComponent(widget->non_client_view(), point_in_widget);
if (hit_test_component != HTNOWHERE)
return hit_test_component;
// Caption is a safe default.
return HTCAPTION;
}
void ResolveInferredOpacity(views::Widget::InitParams* params) {
DCHECK_EQ(params->opacity, WindowOpacity::kInferred);
if (params->type == views::Widget::InitParams::TYPE_WINDOW &&
params->layer_type == ui::LAYER_TEXTURED) {
// A framed window may have a rounded corner which requires the
// window to be transparent. WindowManager controls the actual
// opaque-ness of the window depending on its window state.
params->init_properties_container.SetProperty(
chromeos::kWindowManagerManagesOpacityKey, true);
params->opacity = WindowOpacity::kTranslucent;
} else {
params->opacity = WindowOpacity::kOpaque;
}
}
bool ShouldUseRestoreFrame(const views::Widget* widget) {
aura::Window* window = widget->GetNativeWindow();
// This is true when dragging a maximized window in ash. During this phase,
// the window should look as if it was restored, but keep its maximized state.
if (window->GetProperty(chromeos::kFrameRestoreLookKey))
return true;
// Maximized and fullscreen windows should use the maximized frame.
if (widget->IsMaximized() || widget->IsFullscreen())
return false;
return true;
}
SnapDirection GetSnapDirectionForWindow(aura::Window* window, bool left_top) {
const bool is_primary_display_layout = chromeos::IsDisplayLayoutPrimary(
display::Screen::GetScreen()->GetDisplayNearestWindow(window));
if (left_top) {
return is_primary_display_layout ? SnapDirection::kPrimary
: SnapDirection::kSecondary;
} else {
return is_primary_display_layout ? SnapDirection::kSecondary
: SnapDirection::kPrimary;
}
}
gfx::RoundedCornersF GetWindowRadii(const aura::Window* window) {
if (!ShouldWindowHaveRoundedCorners(window)) {
return gfx::RoundedCornersF();
}
const WindowStateType window_state = window->GetProperty(kWindowStateTypeKey);
if (window_state == WindowStateType::kPip) {
return gfx::RoundedCornersF(kPipRoundedCornerRadius);
}
const int corner_radius = features::IsRoundedWindowsEnabled()
? features::RoundedWindowsRadius()
: kTopCornerRadiusWhenRestored;
const bool rounded_bottom_corners = features::IsRoundedWindowsEnabled();
return gfx::RoundedCornersF(corner_radius, corner_radius,
rounded_bottom_corners ? corner_radius : 0,
rounded_bottom_corners ? corner_radius : 0);
}
bool CanPropertyEffectWindowRadius(const void* class_property_key) {
return class_property_key == kIsShowingInOverviewKey ||
class_property_key == kWindowStateTypeKey;
}
bool ShouldWindowStateHaveRoundedCorners(WindowStateType type) {
return IsNormalWindowStateType(type) || type == WindowStateType::kFloated ||
type == WindowStateType::kPip;
}
bool ShouldWindowHaveRoundedCorners(const aura::Window* window) {
const WindowStateType window_state = window->GetProperty(kWindowStateTypeKey);
// In overview mode, the native window is displayed in `ash::WindowMiniView`
// with its own `ash::WindowMiniViewHeaderView`. This mini view has its own
// rounded corners. Therefore we do not need to round the native window.
// Apart from redundant rounding, rounding the native frame is problematic for
// browsers. For packaged apps, we hide the frame header but for browsers, we
// still show the header since the tab strip is rendered over the header. In
// overview mode, the header becomes a part of contents of WindowMiniView and
// rounding the header ends up rounding the top corners of the contents.
const bool in_overview = window->GetProperty(kIsShowingInOverviewKey);
return ShouldWindowStateHaveRoundedCorners(window_state) && !in_overview;
}
} // namespace chromeos
|