File: native_widget_ns_window_fullscreen_controller.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (196 lines) | stat: -rw-r--r-- 7,941 bytes parent folder | download | duplicates (8)
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
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_NS_WINDOW_FULLSCREEN_CONTROLLER_H_
#define COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_NS_WINDOW_FULLSCREEN_CONTROLLER_H_

#include <optional>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h"
#include "ui/display/types/display_constants.h"
#include "ui/gfx/geometry/rect.h"

namespace remote_cocoa {

class NativeWidgetNSWindowBridge;

class REMOTE_COCOA_APP_SHIM_EXPORT NativeWidgetNSWindowFullscreenController {
 public:
  class Client {
   public:
    // Called when a transition between fullscreen and windowed (or vice-versa).
    // If `is_target_fullscreen` is true, then the target of the transition is
    // fullscreen.
    virtual void FullscreenControllerTransitionStart(
        bool is_target_fullscreen) = 0;

    // Called when a transition between fullscreen and windowed is complete.
    // If `is_fullscreen` is true, then the window is now fullscreen.
    virtual void FullscreenControllerTransitionComplete(bool is_fullscreen) = 0;

    // Set the window's frame to the specified rectangle. If `animate` is true,
    // then animate the transition. Runs the `completion_callback` callback once
    // the animation is complete, or immediately when `animate` is false.
    virtual void FullscreenControllerSetFrame(
        const gfx::Rect& frame,
        bool animate,
        base::OnceCallback<void()> completion_callback) = 0;

    // Call -[NSWindow toggleFullscreen:].
    virtual void FullscreenControllerToggleFullscreen() = 0;

    // Call -[NSWindow close]. Note that this call may result in the caller
    // being destroyed.
    virtual void FullscreenControllerCloseWindow() = 0;

    // Return the display id for the display that the window is currently on.
    virtual int64_t FullscreenControllerGetDisplayId() const = 0;

    // Return the frame that should be set prior to transitioning to fullscreen
    // on the display specified by `display_id`. If `display_id` is invalid,
    // then return an empty rectangle.
    virtual gfx::Rect FullscreenControllerGetFrameForDisplay(
        int64_t display_id) const = 0;

    // Get the window's current frame.
    virtual gfx::Rect FullscreenControllerGetFrame() const = 0;
  };

  explicit NativeWidgetNSWindowFullscreenController(Client* client);
  NativeWidgetNSWindowFullscreenController(
      const NativeWidgetNSWindowFullscreenController&) = delete;
  NativeWidgetNSWindowFullscreenController& operator=(
      const NativeWidgetNSWindowFullscreenController&) = delete;
  ~NativeWidgetNSWindowFullscreenController();

  // Called by NativeWidget::SetFullscreen.
  void EnterFullscreen(int64_t target_display_id);
  void ExitFullscreen();

  // Called from NativeWidgetNSWindowBridge:CloseWindow, indicating that the
  // window has been requested to be closed. If a transition is in progress,
  // then the close will be deferred until after the transition completes.
  void OnWindowWantsToClose();

  // Return true if an active transition has caused closing of the window to be
  // deferred.
  bool HasDeferredWindowClose() const { return has_deferred_window_close_; }

  // Called by NativeWidgetNSWindowBridge::OnWindowWillClose.
  void OnWindowWillClose();

  // Called by -[NSWindowDelegate windowWill/DidEnter/ExitFullScreen:].
  void OnWindowWillEnterFullscreen();
  void OnWindowDidEnterFullscreen();
  void OnWindowWillExitFullscreen();
  void OnWindowDidExitFullscreen();

  // Return false unless the state is kWindowed or kFullscreen.
  bool IsInFullscreenTransition() const;

  // Return true if the window can be resized. The window cannot be resized
  // while fullscreen or during a transition.
  bool CanResize() const;

  // Return the fullscreen state that will be arrived at when all transition
  // is done.
  bool GetTargetFullscreenState() const;

 private:
  enum class State {
    // In windowed mode.
    kWindowed,
    // Moving the window to the target display on which it will go fullscreen.
    kWindowedMovingToFullscreenTarget,
    // In transition to enter fullscreen mode. This encompasses the following
    // states:
    // - From the kWindowed state, a task for ToggleFullscreen has been
    //   posted.
    // - OnWindowWillEnterFullscreen has been called (either as a result of
    //   ToggleFullscreen, or as a result of user interaction), but neither
    //   OnWindowDidEnterFullscreen nor OnWindowDidExitFullscreen have been
    //   called yet.
    kEnterFullscreenTransition,
    // In fullscreen mode.
    kFullscreen,
    // In transition to exit fullscreen mode. This encompasses the following
    // states:
    // - From the kFullscreen state, a task for ToggleFullscreen has been
    //   posted.
    // - OnWindowWillExitFullscreen has been called (either as a result of
    //   ToggleFullscreen, or as a result of user interaction), but neither
    //   OnWindowDidExitFullscreen nor OnWindowDidEnterFullscreen have been
    //   called yet.
    kExitFullscreenTransition,
    // Moving the window back to its original position from before it entered
    // fullscreen.
    kWindowedRestoringOriginalFrame,
    // The window has been closed.
    kClosed,
  };
  struct PendingState {
    bool is_fullscreen = false;
    int64_t display_id = display::kInvalidDisplayId;
  };

  // Move the window to `target_display_id`, and then post a task to go
  // fullscreen.
  void MoveToTargetDisplayThenToggleFullscreen(int64_t target_display_id);

  // Set the window's frame back to `windowed_frame_`, and then return to
  // the kWindowed state.
  void RestoreWindowedFrame();
  // Notifies the client that the fullscreen exit transition has completed after
  // the frame has been restored to its original position.
  void OnWindowedFrameRestored();

  // Helper function wrapping -[NSWindow toggleFullscreen:].
  void ToggleFullscreen();

  // If not currently in transition, consume `pending_state_` and start a
  // transition to the state it specifies.
  void HandlePendingState();

  // If there exists a deferred close, then close the window, set the
  // current state to kClosed, and return true.
  bool HandleDeferredClose();

  // Set `state` to `new_state`, and invalidate any posted tasks. Posted tasks
  // exist to transition from the current state to a new state, and so if the
  // current state changes, then those tasks are no longer applicable.
  void SetStateAndCancelPostedTasks(State new_state);

  State state_ = State::kWindowed;

  // If a call to EnterFullscreen or ExitFullscreen happens during a
  // transition, then that final requested state is stored in `pending_state_`.
  std::optional<PendingState> pending_state_;

  // If we call setFrame while in fullscreen transitions, then we will need to
  // restore the original window frame when we return to windowed mode. We save
  // that original frame in `windowed_frame_`, and set set
  // `restore_windowed_frame_` to true if we call setFrame.
  bool restore_windowed_frame_ = false;
  std::optional<gfx::Rect> windowed_frame_;

  // Trying to close an NSWindow during a fullscreen transition will cause the
  // window to lock up. Use this to track if CloseWindow was called during a
  // fullscreen transition, to defer the -[NSWindow close] call until the
  // transition is complete.
  // https://crbug.com/945237
  bool has_deferred_window_close_ = false;

  // Weak, owns `this`.
  const raw_ptr<Client> client_;
  base::WeakPtrFactory<NativeWidgetNSWindowFullscreenController> weak_factory_{
      this};
};

}  // namespace remote_cocoa

#endif  // COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_NS_WINDOW_FULLSCREEN_CONTROLLER_H_