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
ash / shelf / shelf_window_targeter.cc [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/shelf/shelf_window_targeter.h"
#include "ash/public/cpp/session/session_types.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ui/aura/window.h"
namespace ash {
namespace {
gfx::Insets GetInsetsForAlignment(int distance, ShelfAlignment alignment) {
if (alignment == ShelfAlignment::kLeft) {
return gfx::Insets::TLBR(0, 0, 0, distance);
}
if (alignment == ShelfAlignment::kRight) {
return gfx::Insets::TLBR(0, distance, 0, 0);
}
return gfx::Insets::TLBR(distance, 0, 0, 0);
}
} // namespace
ShelfWindowTargeter::ShelfWindowTargeter(aura::Window* container, Shelf* shelf)
: ::wm::EasyResizeWindowTargeter(gfx::Insets(), gfx::Insets()),
shelf_(shelf) {
UpdateInsetsForVisibilityState(shelf_->GetVisibilityState());
container->AddObserver(this);
shelf_->AddObserver(this);
Shell::Get()->AddShellObserver(this);
}
ShelfWindowTargeter::~ShelfWindowTargeter() {
// Ensure that the observers were removed and the shelf pointer was cleared.
DCHECK(!shelf_);
Shell::Get()->RemoveShellObserver(this);
}
bool ShelfWindowTargeter::ShouldUseExtendedBounds(const aura::Window* w) const {
// Use extended bounds only for direct child of the container.
return window() == w->parent();
}
bool ShelfWindowTargeter::GetHitTestRects(
aura::Window* target,
gfx::Rect* hit_test_rect_mouse,
gfx::Rect* hit_test_rect_touch) const {
bool target_is_shelf_widget =
target == shelf_->shelf_widget()->GetNativeWindow();
*hit_test_rect_mouse = *hit_test_rect_touch = target->bounds();
if (ShouldUseExtendedBounds(target)) {
hit_test_rect_mouse->Inset(mouse_extend());
// Whether the touch hit area should be extended beyond the window top when
// the shelf is in auto-hide state (to make targeting hidden shelf easier).
// This should be applied for shelf widget only, to prevent other widgets
// positioned below display bounds (e.g. hidden hotseat widget) from
// handling touch events instead of the shelf.
if (target_is_shelf_widget)
hit_test_rect_touch->Inset(touch_extend());
}
return true;
}
void ShelfWindowTargeter::OnWindowDestroying(aura::Window* window) {
window->RemoveObserver(this);
shelf_->RemoveObserver(this);
shelf_ = nullptr;
}
void ShelfWindowTargeter::OnShelfAlignmentChanged(
aura::Window* root_window,
ShelfAlignment old_alignment) {
if (!shelf_) {
return;
}
if (shelf_->shelf_widget()->GetNativeWindow()->GetRootWindow() !=
root_window) {
return;
}
UpdateInsets();
}
void ShelfWindowTargeter::OnShelfVisibilityStateChanged(
ShelfVisibilityState new_state) {
UpdateInsetsForVisibilityState(new_state);
}
void ShelfWindowTargeter::UpdateInsetsForVisibilityState(
ShelfVisibilityState state) {
mouse_inset_size_for_shelf_visibility_ =
state == SHELF_VISIBLE
? ShelfConfig::Get()->workspace_area_visible_inset()
: 0;
touch_inset_size_for_shelf_visibility_ =
state == SHELF_AUTO_HIDE
? -ShelfConfig::Get()->workspace_area_auto_hide_inset()
: 0;
UpdateInsets();
}
void ShelfWindowTargeter::UpdateInsets() {
const gfx::Insets mouse_insets = GetInsetsForAlignment(
mouse_inset_size_for_shelf_visibility_, shelf_->alignment());
const gfx::Insets touch_insets = GetInsetsForAlignment(
touch_inset_size_for_shelf_visibility_, shelf_->alignment());
// Remember the insets. See GetHitTestsRects when they're actually used.
SetInsets(mouse_insets, touch_insets);
}
} // namespace ash