Commit e7f66cab authored by Kramer Ge's avatar Kramer Ge Committed by Chromium LUCI CQ

[Ozone/Wayland]Create shell_toplevel_wrapper

shell_toplevel allows a surface to set window-like properties such as
maximize, fullscreen, and minimize, set application-specific metadata
like title and id, and well as trigger user interactive operations such
as interactive resize and move.

Refactor shell_toplevel responsibilities out of shell_surface_wrapper.
shell_toplevel_wrapper's relationship with shell_surface_wrapper should
be similar to shell_popup_wrapper and shell_surface_wrapper.

Change-Id: Iecfdf73dba05d67589b26c85c19368c24b39c3d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2600385
Commit-Queue: Kramer Ge <fangzhoug@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841222}
parent 825bd957
...@@ -51,8 +51,9 @@ source_set("wayland") { ...@@ -51,8 +51,9 @@ source_set("wayland") {
"host/shell_object_factory.h", "host/shell_object_factory.h",
"host/shell_popup_wrapper.cc", "host/shell_popup_wrapper.cc",
"host/shell_popup_wrapper.h", "host/shell_popup_wrapper.h",
"host/shell_surface_wrapper.cc",
"host/shell_surface_wrapper.h", "host/shell_surface_wrapper.h",
"host/shell_toplevel_wrapper.cc",
"host/shell_toplevel_wrapper.h",
"host/wayland_auxiliary_window.cc", "host/wayland_auxiliary_window.cc",
"host/wayland_auxiliary_window.h", "host/wayland_auxiliary_window.h",
"host/wayland_buffer_manager_connector.cc", "host/wayland_buffer_manager_connector.cc",
...@@ -138,6 +139,8 @@ source_set("wayland") { ...@@ -138,6 +139,8 @@ source_set("wayland") {
"host/xdg_popup_wrapper_impl.h", "host/xdg_popup_wrapper_impl.h",
"host/xdg_surface_wrapper_impl.cc", "host/xdg_surface_wrapper_impl.cc",
"host/xdg_surface_wrapper_impl.h", "host/xdg_surface_wrapper_impl.h",
"host/xdg_toplevel_wrapper_impl.cc",
"host/xdg_toplevel_wrapper_impl.h",
"host/zwp_primary_selection_device.cc", "host/zwp_primary_selection_device.cc",
"host/zwp_primary_selection_device.h", "host/zwp_primary_selection_device.h",
"host/zwp_primary_selection_device_manager.cc", "host/zwp_primary_selection_device_manager.cc",
...@@ -147,6 +150,12 @@ source_set("wayland") { ...@@ -147,6 +150,12 @@ source_set("wayland") {
"host/zwp_text_input_wrapper.h", "host/zwp_text_input_wrapper.h",
"host/zwp_text_input_wrapper_v1.cc", "host/zwp_text_input_wrapper_v1.cc",
"host/zwp_text_input_wrapper_v1.h", "host/zwp_text_input_wrapper_v1.h",
"host/zxdg_popup_v6_wrapper_impl.cc",
"host/zxdg_popup_v6_wrapper_impl.h",
"host/zxdg_surface_v6_wrapper_impl.cc",
"host/zxdg_surface_v6_wrapper_impl.h",
"host/zxdg_toplevel_v6_wrapper_impl.cc",
"host/zxdg_toplevel_v6_wrapper_impl.h",
"ozone_platform_wayland.cc", "ozone_platform_wayland.cc",
"ozone_platform_wayland.h", "ozone_platform_wayland.h",
] ]
......
...@@ -8,20 +8,37 @@ ...@@ -8,20 +8,37 @@
#include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h" #include "ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h"
#include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h" #include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h"
#include "ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h"
#include "ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.h"
#include "ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h"
#include "ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h"
namespace ui { namespace ui {
ShellObjectFactory::ShellObjectFactory() = default; ShellObjectFactory::ShellObjectFactory() = default;
ShellObjectFactory::~ShellObjectFactory() = default; ShellObjectFactory::~ShellObjectFactory() = default;
std::unique_ptr<ShellSurfaceWrapper> std::unique_ptr<ShellToplevelWrapper>
ShellObjectFactory::CreateShellSurfaceWrapper(WaylandConnection* connection, ShellObjectFactory::CreateShellToplevelWrapper(WaylandConnection* connection,
WaylandWindow* wayland_window) { WaylandWindow* wayland_window) {
if (connection->shell() || connection->shell_v6()) { if (connection->shell()) {
auto surface = auto surface =
std::make_unique<XDGSurfaceWrapperImpl>(wayland_window, connection); std::make_unique<XDGSurfaceWrapperImpl>(wayland_window, connection);
return surface->Initialize(true /* with_top_level */) ? std::move(surface) if (!surface->Initialize())
: nullptr; return nullptr;
auto toplevel = std::make_unique<XDGToplevelWrapperImpl>(
std::move(surface), wayland_window, connection);
return toplevel->Initialize() ? std::move(toplevel) : nullptr;
} else if (connection->shell_v6()) {
auto surface =
std::make_unique<ZXDGSurfaceV6WrapperImpl>(wayland_window, connection);
if (!surface->Initialize())
return nullptr;
auto toplevel = std::make_unique<ZXDGToplevelV6WrapperImpl>(
std::move(surface), wayland_window, connection);
return toplevel->Initialize() ? std::move(toplevel) : nullptr;
} }
LOG(WARNING) << "Shell protocol is not available."; LOG(WARNING) << "Shell protocol is not available.";
return nullptr; return nullptr;
...@@ -31,15 +48,24 @@ std::unique_ptr<ShellPopupWrapper> ShellObjectFactory::CreateShellPopupWrapper( ...@@ -31,15 +48,24 @@ std::unique_ptr<ShellPopupWrapper> ShellObjectFactory::CreateShellPopupWrapper(
WaylandConnection* connection, WaylandConnection* connection,
WaylandWindow* wayland_window, WaylandWindow* wayland_window,
const gfx::Rect& bounds) { const gfx::Rect& bounds) {
if (connection->shell() || connection->shell_v6()) { if (connection->shell()) {
auto surface = auto surface =
std::make_unique<XDGSurfaceWrapperImpl>(wayland_window, connection); std::make_unique<XDGSurfaceWrapperImpl>(wayland_window, connection);
if (!surface->Initialize(false /* with_top_level */)) if (!surface->Initialize())
return nullptr; return nullptr;
auto popup = std::make_unique<XDGPopupWrapperImpl>(std::move(surface), auto popup = std::make_unique<XDGPopupWrapperImpl>(std::move(surface),
wayland_window); wayland_window);
return popup->Initialize(connection, bounds) ? std::move(popup) : nullptr; return popup->Initialize(connection, bounds) ? std::move(popup) : nullptr;
} else if (connection->shell_v6()) {
auto surface =
std::make_unique<ZXDGSurfaceV6WrapperImpl>(wayland_window, connection);
if (!surface->Initialize())
return nullptr;
auto popup = std::make_unique<ZXDGPopupV6WrapperImpl>(std::move(surface),
wayland_window);
return popup->Initialize(connection, bounds) ? std::move(popup) : nullptr;
} }
LOG(WARNING) << "Shell protocol is not available."; LOG(WARNING) << "Shell protocol is not available.";
return nullptr; return nullptr;
......
...@@ -13,7 +13,7 @@ class Rect; ...@@ -13,7 +13,7 @@ class Rect;
namespace ui { namespace ui {
class ShellSurfaceWrapper; class ShellToplevelWrapper;
class ShellPopupWrapper; class ShellPopupWrapper;
class WaylandConnection; class WaylandConnection;
class WaylandWindow; class WaylandWindow;
...@@ -27,8 +27,8 @@ class ShellObjectFactory { ...@@ -27,8 +27,8 @@ class ShellObjectFactory {
ShellObjectFactory(); ShellObjectFactory();
~ShellObjectFactory(); ~ShellObjectFactory();
// Creates and initializes a ShellSurfaceWrapper. // Creates and initializes a ShellToplevelWrapper.
std::unique_ptr<ShellSurfaceWrapper> CreateShellSurfaceWrapper( std::unique_ptr<ShellToplevelWrapper> CreateShellToplevelWrapper(
WaylandConnection* connection, WaylandConnection* connection,
WaylandWindow* wayland_window); WaylandWindow* wayland_window);
...@@ -41,4 +41,4 @@ class ShellObjectFactory { ...@@ -41,4 +41,4 @@ class ShellObjectFactory {
} // namespace ui } // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_OBJECT_FACTORY_H_ #endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_OBJECT_FACTORY_H_
\ No newline at end of file
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include "base/check_op.h" #include "base/check_op.h"
#include "base/notreached.h" #include "base/notreached.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
namespace ui { namespace ui {
...@@ -79,4 +83,117 @@ gfx::Rect GetAnchorRect(MenuType menu_type, ...@@ -79,4 +83,117 @@ gfx::Rect GetAnchorRect(MenuType menu_type,
return anchor_rect; return anchor_rect;
} }
WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds) {
WlAnchor anchor = WlAnchor::None;
switch (menu_type) {
case MenuType::TYPE_RIGHT_CLICK:
anchor = WlAnchor::TopLeft;
break;
case MenuType::TYPE_3DOT_PARENT_MENU:
anchor = WlAnchor::BottomRight;
break;
case MenuType::TYPE_3DOT_CHILD_MENU:
// Chromium may want to manually position a child menu on the left side of
// its parent menu. Thus, react accordingly. Positive x means the child is
// located on the right side of the parent and negative - on the left
// side.
if (bounds.x() >= 0)
anchor = WlAnchor::TopRight;
else
anchor = WlAnchor::TopLeft;
break;
case MenuType::TYPE_UNKNOWN:
NOTREACHED() << "Unsupported menu type";
break;
}
return anchor;
}
WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds) {
WlGravity gravity = WlGravity::None;
switch (menu_type) {
case MenuType::TYPE_RIGHT_CLICK:
gravity = WlGravity::BottomRight;
break;
case MenuType::TYPE_3DOT_PARENT_MENU:
gravity = WlGravity::BottomRight;
break;
case MenuType::TYPE_3DOT_CHILD_MENU:
// Chromium may want to manually position a child menu on the left side of
// its parent menu. Thus, react accordingly. Positive x means the child is
// located on the right side of the parent and negative - on the left
// side.
if (bounds.x() >= 0)
gravity = WlGravity::BottomRight;
else
gravity = WlGravity::BottomLeft;
break;
case MenuType::TYPE_UNKNOWN:
NOTREACHED() << "Unsupported menu type";
break;
}
return gravity;
}
WlConstraintAdjustment GetConstraintAdjustment(MenuType menu_type) {
WlConstraintAdjustment constraint = WlConstraintAdjustment::None;
switch (menu_type) {
case MenuType::TYPE_RIGHT_CLICK:
constraint = WlConstraintAdjustment::SlideX |
WlConstraintAdjustment::SlideY |
WlConstraintAdjustment::FlipY;
break;
case MenuType::TYPE_3DOT_PARENT_MENU:
constraint =
WlConstraintAdjustment::SlideX | WlConstraintAdjustment::FlipY;
break;
case MenuType::TYPE_3DOT_CHILD_MENU:
constraint =
WlConstraintAdjustment::SlideY | WlConstraintAdjustment::FlipX;
break;
case MenuType::TYPE_UNKNOWN:
NOTREACHED() << "Unsupported menu type";
break;
}
return constraint;
}
MenuType ShellPopupWrapper::GetMenuTypeForPositioner(
WaylandConnection* connection,
WaylandWindow* parent_window) const {
bool is_right_click_menu =
connection->event_source()->last_pointer_button_pressed() &
EF_RIGHT_MOUSE_BUTTON;
// Different types of menu require different anchors, constraint adjustments,
// gravity and etc.
if (is_right_click_menu)
return MenuType::TYPE_RIGHT_CLICK;
else if (!wl::IsMenuType(parent_window->type()))
return MenuType::TYPE_3DOT_PARENT_MENU;
else
return MenuType::TYPE_3DOT_CHILD_MENU;
}
bool ShellPopupWrapper::CanGrabPopup(WaylandConnection* connection) const {
// When drag process starts, as described the protocol -
// https://goo.gl/1Mskq3, the client must have an active implicit grab. If
// we try to create a popup and grab it, it will be immediately dismissed.
// Thus, do not take explicit grab during drag process.
if (connection->IsDragInProgress() || !connection->seat())
return false;
// According to the definition of the xdg protocol, the grab request must be
// used in response to some sort of user action like a button press, key
// press, or touch down event.
EventType last_event_type = connection->event_serial().event_type;
return last_event_type == ET_TOUCH_PRESSED ||
last_event_type == ET_KEY_PRESSED ||
last_event_type == ET_MOUSE_PRESSED;
}
} // namespace ui } // namespace ui
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
namespace ui { namespace ui {
class WaylandConnection; class WaylandConnection;
class WaylandWindow;
enum class MenuType { enum class MenuType {
TYPE_RIGHT_CLICK, TYPE_RIGHT_CLICK,
...@@ -73,11 +74,18 @@ class ShellPopupWrapper { ...@@ -73,11 +74,18 @@ class ShellPopupWrapper {
// Initializes the popup surface. // Initializes the popup surface.
virtual bool Initialize(WaylandConnection* connection, virtual bool Initialize(WaylandConnection* connection,
const gfx::Rect& bounds) = 0; const gfx::Rect& bounds) = 0;
MenuType GetMenuTypeForPositioner(WaylandConnection* connection,
WaylandWindow* parent_window) const;
bool CanGrabPopup(WaylandConnection* connection) const;
}; };
gfx::Rect GetAnchorRect(MenuType menu_type, gfx::Rect GetAnchorRect(MenuType menu_type,
const gfx::Rect& menu_bounds, const gfx::Rect& menu_bounds,
const gfx::Rect& parent_window_bounds); const gfx::Rect& parent_window_bounds);
WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds);
WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds);
WlConstraintAdjustment GetConstraintAdjustment(MenuType menu_type);
} // namespace ui } // namespace ui
......
...@@ -5,90 +5,27 @@ ...@@ -5,90 +5,27 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_ #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_ #define UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_
#include "base/strings/string16.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
namespace gfx { namespace gfx {
class Rect; class Rect;
} }
namespace ui { namespace ui {
class WaylandConnection; // Wrapper interface for different wayland xdg-shell surface versions.
enum class DecorationMode {
// Client-side decoration for a window.
// In this case, the client is responsible for drawing decorations
// for a window (e.g. caption bar, close button). This is suitable for
// windows using custom frame.
kClientSide = 1,
// Server-side decoration for a window.
// In this case, the ash window manager is responsible for drawing
// decorations. This is suitable for windows using native frame.
// e.g. taskmanager.
kServerSide
};
// Wrapper interface for different wayland shells shell versions.
class ShellSurfaceWrapper { class ShellSurfaceWrapper {
public: public:
virtual ~ShellSurfaceWrapper() {} virtual ~ShellSurfaceWrapper() {}
// Initializes the ShellSurface. Some protocols may require to create shell // Initializes the ShellSurface.
// surface without toplevel role and assign a popup role to it later. virtual bool Initialize() = 0;
virtual bool Initialize(bool with_toplevel) = 0;
// Sets a native window to maximized state.
virtual void SetMaximized() = 0;
// Unsets a native window from maximized state.
virtual void UnSetMaximized() = 0;
// Sets a native window to fullscreen state.
virtual void SetFullscreen() = 0;
// Unsets a native window from fullscreen state.
virtual void UnSetFullscreen() = 0;
// Sets a native window to minimized state.
virtual void SetMinimized() = 0;
// Tells wayland to start interactive window drag.
virtual void SurfaceMove(WaylandConnection* connection) = 0;
// Tells wayland to start interactive window resize.
virtual void SurfaceResize(WaylandConnection* connection,
uint32_t hittest) = 0;
// Sets a title of a native window.
virtual void SetTitle(const base::string16& title) = 0;
// Sends acknowledge configure event back to wayland. // Sends acknowledge configure event back to wayland.
virtual void AckConfigure() = 0; virtual void AckConfigure() = 0;
// Sets a desired window geometry once wayland requests client to do so. // Sets a desired window geometry once wayland requests client to do so.
virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0; virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0;
// Sets the minimum size for the top level.
virtual void SetMinSize(int32_t width, int32_t height) = 0;
// Sets the maximum size for the top level.
virtual void SetMaxSize(int32_t width, int32_t height) = 0;
// Sets an app id of the native window that is shown as an application name
// and hints the compositor that it can group application surfaces together by
// their app id. This also helps the compositor to identify application's
// .desktop file and use the icon set there.
virtual void SetAppId(const std::string& app_id) = 0;
// In case of kClientSide or kServerSide, this function sends a
// request to the wayland compositor to update the decoration mode
// for a surface associated with this top level window.
virtual void SetDecoration(DecorationMode decoration) = 0;
}; };
bool CheckIfWlArrayHasValue(struct wl_array* wl_array, uint32_t value);
} // namespace ui } // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_ #endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" #include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h"
namespace ui { namespace ui {
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// 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_SHELL_TOPLEVEL_WRAPPER_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_TOPLEVEL_WRAPPER_H_
#include "base/strings/string16.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
namespace gfx {
class Rect;
}
namespace ui {
class WaylandConnection;
// A wrapper around different versions of xdg toplevels. Allows
// WaylandToplevelWindow to set window-like properties such as maximize,
// fullscreen, and minimize, set application-specific metadata like title and
// id, as well as trigger user interactive operations such as interactive resize
// and move.
class ShellToplevelWrapper {
public:
enum class DecorationMode {
// Client-side decoration for a window.
// In this case, the client is responsible for drawing decorations
// for a window (e.g. caption bar, close button). This is suitable for
// windows using custom frame.
kClientSide = 1,
// Server-side decoration for a window.
// In this case, the ash window manager is responsible for drawing
// decorations. This is suitable for windows using native frame.
// e.g. taskmanager.
kServerSide
};
virtual ~ShellToplevelWrapper() = default;
// Initializes the ShellToplevel.
virtual bool Initialize() = 0;
// Sets a native window to maximized state.
virtual void SetMaximized() = 0;
// Unsets a native window from maximized state.
virtual void UnSetMaximized() = 0;
// Sets a native window to fullscreen state.
virtual void SetFullscreen() = 0;
// Unsets a native window from fullscreen state.
virtual void UnSetFullscreen() = 0;
// Sets a native window to minimized state.
virtual void SetMinimized() = 0;
// Tells wayland to start interactive window drag.
virtual void SurfaceMove(WaylandConnection* connection) = 0;
// Tells wayland to start interactive window resize.
virtual void SurfaceResize(WaylandConnection* connection,
uint32_t hittest) = 0;
// Sets a title of a native window.
virtual void SetTitle(const base::string16& title) = 0;
// Sets a desired window geometry once wayland requests client to do so.
virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0;
// Sets the minimum size for the top level.
virtual void SetMinSize(int32_t width, int32_t height) = 0;
// Sets the maximum size for the top level.
virtual void SetMaxSize(int32_t width, int32_t height) = 0;
// Sets an app id of the native window that is shown as an application name
// and hints the compositor that it can group application surfaces together by
// their app id. This also helps the compositor to identify application's
// .desktop file and use the icon set there.
virtual void SetAppId(const std::string& app_id) = 0;
// In case of kClientSide or kServerSide, this function sends a request to the
// wayland compositor to update the decoration mode for a surface associated
// with this top level window.
virtual void SetDecoration(DecorationMode decoration) = 0;
};
// Look for |value| in |wl_array| in C++ style.
bool CheckIfWlArrayHasValue(struct wl_array* wl_array, uint32_t value);
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_TOPLEVEL_WRAPPER_H_
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/shell_object_factory.h" #include "ui/ozone/platform/wayland/host/shell_object_factory.h"
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" #include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h" #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/host/wayland_event_source.h"
...@@ -40,21 +40,21 @@ WaylandToplevelWindow::WaylandToplevelWindow(PlatformWindowDelegate* delegate, ...@@ -40,21 +40,21 @@ WaylandToplevelWindow::WaylandToplevelWindow(PlatformWindowDelegate* delegate,
WaylandToplevelWindow::~WaylandToplevelWindow() = default; WaylandToplevelWindow::~WaylandToplevelWindow() = default;
bool WaylandToplevelWindow::CreateShellSurface() { bool WaylandToplevelWindow::CreateShellToplevel() {
ShellObjectFactory factory; ShellObjectFactory factory;
shell_surface_ = factory.CreateShellSurfaceWrapper(connection(), this); shell_toplevel_ = factory.CreateShellToplevelWrapper(connection(), this);
if (!shell_surface_) { if (!shell_toplevel_) {
LOG(ERROR) << "Failed to create a ShellSurface."; LOG(ERROR) << "Failed to create a ShellToplevel.";
return false; return false;
} }
#if BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(IS_CHROMEOS_LACROS)
shell_surface_->SetAppId(window_unique_id_); shell_toplevel_->SetAppId(window_unique_id_);
#else #else
shell_surface_->SetAppId(wm_class_class_); shell_toplevel_->SetAppId(wm_class_class_);
#endif #endif
SetDecorationMode(); SetDecorationMode();
shell_surface_->SetTitle(window_title_); shell_toplevel_->SetTitle(window_title_);
SetSizeConstraints(); SetSizeConstraints();
TriggerStateChanges(); TriggerStateChanges();
InitializeAuraShellSurface(); InitializeAuraShellSurface();
...@@ -64,10 +64,10 @@ bool WaylandToplevelWindow::CreateShellSurface() { ...@@ -64,10 +64,10 @@ bool WaylandToplevelWindow::CreateShellSurface() {
void WaylandToplevelWindow::ApplyPendingBounds() { void WaylandToplevelWindow::ApplyPendingBounds() {
if (pending_bounds_dip_.IsEmpty()) if (pending_bounds_dip_.IsEmpty())
return; return;
DCHECK(shell_surface_); DCHECK(shell_toplevel_);
SetBoundsDip(pending_bounds_dip_); SetBoundsDip(pending_bounds_dip_);
shell_surface_->SetWindowGeometry(pending_bounds_dip_); shell_toplevel_->SetWindowGeometry(pending_bounds_dip_);
pending_bounds_dip_ = gfx::Rect(); pending_bounds_dip_ = gfx::Rect();
connection()->ScheduleFlush(); connection()->ScheduleFlush();
} }
...@@ -75,22 +75,22 @@ void WaylandToplevelWindow::ApplyPendingBounds() { ...@@ -75,22 +75,22 @@ void WaylandToplevelWindow::ApplyPendingBounds() {
void WaylandToplevelWindow::DispatchHostWindowDragMovement( void WaylandToplevelWindow::DispatchHostWindowDragMovement(
int hittest, int hittest,
const gfx::Point& pointer_location_in_px) { const gfx::Point& pointer_location_in_px) {
DCHECK(shell_surface_); DCHECK(shell_toplevel_);
connection()->event_source()->ResetPointerFlags(); connection()->event_source()->ResetPointerFlags();
if (hittest == HTCAPTION) if (hittest == HTCAPTION)
shell_surface_->SurfaceMove(connection()); shell_toplevel_->SurfaceMove(connection());
else else
shell_surface_->SurfaceResize(connection(), hittest); shell_toplevel_->SurfaceResize(connection(), hittest);
connection()->ScheduleFlush(); connection()->ScheduleFlush();
} }
void WaylandToplevelWindow::Show(bool inactive) { void WaylandToplevelWindow::Show(bool inactive) {
if (shell_surface_) if (shell_toplevel_)
return; return;
if (!CreateShellSurface()) { if (!CreateShellToplevel()) {
Close(); Close();
return; return;
} }
...@@ -104,7 +104,7 @@ void WaylandToplevelWindow::Show(bool inactive) { ...@@ -104,7 +104,7 @@ void WaylandToplevelWindow::Show(bool inactive) {
} }
void WaylandToplevelWindow::Hide() { void WaylandToplevelWindow::Hide() {
if (!shell_surface_) if (!shell_toplevel_)
return; return;
if (child_window()) { if (child_window()) {
...@@ -112,7 +112,7 @@ void WaylandToplevelWindow::Hide() { ...@@ -112,7 +112,7 @@ void WaylandToplevelWindow::Hide() {
set_child_window(nullptr); set_child_window(nullptr);
} }
shell_surface_.reset(); shell_toplevel_.reset();
connection()->ScheduleFlush(); connection()->ScheduleFlush();
// Detach buffer from surface in order to completely shutdown menus and // Detach buffer from surface in order to completely shutdown menus and
...@@ -123,7 +123,7 @@ void WaylandToplevelWindow::Hide() { ...@@ -123,7 +123,7 @@ void WaylandToplevelWindow::Hide() {
bool WaylandToplevelWindow::IsVisible() const { bool WaylandToplevelWindow::IsVisible() const {
// X and Windows return true if the window is minimized. For consistency, do // X and Windows return true if the window is minimized. For consistency, do
// the same. // the same.
return !!shell_surface_ || state_ == PlatformWindowState::kMinimized; return !!shell_toplevel_ || state_ == PlatformWindowState::kMinimized;
} }
void WaylandToplevelWindow::SetTitle(const base::string16& title) { void WaylandToplevelWindow::SetTitle(const base::string16& title) {
...@@ -132,8 +132,8 @@ void WaylandToplevelWindow::SetTitle(const base::string16& title) { ...@@ -132,8 +132,8 @@ void WaylandToplevelWindow::SetTitle(const base::string16& title) {
window_title_ = title; window_title_ = title;
if (shell_surface_) { if (shell_toplevel_) {
shell_surface_->SetTitle(title); shell_toplevel_->SetTitle(title);
connection()->ScheduleFlush(); connection()->ScheduleFlush();
} }
} }
...@@ -167,7 +167,7 @@ void WaylandToplevelWindow::Minimize() { ...@@ -167,7 +167,7 @@ void WaylandToplevelWindow::Minimize() {
} }
void WaylandToplevelWindow::Restore() { void WaylandToplevelWindow::Restore() {
DCHECK(shell_surface_); DCHECK(shell_toplevel_);
// Differently from other platforms, under Wayland, unmaximizing the dragged // Differently from other platforms, under Wayland, unmaximizing the dragged
// window before starting the drag loop is not needed as it is assumed to be // window before starting the drag loop is not needed as it is assumed to be
...@@ -188,7 +188,7 @@ PlatformWindowState WaylandToplevelWindow::GetPlatformWindowState() const { ...@@ -188,7 +188,7 @@ PlatformWindowState WaylandToplevelWindow::GetPlatformWindowState() const {
void WaylandToplevelWindow::SizeConstraintsChanged() { void WaylandToplevelWindow::SizeConstraintsChanged() {
// Size constraints only make sense for normal windows. // Size constraints only make sense for normal windows.
if (!shell_surface_) if (!shell_toplevel_)
return; return;
DCHECK(delegate()); DCHECK(delegate());
...@@ -209,7 +209,7 @@ void WaylandToplevelWindow::SetUseNativeFrame(bool use_native_frame) { ...@@ -209,7 +209,7 @@ void WaylandToplevelWindow::SetUseNativeFrame(bool use_native_frame) {
if (use_native_frame_ == use_native_frame) if (use_native_frame_ == use_native_frame)
return; return;
use_native_frame_ = use_native_frame; use_native_frame_ = use_native_frame;
if (shell_surface_) if (shell_toplevel_)
SetDecorationMode(); SetDecorationMode();
} }
...@@ -330,7 +330,7 @@ void WaylandToplevelWindow::SetImmersiveFullscreenStatus(bool status) { ...@@ -330,7 +330,7 @@ void WaylandToplevelWindow::SetImmersiveFullscreenStatus(bool status) {
} }
void WaylandToplevelWindow::TriggerStateChanges() { void WaylandToplevelWindow::TriggerStateChanges() {
if (!shell_surface_) if (!shell_toplevel_)
return; return;
// Call UnSetMaximized only if current state is normal. Otherwise, if the // Call UnSetMaximized only if current state is normal. Otherwise, if the
...@@ -338,15 +338,15 @@ void WaylandToplevelWindow::TriggerStateChanges() { ...@@ -338,15 +338,15 @@ void WaylandToplevelWindow::TriggerStateChanges() {
// UnSetMaximized may result in wrong restored window position that clients // UnSetMaximized may result in wrong restored window position that clients
// are not allowed to know about. // are not allowed to know about.
if (state_ == PlatformWindowState::kMinimized) { if (state_ == PlatformWindowState::kMinimized) {
shell_surface_->SetMinimized(); shell_toplevel_->SetMinimized();
} else if (state_ == PlatformWindowState::kFullScreen) { } else if (state_ == PlatformWindowState::kFullScreen) {
shell_surface_->SetFullscreen(); shell_toplevel_->SetFullscreen();
} else if (previous_state_ == PlatformWindowState::kFullScreen) { } else if (previous_state_ == PlatformWindowState::kFullScreen) {
shell_surface_->UnSetFullscreen(); shell_toplevel_->UnSetFullscreen();
} else if (state_ == PlatformWindowState::kMaximized) { } else if (state_ == PlatformWindowState::kMaximized) {
shell_surface_->SetMaximized(); shell_toplevel_->SetMaximized();
} else if (state_ == PlatformWindowState::kNormal) { } else if (state_ == PlatformWindowState::kNormal) {
shell_surface_->UnSetMaximized(); shell_toplevel_->UnSetMaximized();
} }
connection()->ScheduleFlush(); connection()->ScheduleFlush();
...@@ -364,9 +364,9 @@ WmMoveResizeHandler* WaylandToplevelWindow::AsWmMoveResizeHandler() { ...@@ -364,9 +364,9 @@ WmMoveResizeHandler* WaylandToplevelWindow::AsWmMoveResizeHandler() {
void WaylandToplevelWindow::SetSizeConstraints() { void WaylandToplevelWindow::SetSizeConstraints() {
if (min_size_.has_value()) if (min_size_.has_value())
shell_surface_->SetMinSize(min_size_->width(), min_size_->height()); shell_toplevel_->SetMinSize(min_size_->width(), min_size_->height());
if (max_size_.has_value()) if (max_size_.has_value())
shell_surface_->SetMaxSize(max_size_->width(), max_size_->height()); shell_toplevel_->SetMaxSize(max_size_->width(), max_size_->height());
connection()->ScheduleFlush(); connection()->ScheduleFlush();
} }
...@@ -387,7 +387,7 @@ void WaylandToplevelWindow::SetOrResetRestoredBounds() { ...@@ -387,7 +387,7 @@ void WaylandToplevelWindow::SetOrResetRestoredBounds() {
void WaylandToplevelWindow::InitializeAuraShellSurface() { void WaylandToplevelWindow::InitializeAuraShellSurface() {
// InitializeAuraShellSurface() should be called after the XDG surface is // InitializeAuraShellSurface() should be called after the XDG surface is
// initialized. // initialized.
DCHECK(shell_surface_); DCHECK(shell_toplevel_);
if (connection()->zaura_shell() && !aura_surface_) { if (connection()->zaura_shell() && !aura_surface_) {
aura_surface_.reset(zaura_shell_get_aura_surface( aura_surface_.reset(zaura_shell_get_aura_surface(
...@@ -397,13 +397,15 @@ void WaylandToplevelWindow::InitializeAuraShellSurface() { ...@@ -397,13 +397,15 @@ void WaylandToplevelWindow::InitializeAuraShellSurface() {
} }
void WaylandToplevelWindow::SetDecorationMode() { void WaylandToplevelWindow::SetDecorationMode() {
DCHECK(shell_surface_); DCHECK(shell_toplevel_);
if (use_native_frame_) { if (use_native_frame_) {
// Set server-side decoration for windows using a native frame, // Set server-side decoration for windows using a native frame,
// e.g. taskmanager // e.g. taskmanager
shell_surface_->SetDecoration(DecorationMode::kServerSide); shell_toplevel_->SetDecoration(
ShellToplevelWrapper::DecorationMode::kServerSide);
} else { } else {
shell_surface_->SetDecoration(DecorationMode::kClientSide); shell_toplevel_->SetDecoration(
ShellToplevelWrapper::DecorationMode::kClientSide);
} }
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
namespace ui { namespace ui {
class ShellSurfaceWrapper; class ShellToplevelWrapper;
class WaylandToplevelWindow : public WaylandWindow, class WaylandToplevelWindow : public WaylandWindow,
public WmMoveResizeHandler, public WmMoveResizeHandler,
...@@ -27,7 +27,7 @@ class WaylandToplevelWindow : public WaylandWindow, ...@@ -27,7 +27,7 @@ class WaylandToplevelWindow : public WaylandWindow,
WaylandToplevelWindow& operator=(const WaylandToplevelWindow&) = delete; WaylandToplevelWindow& operator=(const WaylandToplevelWindow&) = delete;
~WaylandToplevelWindow() override; ~WaylandToplevelWindow() override;
ShellSurfaceWrapper* shell_surface() const { return shell_surface_.get(); } ShellToplevelWrapper* shell_toplevel() const { return shell_toplevel_.get(); }
// Apply the bounds specified in the most recent configure event. This should // Apply the bounds specified in the most recent configure event. This should
// be called after processing all pending events in the wayland connection. // be called after processing all pending events in the wayland connection.
...@@ -77,11 +77,11 @@ class WaylandToplevelWindow : public WaylandWindow, ...@@ -77,11 +77,11 @@ class WaylandToplevelWindow : public WaylandWindow,
void SetWindowState(PlatformWindowState state); void SetWindowState(PlatformWindowState state);
// Creates a surface window, which is visible as a main window. // Creates a surface window, which is visible as a main window.
bool CreateShellSurface(); bool CreateShellToplevel();
WmMoveResizeHandler* AsWmMoveResizeHandler(); WmMoveResizeHandler* AsWmMoveResizeHandler();
// Propagates the |min_size_| and |max_size_| to the ShellSurface. // Propagates the |min_size_| and |max_size_| to the ShellToplevel.
void SetSizeConstraints(); void SetSizeConstraints();
void SetOrResetRestoredBounds(); void SetOrResetRestoredBounds();
...@@ -94,7 +94,7 @@ class WaylandToplevelWindow : public WaylandWindow, ...@@ -94,7 +94,7 @@ class WaylandToplevelWindow : public WaylandWindow,
void SetDecorationMode(); void SetDecorationMode();
// Wrappers around shell surface. // Wrappers around shell surface.
std::unique_ptr<ShellSurfaceWrapper> shell_surface_; std::unique_ptr<ShellToplevelWrapper> shell_toplevel_;
// These bounds attributes below have suffices that indicate units used. // These bounds attributes below have suffices that indicate units used.
// Wayland operates in DIP but the platform operates in physical pixels so // Wayland operates in DIP but the platform operates in physical pixels so
...@@ -127,7 +127,7 @@ class WaylandToplevelWindow : public WaylandWindow, ...@@ -127,7 +127,7 @@ class WaylandToplevelWindow : public WaylandWindow,
std::string wm_class_class_; std::string wm_class_class_;
#endif #endif
// Title of the ShellSurface. // Title of the ShellToplevel.
base::string16 window_title_; base::string16 window_title_;
// Max and min sizes of the WaylandToplevelWindow window. // Max and min sizes of the WaylandToplevelWindow window.
......
...@@ -16,7 +16,7 @@ class XDGSurfaceWrapperImpl; ...@@ -16,7 +16,7 @@ class XDGSurfaceWrapperImpl;
class WaylandConnection; class WaylandConnection;
class WaylandWindow; class WaylandWindow;
// Popup wrapper for xdg-shell stable and xdg-shell-unstable-v6 // Popup wrapper for xdg-shell stable
class XDGPopupWrapperImpl : public ShellPopupWrapper { class XDGPopupWrapperImpl : public ShellPopupWrapper {
public: public:
XDGPopupWrapperImpl(std::unique_ptr<XDGSurfaceWrapperImpl> surface, XDGPopupWrapperImpl(std::unique_ptr<XDGSurfaceWrapperImpl> surface,
...@@ -30,57 +30,30 @@ class XDGPopupWrapperImpl : public ShellPopupWrapper { ...@@ -30,57 +30,30 @@ class XDGPopupWrapperImpl : public ShellPopupWrapper {
private: private:
bool InitializeStable(WaylandConnection* connection, bool InitializeStable(WaylandConnection* connection,
const gfx::Rect& bounds, const gfx::Rect& bounds,
XDGSurfaceWrapperImpl* parent_xdg_surface); XDGSurfaceWrapperImpl* parent_xdg_surface_wrapper);
struct xdg_positioner* CreatePositionerStable(WaylandConnection* connection, struct xdg_positioner* CreatePositioner(WaylandConnection* connection,
WaylandWindow* parent_window, WaylandWindow* parent_window,
const gfx::Rect& bounds); const gfx::Rect& bounds);
bool InitializeV6(WaylandConnection* connection,
const gfx::Rect& bounds,
XDGSurfaceWrapperImpl* parent_xdg_surface);
struct zxdg_positioner_v6* CreatePositionerV6(WaylandConnection* connection,
WaylandWindow* parent_window,
const gfx::Rect& bounds);
MenuType GetMenuTypeForPositioner(WaylandConnection* connection,
WaylandWindow* parent_window) const;
bool CanGrabPopup(WaylandConnection* connection) const;
// xdg_popup_listener // xdg_popup_listener
static void Configure(void* data, static void Configure(void* data,
int32_t x,
int32_t y,
int32_t width,
int32_t height);
static void ConfigureStable(void* data,
struct xdg_popup* xdg_popup, struct xdg_popup* xdg_popup,
int32_t x, int32_t x,
int32_t y, int32_t y,
int32_t width, int32_t width,
int32_t height); int32_t height);
static void ConfigureV6(void* data, static void PopupDone(void* data, struct xdg_popup* xdg_popup);
struct zxdg_popup_v6* zxdg_popup_v6,
int32_t x, XDGSurfaceWrapperImpl* xdg_surface_wrapper() const;
int32_t y,
int32_t width,
int32_t height);
static void PopupDone(void* data);
static void PopupDoneStable(void* data, struct xdg_popup* xdg_popup);
static void PopupDoneV6(void* data, struct zxdg_popup_v6* zxdg_popup_v6);
XDGSurfaceWrapperImpl* xdg_surface();
// Non-owned WaylandWindow that uses this popup. // Non-owned WaylandWindow that uses this popup.
WaylandWindow* const wayland_window_; WaylandWindow* const wayland_window_;
// Ground surface for this popup. // Ground surface for this popup.
std::unique_ptr<XDGSurfaceWrapperImpl> xdg_surface_; std::unique_ptr<XDGSurfaceWrapperImpl> xdg_surface_wrapper_;
// XDG Shell Stable object. // XDG Shell Stable object.
wl::Object<xdg_popup> xdg_popup_; wl::Object<xdg_popup> xdg_popup_;
// XDG Shell V6 object.
wl::Object<zxdg_popup_v6> zxdg_popup_v6_;
DISALLOW_COPY_AND_ASSIGN(XDGPopupWrapperImpl); DISALLOW_COPY_AND_ASSIGN(XDGPopupWrapperImpl);
}; };
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" #include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
#include <xdg-decoration-unstable-v1-client-protocol.h>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
...@@ -24,7 +22,7 @@ namespace ui { ...@@ -24,7 +22,7 @@ namespace ui {
class WaylandConnection; class WaylandConnection;
class WaylandWindow; class WaylandWindow;
// Surface wrapper for xdg-shell stable and xdg-shell-unstable-v6 // Surface wrapper for xdg-shell stable
class XDGSurfaceWrapperImpl : public ShellSurfaceWrapper { class XDGSurfaceWrapperImpl : public ShellSurfaceWrapper {
public: public:
XDGSurfaceWrapperImpl(WaylandWindow* wayland_window, XDGSurfaceWrapperImpl(WaylandWindow* wayland_window,
...@@ -34,85 +32,25 @@ class XDGSurfaceWrapperImpl : public ShellSurfaceWrapper { ...@@ -34,85 +32,25 @@ class XDGSurfaceWrapperImpl : public ShellSurfaceWrapper {
~XDGSurfaceWrapperImpl() override; ~XDGSurfaceWrapperImpl() override;
// ShellSurfaceWrapper overrides: // ShellSurfaceWrapper overrides:
bool Initialize(bool with_toplevel) override; bool Initialize() override;
void SetMaximized() override;
void UnSetMaximized() override;
void SetFullscreen() override;
void UnSetFullscreen() override;
void SetMinimized() override;
void SurfaceMove(WaylandConnection* connection) override;
void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override;
void SetTitle(const base::string16& title) override;
void AckConfigure() override; void AckConfigure() override;
void SetWindowGeometry(const gfx::Rect& bounds) override; void SetWindowGeometry(const gfx::Rect& bounds) override;
void SetMinSize(int32_t width, int32_t height) override;
void SetMaxSize(int32_t width, int32_t height) override;
void SetAppId(const std::string& app_id) override;
void SetDecoration(DecorationMode decoration) override;
// xdg_surface_listener // xdg_surface_listener
static void ConfigureV6(void* data, static void Configure(void* data,
struct zxdg_surface_v6* zxdg_surface_v6, struct xdg_surface* xdg_surface,
uint32_t serial); uint32_t serial);
static void ConfigureTopLevelV6(void* data,
struct zxdg_toplevel_v6* zxdg_toplevel_v6,
int32_t width,
int32_t height,
struct wl_array* states);
static void ConfigureStable(void* data,
struct xdg_surface* xdg_surface,
uint32_t serial);
static void ConfigureTopLevelStable(void* data,
struct xdg_toplevel* xdg_toplevel,
int32_t width,
int32_t height,
struct wl_array* states);
// xdg_toplevel_listener
static void CloseTopLevelStable(void* data,
struct xdg_toplevel* xdg_toplevel);
static void CloseTopLevelV6(void* data,
struct zxdg_toplevel_v6* zxdg_toplevel_v6);
// Send request to wayland compositor to enable a requested decoration mode.
void SetTopLevelDecorationMode(DecorationMode requested_mode);
// zxdg_decoration_listener
static void ConfigureDecoration(
void* data,
struct zxdg_toplevel_decoration_v1* decoration,
uint32_t mode);
struct xdg_surface* xdg_surface() const; struct xdg_surface* xdg_surface() const;
zxdg_surface_v6* zxdg_surface() const;
private: private:
// Initializes using XDG Shell Stable protocol.
bool InitializeStable(bool with_toplevel);
// Initializes using XDG Shell V6 protocol.
bool InitializeV6(bool with_toplevel);
// Initializes the xdg-decoration protocol extension, if available.
void InitializeXdgDecoration();
// Non-owing WaylandWindow that uses this surface wrapper. // Non-owing WaylandWindow that uses this surface wrapper.
WaylandWindow* const wayland_window_; WaylandWindow* const wayland_window_;
WaylandConnection* const connection_; WaylandConnection* const connection_;
uint32_t pending_configure_serial_ = 0; uint32_t pending_configure_serial_ = 0;
wl::Object<zxdg_surface_v6> zxdg_surface_v6_;
wl::Object<zxdg_toplevel_v6> zxdg_toplevel_v6_;
wl::Object<struct xdg_surface> xdg_surface_; wl::Object<struct xdg_surface> xdg_surface_;
wl::Object<xdg_toplevel> xdg_toplevel_;
wl::Object<zxdg_toplevel_decoration_v1> zxdg_toplevel_decoration_;
bool surface_for_popup_ = false;
// On client side, it keeps track of the decoration mode currently in
// use if xdg-decoration protocol extension is available.
DecorationMode decoration_mode_;
}; };
} // namespace ui } // namespace ui
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h"
#include <xdg-decoration-unstable-v1-client-protocol.h>
#include <xdg-shell-client-protocol.h>
#include <xdg-shell-unstable-v6-client-protocol.h>
#include "base/strings/utf_string_conversions.h"
#include "ui/base/hit_test.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
#include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h"
namespace ui {
XDGToplevelWrapperImpl::XDGToplevelWrapperImpl(
std::unique_ptr<XDGSurfaceWrapperImpl> surface,
WaylandWindow* wayland_window,
WaylandConnection* connection)
: xdg_surface_wrapper_(std::move(surface)),
wayland_window_(wayland_window),
connection_(connection),
decoration_mode_(DecorationMode::kClientSide) {}
XDGToplevelWrapperImpl::~XDGToplevelWrapperImpl() = default;
bool XDGToplevelWrapperImpl::Initialize() {
if (!connection_->shell()) {
NOTREACHED() << "Wrong shell protocol";
return false;
}
static const xdg_toplevel_listener xdg_toplevel_listener = {
&XDGToplevelWrapperImpl::ConfigureTopLevel,
&XDGToplevelWrapperImpl::CloseTopLevel,
};
if (!xdg_surface_wrapper_)
return false;
xdg_toplevel_.reset(
xdg_surface_get_toplevel(xdg_surface_wrapper_->xdg_surface()));
if (!xdg_toplevel_) {
LOG(ERROR) << "Failed to create xdg_toplevel";
return false;
}
xdg_toplevel_add_listener(xdg_toplevel_.get(), &xdg_toplevel_listener, this);
InitializeXdgDecoration();
wayland_window_->root_surface()->Commit();
connection_->ScheduleFlush();
return true;
}
void XDGToplevelWrapperImpl::SetMaximized() {
DCHECK(xdg_toplevel_);
xdg_toplevel_set_maximized(xdg_toplevel_.get());
}
void XDGToplevelWrapperImpl::UnSetMaximized() {
DCHECK(xdg_toplevel_);
xdg_toplevel_unset_maximized(xdg_toplevel_.get());
}
void XDGToplevelWrapperImpl::SetFullscreen() {
DCHECK(xdg_toplevel_);
xdg_toplevel_set_fullscreen(xdg_toplevel_.get(), nullptr);
}
void XDGToplevelWrapperImpl::UnSetFullscreen() {
DCHECK(xdg_toplevel_);
xdg_toplevel_unset_fullscreen(xdg_toplevel_.get());
}
void XDGToplevelWrapperImpl::SetMinimized() {
DCHECK(xdg_toplevel_);
xdg_toplevel_set_minimized(xdg_toplevel_.get());
}
void XDGToplevelWrapperImpl::SurfaceMove(WaylandConnection* connection) {
DCHECK(xdg_toplevel_);
xdg_toplevel_move(xdg_toplevel_.get(), connection->seat(),
connection->serial());
}
void XDGToplevelWrapperImpl::SurfaceResize(WaylandConnection* connection,
uint32_t hittest) {
DCHECK(xdg_toplevel_);
xdg_toplevel_resize(xdg_toplevel_.get(), connection->seat(),
connection->serial(),
wl::IdentifyDirection(*connection, hittest));
}
void XDGToplevelWrapperImpl::SetTitle(const base::string16& title) {
DCHECK(xdg_toplevel_);
xdg_toplevel_set_title(xdg_toplevel_.get(), base::UTF16ToUTF8(title).c_str());
}
void XDGToplevelWrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) {
xdg_surface_wrapper_->SetWindowGeometry(bounds);
}
void XDGToplevelWrapperImpl::SetMinSize(int32_t width, int32_t height) {
DCHECK(xdg_toplevel_);
xdg_toplevel_set_min_size(xdg_toplevel_.get(), width, height);
}
void XDGToplevelWrapperImpl::SetMaxSize(int32_t width, int32_t height) {
DCHECK(xdg_toplevel_);
xdg_toplevel_set_max_size(xdg_toplevel_.get(), width, height);
}
void XDGToplevelWrapperImpl::SetAppId(const std::string& app_id) {
DCHECK(xdg_toplevel_);
xdg_toplevel_set_app_id(xdg_toplevel_.get(), app_id.c_str());
}
void XDGToplevelWrapperImpl::SetDecoration(DecorationMode decoration) {
SetTopLevelDecorationMode(decoration);
}
// static
void XDGToplevelWrapperImpl::ConfigureTopLevel(
void* data,
struct xdg_toplevel* xdg_toplevel,
int32_t width,
int32_t height,
struct wl_array* states) {
auto* surface = static_cast<XDGToplevelWrapperImpl*>(data);
DCHECK(surface);
bool is_maximized =
CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_MAXIMIZED);
bool is_fullscreen =
CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_FULLSCREEN);
bool is_activated =
CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_ACTIVATED);
surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized,
is_fullscreen, is_activated);
}
// static
void XDGToplevelWrapperImpl::CloseTopLevel(void* data,
struct xdg_toplevel* xdg_toplevel) {
auto* surface = static_cast<XDGToplevelWrapperImpl*>(data);
DCHECK(surface);
surface->wayland_window_->OnCloseRequest();
}
void XDGToplevelWrapperImpl::SetTopLevelDecorationMode(
DecorationMode requested_mode) {
if (!zxdg_toplevel_decoration_ || requested_mode == decoration_mode_)
return;
decoration_mode_ = requested_mode;
zxdg_toplevel_decoration_v1_set_mode(zxdg_toplevel_decoration_.get(),
static_cast<uint32_t>(requested_mode));
}
// static
void XDGToplevelWrapperImpl::ConfigureDecoration(
void* data,
struct zxdg_toplevel_decoration_v1* decoration,
uint32_t mode) {
auto* surface = static_cast<XDGToplevelWrapperImpl*>(data);
DCHECK(surface);
surface->SetTopLevelDecorationMode(static_cast<DecorationMode>(mode));
}
void XDGToplevelWrapperImpl::InitializeXdgDecoration() {
if (connection_->xdg_decoration_manager_v1()) {
DCHECK(!zxdg_toplevel_decoration_);
static const zxdg_toplevel_decoration_v1_listener decoration_listener = {
&XDGToplevelWrapperImpl::ConfigureDecoration,
};
zxdg_toplevel_decoration_.reset(
zxdg_decoration_manager_v1_get_toplevel_decoration(
connection_->xdg_decoration_manager_v1(), xdg_toplevel_.get()));
zxdg_toplevel_decoration_v1_add_listener(zxdg_toplevel_decoration_.get(),
&decoration_listener, this);
}
}
XDGSurfaceWrapperImpl* XDGToplevelWrapperImpl::xdg_surface_wrapper() const {
DCHECK(xdg_surface_wrapper_.get());
return xdg_surface_wrapper_.get();
}
} // namespace ui
// Copyright 2021 The Chromium Authors. All rights reserved.
// 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_XDG_TOPLEVEL_WRAPPER_IMPL_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_XDG_TOPLEVEL_WRAPPER_IMPL_H_
#include <memory>
#include "base/macros.h"
#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h"
namespace ui {
class XDGSurfaceWrapperImpl;
class WaylandConnection;
class WaylandWindow;
// Toplevel wrapper for xdg-shell stable
class XDGToplevelWrapperImpl : public ShellToplevelWrapper {
public:
XDGToplevelWrapperImpl(std::unique_ptr<XDGSurfaceWrapperImpl> surface,
WaylandWindow* wayland_window,
WaylandConnection* connection);
XDGToplevelWrapperImpl(const XDGToplevelWrapperImpl&) = delete;
XDGToplevelWrapperImpl& operator=(const XDGToplevelWrapperImpl&) = delete;
~XDGToplevelWrapperImpl() override;
// ShellSurfaceWrapper overrides:
bool Initialize() override;
void SetMaximized() override;
void UnSetMaximized() override;
void SetFullscreen() override;
void UnSetFullscreen() override;
void SetMinimized() override;
void SurfaceMove(WaylandConnection* connection) override;
void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override;
void SetTitle(const base::string16& title) override;
void SetWindowGeometry(const gfx::Rect& bounds) override;
void SetMinSize(int32_t width, int32_t height) override;
void SetMaxSize(int32_t width, int32_t height) override;
void SetAppId(const std::string& app_id) override;
void SetDecoration(DecorationMode decoration) override;
XDGSurfaceWrapperImpl* xdg_surface_wrapper() const;
private:
// xdg_toplevel_listener
static void ConfigureTopLevel(void* data,
struct xdg_toplevel* xdg_toplevel,
int32_t width,
int32_t height,
struct wl_array* states);
static void CloseTopLevel(void* data, struct xdg_toplevel* xdg_toplevel);
// zxdg_decoration_listener
static void ConfigureDecoration(
void* data,
struct zxdg_toplevel_decoration_v1* decoration,
uint32_t mode);
// Send request to wayland compositor to enable a requested decoration mode.
void SetTopLevelDecorationMode(DecorationMode requested_mode);
// Initializes the xdg-decoration protocol extension, if available.
void InitializeXdgDecoration();
// Ground surface for this toplevel wrapper.
std::unique_ptr<XDGSurfaceWrapperImpl> xdg_surface_wrapper_;
// Non-owing WaylandWindow that uses this toplevel wrapper.
WaylandWindow* const wayland_window_;
WaylandConnection* const connection_;
// XDG Shell Stable object.
wl::Object<xdg_toplevel> xdg_toplevel_;
wl::Object<zxdg_toplevel_decoration_v1> zxdg_toplevel_decoration_;
// On client side, it keeps track of the decoration mode currently in
// use if xdg-decoration protocol extension is available.
DecorationMode decoration_mode_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_XDG_TOPLEVEL_WRAPPER_IMPL_H_
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.h"
#include <xdg-shell-unstable-v6-client-protocol.h>
#include <memory>
#include "base/environment.h"
#include "base/nix/xdg_util.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/types/event_type.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_pointer.h"
#include "ui/ozone/platform/wayland/host/wayland_popup.h"
#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
#include "ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h"
#include "ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h"
namespace ui {
namespace {
uint32_t TranslateAnchor(WlAnchor anchor) {
switch (anchor) {
case WlAnchor::None:
return ZXDG_POSITIONER_V6_ANCHOR_NONE;
case WlAnchor::Top:
return ZXDG_POSITIONER_V6_ANCHOR_TOP;
case WlAnchor::Bottom:
return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
case WlAnchor::Left:
return ZXDG_POSITIONER_V6_ANCHOR_LEFT;
case WlAnchor::Right:
return ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
case WlAnchor::TopLeft:
return ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_LEFT;
case WlAnchor::BottomLeft:
return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_LEFT;
case WlAnchor::TopRight:
return ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
case WlAnchor::BottomRight:
return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
}
}
uint32_t TranslateGravity(WlGravity gravity) {
switch (gravity) {
case WlGravity::None:
return ZXDG_POSITIONER_V6_GRAVITY_NONE;
case WlGravity::Top:
return ZXDG_POSITIONER_V6_GRAVITY_TOP;
case WlGravity::Bottom:
return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
case WlGravity::Left:
return ZXDG_POSITIONER_V6_GRAVITY_LEFT;
case WlGravity::Right:
return ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
case WlGravity::TopLeft:
return ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_LEFT;
case WlGravity::BottomLeft:
return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
ZXDG_POSITIONER_V6_GRAVITY_LEFT;
case WlGravity::TopRight:
return ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
case WlGravity::BottomRight:
return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
}
}
uint32_t TranslateConstraintAdjustment(
WlConstraintAdjustment constraint_adjustment) {
uint32_t res = 0;
if ((constraint_adjustment & WlConstraintAdjustment::SlideX) !=
WlConstraintAdjustment::None)
res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X;
if ((constraint_adjustment & WlConstraintAdjustment::SlideY) !=
WlConstraintAdjustment::None)
res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
if ((constraint_adjustment & WlConstraintAdjustment::FlipX) !=
WlConstraintAdjustment::None)
res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X;
if ((constraint_adjustment & WlConstraintAdjustment::FlipY) !=
WlConstraintAdjustment::None)
res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y;
if ((constraint_adjustment & WlConstraintAdjustment::ResizeX) !=
WlConstraintAdjustment::None)
res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X;
if ((constraint_adjustment & WlConstraintAdjustment::ResizeY) !=
WlConstraintAdjustment::None)
res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
return res;
}
} // namespace
ZXDGPopupV6WrapperImpl::ZXDGPopupV6WrapperImpl(
std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface,
WaylandWindow* wayland_window)
: wayland_window_(wayland_window),
zxdg_surface_v6_wrapper_(std::move(surface)) {
DCHECK(zxdg_surface_v6_wrapper_);
DCHECK(wayland_window_ && wayland_window_->parent_window());
}
ZXDGPopupV6WrapperImpl::~ZXDGPopupV6WrapperImpl() = default;
bool ZXDGPopupV6WrapperImpl::Initialize(WaylandConnection* connection,
const gfx::Rect& bounds) {
if (!connection->shell() && !connection->shell_v6()) {
NOTREACHED() << "Wrong shell protocol";
return false;
}
ZXDGSurfaceV6WrapperImpl* parent_xdg_surface = nullptr;
// If the parent window is a popup, the surface of that popup must be used as
// a parent.
if (wl::IsMenuType(wayland_window_->parent_window()->type())) {
auto* wayland_popup =
static_cast<WaylandPopup*>(wayland_window_->parent_window());
ZXDGPopupV6WrapperImpl* popup =
static_cast<ZXDGPopupV6WrapperImpl*>(wayland_popup->shell_popup());
parent_xdg_surface = popup->zxdg_surface_v6_wrapper();
} else {
WaylandToplevelWindow* wayland_surface =
static_cast<WaylandToplevelWindow*>(wayland_window_->parent_window());
parent_xdg_surface = static_cast<ZXDGToplevelV6WrapperImpl*>(
wayland_surface->shell_toplevel())
->zxdg_surface_v6_wrapper();
}
if (!zxdg_surface_v6_wrapper_ || !parent_xdg_surface)
return false;
auto new_bounds = bounds;
// Wayland doesn't allow empty bounds. If a zero or negative size is set, the
// invalid_input error is raised. Thus, use the least possible one.
// WaylandPopup will update its bounds upon the following configure event.
if (new_bounds.IsEmpty())
new_bounds.set_size({1, 1});
if (connection->shell_v6())
return InitializeV6(connection, new_bounds, parent_xdg_surface);
return false;
}
bool ZXDGPopupV6WrapperImpl::InitializeV6(
WaylandConnection* connection,
const gfx::Rect& bounds,
ZXDGSurfaceV6WrapperImpl* parent_xdg_surface) {
static const struct zxdg_popup_v6_listener zxdg_popup_v6_listener = {
&ZXDGPopupV6WrapperImpl::Configure,
&ZXDGPopupV6WrapperImpl::PopupDone,
};
zxdg_positioner_v6* positioner =
CreatePositioner(connection, wayland_window_->parent_window(), bounds);
if (!positioner)
return false;
zxdg_popup_v6_.reset(zxdg_surface_v6_get_popup(
zxdg_surface_v6_wrapper_->zxdg_surface(),
parent_xdg_surface->zxdg_surface(), positioner));
if (!zxdg_popup_v6_)
return false;
zxdg_positioner_v6_destroy(positioner);
if (CanGrabPopup(connection)) {
zxdg_popup_v6_grab(zxdg_popup_v6_.get(), connection->seat(),
connection->serial());
}
zxdg_popup_v6_add_listener(zxdg_popup_v6_.get(), &zxdg_popup_v6_listener,
this);
wayland_window_->root_surface()->Commit();
return true;
}
zxdg_positioner_v6* ZXDGPopupV6WrapperImpl::CreatePositioner(
WaylandConnection* connection,
WaylandWindow* parent_window,
const gfx::Rect& bounds) {
struct zxdg_positioner_v6* positioner;
positioner = zxdg_shell_v6_create_positioner(connection->shell_v6());
if (!positioner)
return nullptr;
auto menu_type = GetMenuTypeForPositioner(connection, parent_window);
// The parent we got must be the topmost in the stack of the same family
// windows.
DCHECK_EQ(parent_window->GetTopMostChildWindow(), parent_window);
// Place anchor to the end of the possible position.
gfx::Rect anchor_rect = GetAnchorRect(
menu_type, bounds,
gfx::ScaleToRoundedRect(parent_window->GetBounds(),
1.0 / parent_window->buffer_scale()));
zxdg_positioner_v6_set_anchor_rect(positioner, anchor_rect.x(),
anchor_rect.y(), anchor_rect.width(),
anchor_rect.height());
zxdg_positioner_v6_set_size(positioner, bounds.width(), bounds.height());
zxdg_positioner_v6_set_anchor(positioner,
TranslateAnchor(GetAnchor(menu_type, bounds)));
zxdg_positioner_v6_set_gravity(
positioner, TranslateGravity(GetGravity(menu_type, bounds)));
zxdg_positioner_v6_set_constraint_adjustment(
positioner,
TranslateConstraintAdjustment(GetConstraintAdjustment(menu_type)));
return positioner;
}
// static
void ZXDGPopupV6WrapperImpl::Configure(void* data,
struct zxdg_popup_v6* zxdg_popup_v6,
int32_t x,
int32_t y,
int32_t width,
int32_t height) {
// As long as the Wayland compositor repositions/requires to position windows
// relative to their parents, do not propagate final bounds information to
// Chromium. The browser places windows in respect to screen origin, but
// Wayland requires doing so in respect to parent window's origin. To properly
// place windows, the bounds are translated and adjusted according to the
// Wayland compositor needs during WaylandWindow::CreateXdgPopup call.
WaylandWindow* window =
static_cast<ZXDGPopupV6WrapperImpl*>(data)->wayland_window_;
DCHECK(window);
window->HandlePopupConfigure({x, y, width, height});
}
// static
void ZXDGPopupV6WrapperImpl::PopupDone(void* data,
struct zxdg_popup_v6* zxdg_popup_v6) {
WaylandWindow* window =
static_cast<ZXDGPopupV6WrapperImpl*>(data)->wayland_window_;
DCHECK(window);
window->Hide();
window->OnCloseRequest();
}
ZXDGSurfaceV6WrapperImpl* ZXDGPopupV6WrapperImpl::zxdg_surface_v6_wrapper()
const {
DCHECK(zxdg_surface_v6_wrapper_.get());
return zxdg_surface_v6_wrapper_.get();
}
} // namespace ui
// Copyright 2021 The Chromium Authors. All rights reserved.
// 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_ZXDG_POPUP_V6_WRAPPER_IMPL_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_POPUP_V6_WRAPPER_IMPL_H_
#include <memory>
#include "base/macros.h"
#include "ui/ozone/platform/wayland/host/shell_popup_wrapper.h"
namespace ui {
class ZXDGSurfaceV6WrapperImpl;
class WaylandConnection;
class WaylandWindow;
// Popup wrapper for xdg-shell-unstable-v6
class ZXDGPopupV6WrapperImpl : public ShellPopupWrapper {
public:
ZXDGPopupV6WrapperImpl(std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface,
WaylandWindow* wayland_window);
~ZXDGPopupV6WrapperImpl() override;
// XDGPopupWrapper:
bool Initialize(WaylandConnection* connection,
const gfx::Rect& bounds) override;
private:
bool InitializeV6(WaylandConnection* connection,
const gfx::Rect& bounds,
ZXDGSurfaceV6WrapperImpl* parent_zxdg_surface_v6_wrapper);
struct zxdg_positioner_v6* CreatePositioner(WaylandConnection* connection,
WaylandWindow* parent_window,
const gfx::Rect& bounds);
// zxdg_popup_v6_listener
static void Configure(void* data,
struct zxdg_popup_v6* zxdg_popup_v6,
int32_t x,
int32_t y,
int32_t width,
int32_t height);
static void PopupDone(void* data, struct zxdg_popup_v6* zxdg_popup_v6);
ZXDGSurfaceV6WrapperImpl* zxdg_surface_v6_wrapper() const;
// Non-owned WaylandWindow that uses this popup.
WaylandWindow* const wayland_window_;
// Ground surface for this popup.
std::unique_ptr<ZXDGSurfaceV6WrapperImpl> zxdg_surface_v6_wrapper_;
// XDG Shell V6 object.
wl::Object<zxdg_popup_v6> zxdg_popup_v6_;
DISALLOW_COPY_AND_ASSIGN(ZXDGPopupV6WrapperImpl);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_POPUP_V6_WRAPPER_IMPL_H_
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h"
#include <xdg-shell-unstable-v6-client-protocol.h>
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
namespace ui {
ZXDGSurfaceV6WrapperImpl::ZXDGSurfaceV6WrapperImpl(
WaylandWindow* wayland_window,
WaylandConnection* connection)
: wayland_window_(wayland_window), connection_(connection) {}
ZXDGSurfaceV6WrapperImpl::~ZXDGSurfaceV6WrapperImpl() = default;
bool ZXDGSurfaceV6WrapperImpl::Initialize() {
if (!connection_->shell_v6()) {
NOTREACHED() << "Wrong shell protocol";
return false;
}
static const zxdg_surface_v6_listener zxdg_surface_v6_listener = {
&ZXDGSurfaceV6WrapperImpl::Configure,
};
zxdg_surface_v6_.reset(zxdg_shell_v6_get_xdg_surface(
connection_->shell_v6(), wayland_window_->root_surface()->surface()));
if (!zxdg_surface_v6_) {
LOG(ERROR) << "Failed to create zxdg_surface";
return false;
}
zxdg_surface_v6_add_listener(zxdg_surface_v6_.get(),
&zxdg_surface_v6_listener, this);
connection_->ScheduleFlush();
return true;
}
void ZXDGSurfaceV6WrapperImpl::AckConfigure() {
DCHECK(zxdg_surface_v6_);
zxdg_surface_v6_ack_configure(zxdg_surface_v6_.get(),
pending_configure_serial_);
connection_->wayland_window_manager()->NotifyWindowConfigured(
wayland_window_);
}
void ZXDGSurfaceV6WrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) {
DCHECK(zxdg_surface_v6_);
zxdg_surface_v6_set_window_geometry(zxdg_surface_v6_.get(), bounds.x(),
bounds.y(), bounds.width(),
bounds.height());
}
// static
void ZXDGSurfaceV6WrapperImpl::Configure(
void* data,
struct zxdg_surface_v6* zxdg_surface_v6,
uint32_t serial) {
auto* surface = static_cast<ZXDGSurfaceV6WrapperImpl*>(data);
DCHECK(surface);
surface->pending_configure_serial_ = serial;
surface->AckConfigure();
}
zxdg_surface_v6* ZXDGSurfaceV6WrapperImpl::zxdg_surface() const {
DCHECK(zxdg_surface_v6_);
return zxdg_surface_v6_.get();
}
} // namespace ui
// Copyright 2021 The Chromium Authors. All rights reserved.
// 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_ZXDG_SURFACE_V6_WRAPPER_IMPL_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_SURFACE_V6_WRAPPER_IMPL_H_
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
#include <cstdint>
#include <string>
#include "base/strings/string16.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
namespace gfx {
class Rect;
}
namespace ui {
class WaylandConnection;
class WaylandWindow;
// Surface wrapper for xdg-shell-unstable-v6
class ZXDGSurfaceV6WrapperImpl : public ShellSurfaceWrapper {
public:
ZXDGSurfaceV6WrapperImpl(WaylandWindow* wayland_window,
WaylandConnection* connection);
ZXDGSurfaceV6WrapperImpl(const ZXDGSurfaceV6WrapperImpl&) = delete;
ZXDGSurfaceV6WrapperImpl& operator=(const ZXDGSurfaceV6WrapperImpl&) = delete;
~ZXDGSurfaceV6WrapperImpl() override;
// ShellSurfaceWrapper overrides:
bool Initialize() override;
void AckConfigure() override;
void SetWindowGeometry(const gfx::Rect& bounds) override;
// zxdg_surface_v6_listener
static void Configure(void* data,
struct zxdg_surface_v6* zxdg_surface_v6,
uint32_t serial);
zxdg_surface_v6* zxdg_surface() const;
private:
// Non-owing WaylandWindow that uses this surface wrapper.
WaylandWindow* const wayland_window_;
WaylandConnection* const connection_;
uint32_t pending_configure_serial_ = 0;
wl::Object<zxdg_surface_v6> zxdg_surface_v6_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_SURFACE_V6_WRAPPER_IMPL_H_
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h"
#include <xdg-decoration-unstable-v1-client-protocol.h>
#include <xdg-shell-client-protocol.h>
#include <xdg-shell-unstable-v6-client-protocol.h>
#include "base/strings/utf_string_conversions.h"
#include "ui/base/hit_test.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
#include "ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h"
namespace ui {
ZXDGToplevelV6WrapperImpl::ZXDGToplevelV6WrapperImpl(
std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface,
WaylandWindow* wayland_window,
WaylandConnection* connection)
: zxdg_surface_v6_wrapper_(std::move(surface)),
wayland_window_(wayland_window),
connection_(connection) {}
ZXDGToplevelV6WrapperImpl::~ZXDGToplevelV6WrapperImpl() = default;
bool ZXDGToplevelV6WrapperImpl::Initialize() {
if (!connection_->shell_v6()) {
NOTREACHED() << "Wrong shell protocol";
return false;
}
static const zxdg_toplevel_v6_listener zxdg_toplevel_v6_listener = {
&ZXDGToplevelV6WrapperImpl::ConfigureTopLevel,
&ZXDGToplevelV6WrapperImpl::CloseTopLevel,
};
if (!zxdg_surface_v6_wrapper_)
return false;
zxdg_toplevel_v6_.reset(
zxdg_surface_v6_get_toplevel(zxdg_surface_v6_wrapper_->zxdg_surface()));
if (!zxdg_toplevel_v6_) {
LOG(ERROR) << "Failed to create zxdg_toplevel";
return false;
}
zxdg_toplevel_v6_add_listener(zxdg_toplevel_v6_.get(),
&zxdg_toplevel_v6_listener, this);
wayland_window_->root_surface()->Commit();
connection_->ScheduleFlush();
return true;
}
void ZXDGToplevelV6WrapperImpl::SetMaximized() {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_set_maximized(zxdg_toplevel_v6_.get());
}
void ZXDGToplevelV6WrapperImpl::UnSetMaximized() {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_unset_maximized(zxdg_toplevel_v6_.get());
}
void ZXDGToplevelV6WrapperImpl::SetFullscreen() {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_set_fullscreen(zxdg_toplevel_v6_.get(), nullptr);
}
void ZXDGToplevelV6WrapperImpl::UnSetFullscreen() {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_unset_fullscreen(zxdg_toplevel_v6_.get());
}
void ZXDGToplevelV6WrapperImpl::SetMinimized() {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_set_minimized(zxdg_toplevel_v6_.get());
}
void ZXDGToplevelV6WrapperImpl::SurfaceMove(WaylandConnection* connection) {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_move(zxdg_toplevel_v6_.get(), connection->seat(),
connection->serial());
}
void ZXDGToplevelV6WrapperImpl::SurfaceResize(WaylandConnection* connection,
uint32_t hittest) {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_resize(zxdg_toplevel_v6_.get(), connection->seat(),
connection->serial(),
wl::IdentifyDirection(*connection, hittest));
}
void ZXDGToplevelV6WrapperImpl::SetTitle(const base::string16& title) {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_set_title(zxdg_toplevel_v6_.get(),
base::UTF16ToUTF8(title).c_str());
}
void ZXDGToplevelV6WrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) {
zxdg_surface_v6_wrapper_->SetWindowGeometry(bounds);
}
void ZXDGToplevelV6WrapperImpl::SetMinSize(int32_t width, int32_t height) {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_set_min_size(zxdg_toplevel_v6_.get(), width, height);
}
void ZXDGToplevelV6WrapperImpl::SetMaxSize(int32_t width, int32_t height) {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_set_max_size(zxdg_toplevel_v6_.get(), width, height);
}
void ZXDGToplevelV6WrapperImpl::SetAppId(const std::string& app_id) {
DCHECK(zxdg_toplevel_v6_);
zxdg_toplevel_v6_set_app_id(zxdg_toplevel_v6_.get(), app_id.c_str());
}
void ZXDGToplevelV6WrapperImpl::SetDecoration(DecorationMode decoration) {}
// static
void ZXDGToplevelV6WrapperImpl::ConfigureTopLevel(
void* data,
struct zxdg_toplevel_v6* zxdg_toplevel_v6,
int32_t width,
int32_t height,
struct wl_array* states) {
auto* surface = static_cast<ZXDGToplevelV6WrapperImpl*>(data);
DCHECK(surface);
bool is_maximized =
CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED);
bool is_fullscreen =
CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN);
bool is_activated =
CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED);
surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized,
is_fullscreen, is_activated);
}
// static
void ZXDGToplevelV6WrapperImpl::CloseTopLevel(
void* data,
struct zxdg_toplevel_v6* zxdg_toplevel_v6) {
auto* surface = static_cast<ZXDGToplevelV6WrapperImpl*>(data);
DCHECK(surface);
surface->wayland_window_->OnCloseRequest();
}
ZXDGSurfaceV6WrapperImpl* ZXDGToplevelV6WrapperImpl::zxdg_surface_v6_wrapper()
const {
DCHECK(zxdg_surface_v6_wrapper_.get());
return zxdg_surface_v6_wrapper_.get();
}
} // namespace ui
// Copyright 2021 The Chromium Authors. All rights reserved.
// 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_ZXDG_TOPLEVEL_V6_WRAPPER_IMPL_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_TOPLEVEL_V6_WRAPPER_IMPL_H_
#include <memory>
#include "base/macros.h"
#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h"
namespace ui {
class ZXDGSurfaceV6WrapperImpl;
class WaylandConnection;
class WaylandWindow;
// Toplevel wrapper for xdg-shell-unstable-v6
class ZXDGToplevelV6WrapperImpl : public ShellToplevelWrapper {
public:
ZXDGToplevelV6WrapperImpl(std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface,
WaylandWindow* wayland_window,
WaylandConnection* connection);
ZXDGToplevelV6WrapperImpl(const ZXDGToplevelV6WrapperImpl&) = delete;
ZXDGToplevelV6WrapperImpl& operator=(const ZXDGToplevelV6WrapperImpl&) =
delete;
~ZXDGToplevelV6WrapperImpl() override;
// ShellSurfaceWrapper overrides:
bool Initialize() override;
void SetMaximized() override;
void UnSetMaximized() override;
void SetFullscreen() override;
void UnSetFullscreen() override;
void SetMinimized() override;
void SurfaceMove(WaylandConnection* connection) override;
void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override;
void SetTitle(const base::string16& title) override;
void SetWindowGeometry(const gfx::Rect& bounds) override;
void SetMinSize(int32_t width, int32_t height) override;
void SetMaxSize(int32_t width, int32_t height) override;
void SetAppId(const std::string& app_id) override;
void SetDecoration(DecorationMode decoration) override;
ZXDGSurfaceV6WrapperImpl* zxdg_surface_v6_wrapper() const;
private:
// zxdg_toplevel_v6_listener
static void ConfigureTopLevel(void* data,
struct zxdg_toplevel_v6* zxdg_toplevel_v6,
int32_t width,
int32_t height,
struct wl_array* states);
static void CloseTopLevel(void* data,
struct zxdg_toplevel_v6* zxdg_toplevel_v6);
// Ground surface for this toplevel wrapper.
std::unique_ptr<ZXDGSurfaceV6WrapperImpl> zxdg_surface_v6_wrapper_;
// Non-owing WaylandWindow that uses this toplevel wrapper.
WaylandWindow* const wayland_window_;
WaylandConnection* const connection_;
// XDG Shell V6 object.
wl::Object<zxdg_toplevel_v6> zxdg_toplevel_v6_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_TOPLEVEL_V6_WRAPPER_IMPL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment