File: immersive_fullscreen_controller.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (328 lines) | stat: -rw-r--r-- 12,692 bytes parent folder | download | duplicates (6)
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_UI_FRAME_IMMERSIVE_IMMERSIVE_FULLSCREEN_CONTROLLER_H_
#define CHROMEOS_UI_FRAME_IMMERSIVE_IMMERSIVE_FULLSCREEN_CONTROLLER_H_

#include <memory>
#include <vector>

#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "chromeos/ui/frame/immersive/immersive_revealed_lock.h"
#include "ui/aura/window_observer.h"
#include "ui/events/event_handler.h"
#include "ui/events/event_observer.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/widget_observer.h"

namespace aura {
class WindowTargeter;
}  // namespace aura

namespace ash {
class ImmersiveFullscreenControllerTest;
}  // namespace ash

namespace gfx {
class Point;
}  // namespace gfx

namespace ui {
class GestureEvent;
class LocatedEvent;
class MouseEvent;
class TouchEvent;
}  // namespace ui

namespace views {
class View;
class Widget;
}  // namespace views

namespace chromeos {

class ImmersiveFocusWatcher;
class ImmersiveFullscreenControllerDelegate;
class ImmersiveFullscreenControllerTestApi;

// This class is tested as part of //ash, eg ImmersiveFullscreenControllerTest,
// which inherits from AshTestBase.
class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) ImmersiveFullscreenController
    : public aura::WindowObserver,
      public gfx::AnimationDelegate,
      public ui::EventObserver,
      public ui::EventHandler,
      public views::ViewObserver,
      public views::WidgetObserver,
      public ImmersiveRevealedLock::Delegate {
 public:
  // How many pixels are reserved for touch-events towards the top of an
  // immersive-fullscreen window.
  static const int kImmersiveFullscreenTopEdgeInset;

  // The height in pixels of the region below the top edge of the display in
  // which the mouse can trigger revealing the top-of-window views. The height
  // must be greater than 1px because the top pixel is used to trigger moving
  // the cursor between displays if the user has a vertical display layout
  // (primary display above/below secondary display).
  static const int kMouseRevealBoundsHeight;

  ImmersiveFullscreenController();

  ImmersiveFullscreenController(const ImmersiveFullscreenController&) = delete;
  ImmersiveFullscreenController& operator=(
      const ImmersiveFullscreenController&) = delete;

  ~ImmersiveFullscreenController() override;

  // Initializes the controller. Must be called prior to enabling immersive
  // fullscreen via EnableForWidget(). |top_container| is used to keep the
  // top-of-window views revealed when a child of |top_container| has focus.
  // |top_container| does not affect which mouse and touch events keep the
  // top-of-window views revealed. |widget| is the widget to make fullscreen.
  void Init(ImmersiveFullscreenControllerDelegate* delegate,
            views::Widget* widget,
            views::View* top_container);

  // Returns true if in immersive fullscreen.
  bool IsEnabled() const;

  // Returns true if in immersive fullscreen and the top-of-window views are
  // fully or partially visible.
  bool IsRevealed() const;

  // Returns a lock which will keep the top-of-window views revealed for its
  // lifetime. Several locks can be obtained. When all of the locks are
  // destroyed, if immersive fullscreen is enabled and there is nothing else
  // keeping the top-of-window views revealed, the top-of-window views will be
  // closed. This method always returns a valid lock regardless of whether
  // immersive fullscreen is enabled. The lock's lifetime can span immersive
  // fullscreen being enabled / disabled. If acquiring the lock causes a reveal,
  // the top-of-window views will animate according to |animate_reveal|. The
  // caller takes ownership of the returned lock.
  [[nodiscard]] ImmersiveRevealedLock* GetRevealedLock(
      AnimateReveal animate_reveal);

  views::Widget* widget() { return widget_; }
  views::View* top_container() { return top_container_; }

  // ui::EventObserver:
  void OnEvent(const ui::Event& event) override;

  // ui::EventHandler:
  void OnEvent(ui::Event* event) override;
  void OnGestureEvent(ui::GestureEvent* event) override;

  // aura::WindowObserver:
  void OnWindowPropertyChanged(aura::Window* window,
                               const void* key,
                               intptr_t old) override;
  void OnWindowDestroying(aura::Window* window) override;

  // views::ViewObserver:
  void OnViewBoundsChanged(views::View* observed_view) override;
  void OnViewIsDeleting(views::View* observed_view) override;

  // views::WidgetObserver:
  void OnWidgetDestroyed(views::Widget* widget) override;

  // gfx::AnimationDelegate overrides:
  void AnimationEnded(const gfx::Animation* animation) override;
  void AnimationProgressed(const gfx::Animation* animation) override;

  // chromeos::ImmersiveRevealedLock::Delegate overrides:
  void LockRevealedState(AnimateReveal animate_reveal) override;
  void UnlockRevealedState() override;

  static void EnableForWidget(views::Widget* widget, bool enabled);

  static ImmersiveFullscreenController* Get(views::Widget* widget);

 private:
  friend class ash::ImmersiveFullscreenControllerTest;
  friend class ImmersiveFullscreenControllerTestApi;

  enum Animate {
    ANIMATE_NO,
    ANIMATE_SLOW,
    ANIMATE_FAST,
  };
  enum RevealState {
    CLOSED,
    SLIDING_OPEN,
    REVEALED,
    SLIDING_CLOSED,
  };
  enum SwipeType { SWIPE_OPEN, SWIPE_CLOSE, SWIPE_NONE };

  // Enables or disables observers for the widget's aura::Window and
  // |top_container_|.
  void EnableWindowObservers(bool enable);

  // Enables or disables observers for mouse, touch, focus, and activation.
  void EnableEventObservers(bool enable);

  // Called to handle EventObserver::OnEvent.
  void HandleMouseEvent(const ui::MouseEvent& event,
                        const gfx::Point& location_in_screen,
                        views::Widget* target);
  void HandleTouchEvent(const ui::TouchEvent& event,
                        const gfx::Point& location_in_screen);

  // Updates |top_edge_hover_timer_| based on a mouse |event|. If the mouse is
  // hovered at the top of the screen the timer is started. If the mouse moves
  // away from the top edge, or moves too much in the x direction, the timer is
  // stopped.
  void UpdateTopEdgeHoverTimer(const ui::MouseEvent& event,
                               const gfx::Point& location_in_screen,
                               views::Widget* target);

  // Updates |located_event_revealed_lock_| based on the current mouse state and
  // the current touch state.
  // |event| is null if the source event is not known.
  void UpdateLocatedEventRevealedLock(const ui::LocatedEvent* event,
                                      const gfx::Point& location_in_screen);

  // Convenience for calling two argument version with a null event and looking
  // up the location from the last mouse location.
  void UpdateLocatedEventRevealedLock();

  // Acquires |located_event_revealed_lock_| if it is not already held.
  void AcquireLocatedEventRevealedLock();

  // Updates |focus_revealed_lock_| based on the currently active view and the
  // currently active widget.
  void UpdateFocusRevealedLock();

  // Update |located_event_revealed_lock_| and |focus_revealed_lock_| as a
  // result of a gesture of |swipe_type|. Returns true if any locks were
  // acquired or released.
  bool UpdateRevealedLocksForSwipe(SwipeType swipe_type);

  // Returns the animation duration given |animate|.
  base::TimeDelta GetAnimationDuration(Animate animate) const;

  // Temporarily reveals the top-of-window views while in immersive mode,
  // hiding them when the cursor exits the area of the top views. If |animate|
  // is not ANIMATE_NO, slides in the view, otherwise shows it immediately.
  void MaybeStartReveal(Animate animate);

  // Called when the animation to slide open the top-of-window views has
  // completed.
  void OnSlideOpenAnimationCompleted();

  // Hides the top-of-window views if immersive mode is enabled and nothing is
  // keeping them revealed. Optionally animates.
  void MaybeEndReveal(Animate animate);

  // Called when the animation to slide out the top-of-window views has
  // completed.
  void OnSlideClosedAnimationCompleted();

  // Returns the type of swipe given |event|.
  SwipeType GetSwipeType(const ui::GestureEvent& event) const;

  // Returns true if a mouse event at |location_in_screen| should be ignored.
  // Ignored mouse events should not contribute to revealing or unrevealing the
  // top-of-window views.
  bool ShouldIgnoreMouseEventAtLocation(
      const gfx::Point& location_in_screen) const;

  // True when |location| is "near" to the top container. When the top container
  // is not closed "near" means within the displayed bounds or above it. When
  // the top container is closed "near" means either within the displayed
  // bounds, above it, or within a few pixels below it. This allow the container
  // to steal enough pixels to detect a swipe in and handles the case that there
  // is a bezel sensor above the top container.
  bool ShouldHandleGestureEvent(const gfx::Point& location) const;

  // Returns the display bounds of the screen |widget_| is on.
  gfx::Rect GetDisplayBoundsInScreen() const;

  // Test if the |widget| is the event target to control reveal state.
  bool IsTargetForWidget(views::Widget* widget) const;

  // Enables or disables immersive fullscreen in accordance with the
  // kImmersiveIsActive property.
  void UpdateEnabled();

  // Adds insets that redirect touch events at the top of the Widget to the
  // Widget's window instead of a child window. These insets allow triggering
  // immersive reveal and are not used when the immersive reveal is already
  // active.
  void EnableTouchInsets(bool enable);

  // Do the cleanup when the widget or aura::Window is about to destroy.
  // The destruction order of widget and aura::Window depends on the widget
  // ownership mode, so we need to watch for the destruction of both and do the
  // cleanup.
  void CleanupOnWindowDestroy();

  // Not owned.
  raw_ptr<ImmersiveFullscreenControllerDelegate, DanglingUntriaged> delegate_ =
      nullptr;
  raw_ptr<views::View, DanglingUntriaged> top_container_ = nullptr;
  raw_ptr<views::Widget, DanglingUntriaged> widget_ = nullptr;

  base::ScopedObservation<views::Widget, views::WidgetObserver>
      widget_observation_{this};

  // True if the observers have been enabled.
  bool event_observers_enabled_ = false;

  // True when in immersive fullscreen.
  bool enabled_ = false;

  // State machine for the revealed/closed animations.
  RevealState reveal_state_ = CLOSED;

  int revealed_lock_count_ = 0;

  // Timer to track cursor being held at the top edge of the screen.
  base::OneShotTimer top_edge_hover_timer_;

  // The cursor x position in screen coordinates when the cursor first hit the
  // top edge of the screen.
  int mouse_x_when_hit_top_in_screen_ = -1;

  // Tracks if the controller has seen a EventType::kGestureScrollBegin, without
  // the following events.
  bool gesture_begun_ = false;

  // Lock which keeps the top-of-window views revealed based on the current
  // mouse state and the current touch state. Acquiring the lock is used to
  // trigger a reveal when the user moves the mouse to the top of the screen
  // and when the user does a SWIPE_OPEN edge gesture.
  std::unique_ptr<ImmersiveRevealedLock> located_event_revealed_lock_;

  std::unique_ptr<gfx::AnimationDelegate> animation_notifier_;

  // The animation which controls sliding the top-of-window views in and out.
  std::unique_ptr<gfx::SlideAnimation> animation_;

  // Whether the animations are disabled for testing.
  bool animations_disabled_for_test_;

  std::unique_ptr<ImmersiveFocusWatcher> immersive_focus_watcher_;

  // The window targeter that was in use before immersive fullscreen mode was
  // entered, if any. Will be re-installed on the window after leaving immersive
  // fullscreen.
  std::unique_ptr<aura::WindowTargeter> normal_targeter_;

  // |animations_disabled_for_test_| is initialized to this. See
  // ImmersiveFullscreenControllerTestApi::GlobalAnimationDisabler for details.
  static bool value_for_animations_disabled_for_test_;

  base::WeakPtrFactory<ImmersiveFullscreenController> weak_ptr_factory_{this};
};

}  // namespace chromeos

#endif  // CHROMEOS_UI_FRAME_IMMERSIVE_IMMERSIVE_FULLSCREEN_CONTROLLER_H_