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
ash / wm / tablet_mode / tablet_mode_toggle_fullscreen_event_handler.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/wm/tablet_mode/tablet_mode_toggle_fullscreen_event_handler.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
namespace ash {
namespace {
// The height of the area in which a touch operation leads to exiting the
// full screen mode.
constexpr int kLeaveFullScreenAreaHeightInPixel = 2;
} // namespace
TabletModeToggleFullscreenEventHandler::
TabletModeToggleFullscreenEventHandler() {
Shell::Get()->AddPreTargetHandler(this);
}
TabletModeToggleFullscreenEventHandler::
~TabletModeToggleFullscreenEventHandler() {
ResetDragData();
Shell::Get()->RemovePreTargetHandler(this);
}
void TabletModeToggleFullscreenEventHandler::OnTouchEvent(
ui::TouchEvent* event) {
if (ProcessEvent(*event)) {
event->SetHandled();
event->StopPropagation();
}
}
void TabletModeToggleFullscreenEventHandler::OnWindowDestroying(
aura::Window* window) {
DCHECK(drag_data_);
DCHECK_EQ(drag_data_->window, window);
ResetDragData();
}
bool TabletModeToggleFullscreenEventHandler::ProcessEvent(
const ui::TouchEvent& event) {
switch (event.type()) {
case ui::EventType::kTouchPressed: {
// Another drag is already underway from another finger.
if (drag_data_) {
return false;
}
aura::Window* active_window = window_util::GetActiveWindow();
if (!active_window || !CanToggleFullscreen(active_window))
return false;
const int y = event.y();
// For touch press events only process the ones on the top or bottom
// lines.
if (y >= kLeaveFullScreenAreaHeightInPixel &&
y < (active_window->bounds().height() -
kLeaveFullScreenAreaHeightInPixel)) {
return false;
}
drag_data_ = DragData{.start_y_location = y, .window = active_window};
active_window->AddObserver(this);
return true;
}
case ui::EventType::kTouchReleased: {
if (!drag_data_)
return false;
// Toggle fullscreen if dragged enough and the window can still be
// fullscreened.
const int drag_threshold =
ShelfConfig::Get()->shelf_size() *
ShelfConfig::Get()->drag_hide_ratio_threshold();
if (abs(event.y() - drag_data_->start_y_location) > drag_threshold &&
CanToggleFullscreen(drag_data_->window)) {
WMEvent toggle_fullscreen(WM_EVENT_TOGGLE_FULLSCREEN);
WindowState::Get(drag_data_->window)->OnWMEvent(&toggle_fullscreen);
}
ResetDragData();
return true;
}
case ui::EventType::kTouchMoved:
return drag_data_.has_value();
case ui::EventType::kTouchCancelled: {
const bool drag_in_progress = drag_data_.has_value();
ResetDragData();
return drag_in_progress;
}
default:
break;
}
NOTREACHED();
}
bool TabletModeToggleFullscreenEventHandler::CanToggleFullscreen(
const aura::Window* window) {
DCHECK(window);
const SessionControllerImpl* controller = Shell::Get()->session_controller();
if (controller->IsScreenLocked() ||
controller->GetSessionState() != session_manager::SessionState::ACTIVE) {
return false;
}
// Find the active window (from the primary screen) to un-fullscreen.
aura::Window* active_window = window_util::GetActiveWindow();
if (window != active_window)
return false;
const WindowState* window_state = WindowState::Get(window);
if (!window_state->IsFullscreen() || window_state->IsInImmersiveFullscreen())
return false;
// Do not exit fullscreen in kiosk app mode.
if (Shell::Get()->session_controller()->IsRunningInAppMode())
return false;
return true;
}
void TabletModeToggleFullscreenEventHandler::ResetDragData() {
if (drag_data_)
drag_data_->window->RemoveObserver(this);
drag_data_.reset();
}
} // namespace ash