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
|
// Copyright 2015 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_EXO_SHELL_SURFACE_H_
#define COMPONENTS_EXO_SHELL_SURFACE_H_
#include "ash/focus_cycler.h"
#include "ash/wm/toplevel_window_event_handler.h"
#include "ash/wm/window_state_observer.h"
#include "base/containers/circular_deque.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "components/exo/shell_surface_base.h"
#include "components/exo/shell_surface_observer.h"
#include "ui/base/ui_base_types.h"
namespace ash {
class ScopedAnimationDisabler;
} // namespace ash
namespace ui {
class CompositorLock;
} // namespace ui
namespace exo {
class Surface;
// This class implements toplevel surface for which position and state are
// managed by the shell.
class ShellSurface : public ShellSurfaceBase, public ash::WindowStateObserver {
public:
// The |origin| is the initial position in screen coordinates. The position
// specified as part of the geometry is relative to the shell surface.
ShellSurface(Surface* surface,
const gfx::Point& origin,
bool can_minimize,
int container);
explicit ShellSurface(Surface* surface);
ShellSurface(const ShellSurface&) = delete;
ShellSurface& operator=(const ShellSurface&) = delete;
~ShellSurface() override;
// Set the callback to run when the client is asked to configure the surface.
// The size is a hint, in the sense that the client is free to ignore it if
// it doesn't resize, pick a smaller size (to satisfy aspect ratio or resize
// in steps of NxM pixels).
using ConfigureCallback =
base::RepeatingCallback<uint32_t(const gfx::Rect& bounds,
chromeos::WindowStateType state_type,
bool resizing,
bool activated,
const gfx::Vector2d& origin_offset,
float raster_scale)>;
using OriginChangeCallback =
base::RepeatingCallback<void(const gfx::Point& origin)>;
using RotateFocusCallback =
base::RepeatingCallback<uint32_t(ash::FocusCycler::Direction direction,
bool restart)>;
using OverviewChangeCallback =
base::RepeatingCallback<void(bool in_overview)>;
void set_configure_callback(const ConfigureCallback& configure_callback) {
configure_callback_ = configure_callback;
}
void set_origin_change_callback(
const OriginChangeCallback& origin_change_callback) {
origin_change_callback_ = origin_change_callback;
}
void set_rotate_focus_callback(const RotateFocusCallback callback) {
rotate_focus_callback_ = callback;
}
void set_overview_change_callback(const OverviewChangeCallback callback) {
overview_change_callback_ = callback;
}
// When the client is asked to configure the surface, it should acknowledge
// the configure request sometime before the commit. |serial| is the serial
// from the configure callback.
void AcknowledgeConfigure(uint32_t serial);
// Set the "parent" of this surface. This window should be stacked above a
// parent.
void SetParent(ShellSurface* parent);
bool CanMaximize() const override;
// Maximizes the shell surface.
void Maximize();
// Minimize the shell surface.
void Minimize();
// Restore the shell surface.
void Restore();
// Set fullscreen state for shell surface. When `fullscreen` is true,
// `display_id` indicates the id of the display where the surface should be
// shown on, otherwise it gets ignored. When `display::kInvalidDisplayId` is
// specified the current display will be used.
void SetFullscreen(bool fullscreen, int64_t display_id);
// Make the shell surface popup type.
void SetPopup();
// Invokes when the surface has reached the end of its own focus rotation.
// This signals ash to to continue its own focus rotation.
void AckRotateFocus(uint32_t serial, bool handled);
// Set event grab on the surface.
void Grab();
// Start an interactive resize of surface. |component| is one of the windows
// HT constants (see ui/base/hit_test.h) and describes in what direction the
// surface should be resized.
bool StartResize(int component);
// Start an interactive move of surface.
bool StartMove();
// Sends a wayland request to the surface to rotate focus within itself. If
// the client was able to rotate, it will return a "handled" response,
// otherwise it will respond with a "not handled" response.
// If the client does not support the wayland event, the base class'
// impl is invoked. In practice, this means that the surface will be focused,
// but it will not rotate focus within its panes.
bool RotatePaneFocusFromView(views::View* focused_view,
bool forward,
bool enable_wrapping) override;
// Return the initial show state for this surface.
ui::WindowShowState initial_show_state() { return initial_show_state_; }
void AddObserver(ShellSurfaceObserver* observer);
void RemoveObserver(ShellSurfaceObserver* observer);
// Overridden from SurfaceDelegate:
void OnSetFrame(SurfaceFrameType type) override;
void OnSetParent(Surface* parent, const gfx::Point& position) override;
// Overridden from ShellSurfaceBase:
void InitializeWindowState(ash::WindowState* window_state) override;
absl::optional<gfx::Rect> GetWidgetBounds() const override;
gfx::Point GetSurfaceOrigin() const override;
void SetUseImmersiveForFullscreen(bool value) override;
// Overridden from aura::WindowObserver:
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
void OnWindowAddedToRootWindow(aura::Window* window) override;
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old_value) override;
// Overridden from ash::WindowStateObserver:
void OnPreWindowStateTypeChange(ash::WindowState* window_state,
chromeos::WindowStateType old_type) override;
void OnPostWindowStateTypeChange(ash::WindowState* window_state,
chromeos::WindowStateType old_type) override;
// Overridden from wm::ActivationChangeObserver:
void OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
// Overridden from ShellSurfaceBase:
gfx::Rect ComputeAdjustedBounds(const gfx::Rect& bounds) const override;
void SetWidgetBounds(const gfx::Rect& bounds,
bool adjusted_by_server) override;
bool OnPreWidgetCommit() override;
std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
views::Widget* widget) override;
void EndDrag();
int resize_component_for_test() const { return resize_component_; }
private:
struct Config;
// Helper class used to coalesce a number of changes into one "configure"
// callback. Callbacks are suppressed while an instance of this class is
// instantiated and instead called when the instance is destroyed.
// If |force_configure_| is true ShellSurface::Configure() will be called
// even if no changes to shell surface took place during the lifetime of the
// ScopedConfigure instance.
class ScopedConfigure {
public:
ScopedConfigure(ShellSurface* shell_surface, bool force_configure);
ScopedConfigure(const ScopedConfigure&) = delete;
ScopedConfigure& operator=(const ScopedConfigure&) = delete;
~ScopedConfigure();
void set_needs_configure() { needs_configure_ = true; }
private:
const raw_ptr<ShellSurface, ExperimentalAsh> shell_surface_;
const bool force_configure_;
bool needs_configure_ = false;
};
// Set the parent window of this surface.
void SetParentWindow(aura::Window* parent);
// Sets up a transient window manager for this window if it can (i.e. if the
// surface has a widget with a parent).
void MaybeMakeTransient();
// Asks the client to configure its surface. Optionally, the user can override
// the behaviour to check for window dragging by setting ends_drag to true.
void Configure(bool ends_drag = false);
bool GetCanResizeFromSizeConstraints() const override;
bool AttemptToStartDrag(int component);
// Utility methods to resolve the initial bounds for the first commit.
gfx::Rect GetInitialBoundsForState(
const chromeos::WindowStateType state) const;
display::Display GetDisplayForInitialBounds() const;
std::unique_ptr<ash::ScopedAnimationDisabler> animations_disabler_;
std::unique_ptr<ui::CompositorLock> configure_compositor_lock_;
ConfigureCallback configure_callback_;
OriginChangeCallback origin_change_callback_;
RotateFocusCallback rotate_focus_callback_;
OverviewChangeCallback overview_change_callback_;
raw_ptr<ScopedConfigure, ExperimentalAsh> scoped_configure_ = nullptr;
base::circular_deque<std::unique_ptr<Config>> pending_configs_;
// Stores the config which is acked but not yet committed. This will keep the
// compositor locked until reset after Commit() is called.
std::unique_ptr<Config> config_waiting_for_commit_;
// Window resizing is an asynchronous operation. See
// https://crbug.com/1336706#c22 for a more detailed explanation.
// |origin_offset_| is typically (0,0). During an asynchronous resizing
// |origin_offset_| is set to a non-zero value such that it appears as though
// the ExoShellSurfaceHost has not moved even though ExoShellSurface has
// already been moved and resized to the new position.
gfx::Vector2d origin_offset_;
gfx::Vector2d pending_origin_offset_;
gfx::Vector2d pending_origin_offset_accumulator_;
gfx::Rect old_screen_bounds_for_pending_move_;
int resize_component_ = HTCAPTION; // HT constant (see ui/base/hit_test.h)
int pending_resize_component_ = HTCAPTION;
// TODO(oshima): Use WindowStateType instead.
ui::WindowShowState initial_show_state_ = ui::SHOW_STATE_DEFAULT;
bool notify_bounds_changes_ = true;
bool window_state_is_changing_ = false;
float pending_raster_scale_ = 1.0;
struct InflightFocusRotateRequest {
uint32_t serial;
ash::FocusCycler::Direction direction;
};
std::queue<InflightFocusRotateRequest> rotate_focus_inflight_requests_;
base::ObserverList<ShellSurfaceObserver> observers_;
};
} // namespace exo
#endif // COMPONENTS_EXO_SHELL_SURFACE_H_
|