blob: eb8c4f58001a9707dc1a4285199aa6062616aff1 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_TOPLEVEL_WINDOW_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_TOPLEVEL_WINDOW_H_
#include <memory>
#include <optional>
#include <ostream>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
#include "ui/ozone/platform/wayland/host/xdg_session.h"
#include "ui/ozone/public/platform_session_manager.h"
#include "ui/platform_window/extensions/system_modal_extension.h"
#include "ui/platform_window/extensions/wayland_extension.h"
#include "ui/platform_window/extensions/workspace_extension.h"
#include "ui/platform_window/extensions/workspace_extension_delegate.h"
#include "ui/platform_window/wm/wm_move_loop_handler.h"
#include "ui/platform_window/wm/wm_move_resize_handler.h"
namespace views::corewm {
enum class TooltipTrigger;
} // namespace views::corewm
namespace ui {
class OrgKdeKwinAppmenu;
class XdgToplevel;
class WaylandToplevelWindow : public WaylandWindow,
public WmMoveResizeHandler,
public WmMoveLoopHandler,
public WaylandToplevelExtension,
public WorkspaceExtension,
public SystemModalExtension,
public XdgSession::Observer {
public:
WaylandToplevelWindow(PlatformWindowDelegate* delegate,
WaylandConnection* connection);
WaylandToplevelWindow(const WaylandToplevelWindow&) = delete;
WaylandToplevelWindow& operator=(const WaylandToplevelWindow&) = delete;
~WaylandToplevelWindow() override;
XdgToplevel* xdg_toplevel() const { return xdg_toplevel_.get(); }
// Sets the window's origin.
void SetOrigin(const gfx::Point& origin);
// Notify that this window's active state may change.
void UpdateActivationState();
// WaylandWindow overrides:
void UpdateWindowScale(bool update_bounds) override;
WaylandToplevelWindow* AsWaylandToplevelWindow() override;
// Configure related:
void HandleToplevelConfigure(int32_t width,
int32_t height,
const WindowStates& window_states) override;
void HandleToplevelConfigureWithOrigin(
int32_t x,
int32_t y,
int32_t width,
int32_t height,
const WindowStates& window_states) override;
void HandleSurfaceConfigure(uint32_t serial) override;
void OnSequencePoint(int64_t seq) override;
bool IsSurfaceConfigured() override;
void AckConfigure(uint32_t serial) override;
bool OnInitialize(PlatformWindowInitProperties properties,
PlatformWindowDelegate::State* state) override;
bool IsActive() const override;
bool IsSuspended() const override;
void SetWindowGeometry(const PlatformWindowDelegate::State& state) override;
base::WeakPtr<WaylandWindow> AsWeakPtr() override;
// WmDragHandler:
bool ShouldReleaseCaptureForDrag(ui::OSExchangeData* data) const override;
// WmMoveResizeHandler
void DispatchHostWindowDragMovement(
int hittest,
const gfx::Point& pointer_location_in_px) override;
// PlatformWindow:
void Show(bool inactive) override;
void Hide() override;
bool IsVisible() const override;
void SetTitle(const std::u16string& title) override;
void SetFullscreen(bool fullscreen, int64_t target_display_id) override;
void Maximize() override;
void Minimize() override;
void Restore() override;
void ShowWindowControlsMenu(const gfx::Point& point) override;
void Activate() override;
void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) override;
void SizeConstraintsChanged() override;
// `SetZOrderLevel()` must be called on `z_order_` in
// `SetUpShellIntegration()`.
void SetZOrderLevel(ZOrderLevel order) override;
ZOrderLevel GetZOrderLevel() const override;
std::string GetWindowUniqueId() const override;
// SetUseNativeFrame and ShouldUseNativeFrame decide on
// xdg-decoration mode for a window.
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
bool ShouldUpdateWindowShape() const override;
bool CanSetDecorationInsets() const override;
void SetOpaqueRegion(
std::optional<std::vector<gfx::Rect>> region_px) override;
void SetInputRegion(std::optional<std::vector<gfx::Rect>> region_px) override;
bool IsClientControlledWindowMovementSupported() const override;
// WmMoveLoopHandler:
bool RunMoveLoop(const gfx::Vector2d& drag_offset) override;
void EndMoveLoop() override;
// WaylandToplevelExtension:
void StartWindowDraggingSessionIfNeeded(
ui::mojom::DragEventSource event_source,
bool allow_system_drag) override;
bool SupportsPointerLock() override;
void LockPointer(bool enabled) override;
void SetAppmenu(const std::string& service_name,
const std::string& object_path) override;
void UnsetAppmenu() override;
// WorkspaceExtension:
std::string GetWorkspace() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
void SetWorkspaceExtensionDelegate(
WorkspaceExtensionDelegate* delegate) override;
// SystemModalExtension:
void SetSystemModal(bool modal) override;
void DumpState(std::ostream& out) const override;
// XdgSession::Observer:
void OnSessionDestroying() override;
private:
// XdgToplevelSession instances are owned by toplevel windows, given their
// close lifecycle, though ownership might be transferred to the associated
// XdgSession, during removals, for example. To make this relationship more
// explicit and keep the public API clean and concise, friendship is used
// here. See XdgSession::RemoveToplevel for further context.
friend class XdgSession;
std::unique_ptr<XdgToplevelSession> TakeToplevelSession() {
return std::move(toplevel_session_);
}
std::string session_id() const {
return session_data_ ? session_data_->session_id : "";
}
int32_t session_toplevel_id() const {
return session_data_ ? session_data_->window_id : 0;
}
// WaylandWindow protected overrides:
// Calls UpdateWindowShape, set_input_region and set_opaque_region for this
// toplevel window.
void UpdateWindowMask() override;
void UpdateSystemModal();
void TriggerStateChanges(PlatformWindowState window_state);
// Sets the new window `state` to the window. `target_display_id` gets ignored
// unless the state is `PlatformWindowState::kFullscreen`.
void SetWindowState(PlatformWindowState state, int64_t target_display_id);
bool ShouldTriggerStateChange(PlatformWindowState state,
int64_t target_display_id) const;
// Activates the surface using XDG activation given an activation token.
void ActivateWithToken(std::string token);
WaylandOutput* GetWaylandOutputForDisplayId(int64_t display_id);
// Creates and initializes the underlying xdg_toplevel surface, which
// is the protocol object the makes it possible for this map this as a
// toplevel window.
bool CreateXdgToplevel();
WmMoveResizeHandler* AsWmMoveResizeHandler();
// Propagates the minimum size and maximum size to the ShellToplevel.
void SetSizeConstraints();
// Initializes additional shell integration, if the appropriate interfaces are
// available.
void SetUpShellIntegration();
// Sets decoration mode for a window.
void OnDecorationModeChanged();
// Issues session management requests, if needed, at mapping- and
// configure-time stages of the toplevel window initialization.
void UpdateSessionStateIfNeeded();
// Try to announce the appmenu associated with this toplevel, if there's any.
void TryAnnounceAppmenu();
std::unique_ptr<XdgToplevel> xdg_toplevel_;
// True if it's maximized before requesting the window state change from the
// client.
bool previously_maximized_ = false;
// The display ID to switch to in case the state is `kFullscreen`.
int64_t fullscreen_display_id_ = display::kInvalidDisplayId;
bool is_active_ = false;
bool is_xdg_active_ = false;
bool is_suspended_ = false;
// Id of the chromium app passed through
// PlatformWindowInitProperties::wm_class_name. This is used by Wayland
// compositor to identify the app, unite it's windows into the same stack of
// windows and find *.desktop file to set various preferences including icons.
std::string app_id_;
// Title of the ShellToplevel.
std::u16string window_title_;
// When use_native_frame is false, client-side decoration is set.
// When use_native_frame is true, server-side decoration is set.
bool use_native_frame_ = false;
std::optional<std::vector<gfx::Rect>> opaque_region_px_;
std::optional<std::vector<gfx::Rect>> input_region_px_;
// Current modal status.
bool system_modal_ = false;
// The desk index for the window.
// If |workspace_| is -1, window is visible on all workspaces.
std::optional<int> workspace_ = std::nullopt;
// The z order for the window.
ZOrderLevel z_order_ = ZOrderLevel::kNormal;
// Activation will only be done if the surface is configured.
// If it is requested before, it is stored and executed in ack configure.
std::optional<std::string> pending_configure_activation_token_ = std::nullopt;
raw_ptr<WorkspaceExtensionDelegate> workspace_extension_delegate_ = nullptr;
gfx::ImageSkia initial_icon_;
std::optional<PlatformSessionWindowData> session_data_;
raw_ptr<XdgSession> session_;
base::ScopedObservation<XdgSession, XdgSession::Observer> session_observer_{
this};
std::unique_ptr<XdgToplevelSession> toplevel_session_;
// Global application menu integration.
std::unique_ptr<OrgKdeKwinAppmenu> appmenu_;
std::string appmenu_service_name_;
std::string appmenu_object_path_;
base::WeakPtrFactory<WaylandToplevelWindow> weak_ptr_factory_{this};
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_TOPLEVEL_WINDOW_H_