GHOST/Wayland: support client-side window decorations
This implements client-side window decorations for moving and resizing windows and HiDPI support. This functionality depends on the external project 'libdecor' that is currently a build option: WITH_GHOST_WAYLAND_LIBDECOR. Reviewed by: brecht, campbellbarton Ref D7989
This commit is contained in:
parent
f1d191120f
commit
29755e1df8
Notes:
blender-bot
2023-02-13 22:37:44 +01:00
Referenced by issue #76428, GHOST/Wayland Support
|
@ -222,6 +222,11 @@ if(UNIX AND NOT (APPLE OR HAIKU))
|
|||
|
||||
option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing (under development)" OFF)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND)
|
||||
|
||||
if (WITH_GHOST_WAYLAND)
|
||||
option(WITH_GHOST_WAYLAND_LIBDECOR "Optionally build with LibDecor window decorations" OFF)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_X11)
|
||||
|
|
|
@ -615,6 +615,10 @@ if(WITH_GHOST_WAYLAND)
|
|||
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
|
||||
pkg_check_modules(dbus REQUIRED dbus-1)
|
||||
|
||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
pkg_check_modules(libdecor REQUIRED libdecor-0>=0.1)
|
||||
endif()
|
||||
|
||||
set(WITH_GL_EGL ON)
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
|
@ -624,6 +628,13 @@ if(WITH_GHOST_WAYLAND)
|
|||
${wayland-cursor_LINK_LIBRARIES}
|
||||
${dbus_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${libdecor_LIBRARIES}
|
||||
)
|
||||
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_X11)
|
||||
|
|
|
@ -271,6 +271,12 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
${dbus_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
list(APPEND INC_SYS
|
||||
${libdecor_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
include(CheckSymbolExists)
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
|
||||
check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE)
|
||||
|
@ -332,14 +338,17 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
${INC_DST}
|
||||
)
|
||||
|
||||
# `xdg-shell`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||
)
|
||||
# `xdg-decoration`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||
)
|
||||
if(NOT WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
# `xdg-shell`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||
)
|
||||
# `xdg-decoration`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||
)
|
||||
endif()
|
||||
|
||||
# `xdg-output`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-output/xdg-output-unstable-v1.xml"
|
||||
|
|
|
@ -254,8 +254,14 @@ struct display_t {
|
|||
|
||||
struct wl_display *display = nullptr;
|
||||
struct wl_compositor *compositor = nullptr;
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
struct libdecor *decor_context = nullptr;
|
||||
#else
|
||||
struct xdg_wm_base *xdg_shell = nullptr;
|
||||
struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
|
||||
#endif
|
||||
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
|
||||
struct wl_shm *shm = nullptr;
|
||||
std::vector<output_t *> outputs;
|
||||
|
@ -402,6 +408,11 @@ static void display_destroy(display_t *d)
|
|||
wl_compositor_destroy(d->compositor);
|
||||
}
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (d->decor_context) {
|
||||
libdecor_unref(d->decor_context);
|
||||
}
|
||||
#else
|
||||
if (d->xdg_decoration_manager) {
|
||||
zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager);
|
||||
}
|
||||
|
@ -409,6 +420,7 @@ static void display_destroy(display_t *d)
|
|||
if (d->xdg_shell) {
|
||||
xdg_wm_base_destroy(d->xdg_shell);
|
||||
}
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
if (eglGetDisplay) {
|
||||
::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
|
||||
|
@ -2190,6 +2202,8 @@ static const struct wl_output_listener output_listener = {
|
|||
/** \name Listener (XDG WM Base), #xdg_wm_base_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static void shell_handle_ping(void * /*data*/,
|
||||
struct xdg_wm_base *xdg_wm_base,
|
||||
const uint32_t serial)
|
||||
|
@ -2201,6 +2215,32 @@ static const struct xdg_wm_base_listener shell_listener = {
|
|||
shell_handle_ping,
|
||||
};
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (LibDecor), #libdecor_interface
|
||||
* \{ */
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static void decor_handle_error(struct libdecor * /*context*/,
|
||||
enum libdecor_error error,
|
||||
const char *message)
|
||||
{
|
||||
(void)(error);
|
||||
(void)(message);
|
||||
GHOST_PRINT("decoration error (" << error << "): " << message << std::endl);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static struct libdecor_interface libdecor_interface = {
|
||||
decor_handle_error,
|
||||
};
|
||||
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -2218,6 +2258,9 @@ static void global_handle_add(void *data,
|
|||
display->compositor = static_cast<wl_compositor *>(
|
||||
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
|
||||
}
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
/* Pass. */
|
||||
#else
|
||||
else if (!strcmp(interface, xdg_wm_base_interface.name)) {
|
||||
display->xdg_shell = static_cast<xdg_wm_base *>(
|
||||
wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
|
||||
|
@ -2227,6 +2270,7 @@ static void global_handle_add(void *data,
|
|||
display->xdg_decoration_manager = static_cast<zxdg_decoration_manager_v1 *>(
|
||||
wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1));
|
||||
}
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
else if (!strcmp(interface, zxdg_output_manager_v1_interface.name)) {
|
||||
display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
|
||||
wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 3));
|
||||
|
@ -2330,10 +2374,18 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t)
|
|||
wl_display_roundtrip(d->display);
|
||||
wl_registry_destroy(registry);
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
d->decor_context = libdecor_new(d->display, &libdecor_interface);
|
||||
if (!d->decor_context) {
|
||||
display_destroy(d);
|
||||
throw std::runtime_error("Wayland: unable to create window decorations!");
|
||||
}
|
||||
#else
|
||||
if (!d->xdg_shell) {
|
||||
display_destroy(d);
|
||||
throw std::runtime_error("Wayland: unable to access xdg_shell!");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Register data device per seat for IPC between Wayland clients. */
|
||||
if (d->data_device_manager) {
|
||||
|
@ -2667,6 +2719,15 @@ wl_compositor *GHOST_SystemWayland::compositor()
|
|||
return d->compositor;
|
||||
}
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
libdecor *GHOST_SystemWayland::decor_context()
|
||||
{
|
||||
return d->decor_context;
|
||||
}
|
||||
|
||||
#else /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
xdg_wm_base *GHOST_SystemWayland::xdg_shell()
|
||||
{
|
||||
return d->xdg_shell;
|
||||
|
@ -2677,6 +2738,8 @@ zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decoration_manager()
|
|||
return d->xdg_decoration_manager;
|
||||
}
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
const std::vector<output_t *> &GHOST_SystemWayland::outputs() const
|
||||
{
|
||||
return d->outputs;
|
||||
|
|
|
@ -13,9 +13,13 @@
|
|||
|
||||
#include <wayland-client.h>
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
# include <libdecor.h>
|
||||
#else
|
||||
/* Generated by `wayland-scanner`. */
|
||||
#include <xdg-decoration-unstable-v1-client-protocol.h>
|
||||
#include <xdg-shell-client-protocol.h>
|
||||
# include <xdg-decoration-unstable-v1-client-protocol.h>
|
||||
# include <xdg-shell-client-protocol.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -103,9 +107,12 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
|
||||
wl_compositor *compositor();
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor *decor_context();
|
||||
#else
|
||||
xdg_wm_base *xdg_shell();
|
||||
|
||||
zxdg_decoration_manager_v1 *xdg_decoration_manager();
|
||||
#endif
|
||||
|
||||
const std::vector<output_t *> &outputs() const;
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
#include <algorithm> /* For `std::find`. */
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
# include <libdecor.h>
|
||||
#endif
|
||||
|
||||
static constexpr size_t base_dpi = 96;
|
||||
|
||||
struct window_t {
|
||||
|
@ -41,10 +45,17 @@ struct window_t {
|
|||
*/
|
||||
uint32_t dpi = 0;
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
struct libdecor_frame *decor_frame = nullptr;
|
||||
bool decor_configured = false;
|
||||
#else
|
||||
struct xdg_surface *xdg_surface = nullptr;
|
||||
struct xdg_toplevel *xdg_toplevel = nullptr;
|
||||
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration = nullptr;
|
||||
struct xdg_toplevel *xdg_toplevel = nullptr;
|
||||
|
||||
enum zxdg_toplevel_decoration_v1_mode decoration_mode = (enum zxdg_toplevel_decoration_v1_mode)0;
|
||||
#endif
|
||||
|
||||
wl_egl_window *egl_window = nullptr;
|
||||
bool is_maximised = false;
|
||||
bool is_fullscreen = false;
|
||||
|
@ -121,6 +132,8 @@ static int outputs_max_scale_or_default(const std::vector<output_t *> &outputs,
|
|||
/** \name Listener (XDG Top Level), #xdg_toplevel_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static void xdg_toplevel_handle_configure(void *data,
|
||||
xdg_toplevel * /*xdg_toplevel*/,
|
||||
const int32_t width,
|
||||
|
@ -163,12 +176,83 @@ static const xdg_toplevel_listener toplevel_listener = {
|
|||
xdg_toplevel_handle_close,
|
||||
};
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (LibDecor Frame), #libdecor_frame_interface
|
||||
* \{ */
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static void frame_handle_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration,
|
||||
void *data)
|
||||
{
|
||||
window_t *win = static_cast<window_t *>(data);
|
||||
|
||||
int size_next[2];
|
||||
enum libdecor_window_state window_state;
|
||||
struct libdecor_state *state;
|
||||
|
||||
if (!libdecor_configuration_get_content_size(
|
||||
configuration, frame, &size_next[0], &size_next[1])) {
|
||||
size_next[0] = win->size[0] / win->scale;
|
||||
size_next[1] = win->size[1] / win->scale;
|
||||
}
|
||||
|
||||
win->size[0] = win->scale * size_next[0];
|
||||
win->size[1] = win->scale * size_next[1];
|
||||
|
||||
wl_egl_window_resize(win->egl_window, win->size[0], win->size[1], 0, 0);
|
||||
win->w->notify_size();
|
||||
|
||||
if (!libdecor_configuration_get_window_state(configuration, &window_state)) {
|
||||
window_state = LIBDECOR_WINDOW_STATE_NONE;
|
||||
}
|
||||
|
||||
win->is_maximised = window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED;
|
||||
win->is_fullscreen = window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN;
|
||||
win->is_active = window_state & LIBDECOR_WINDOW_STATE_ACTIVE;
|
||||
|
||||
win->is_active ? win->w->activate() : win->w->deactivate();
|
||||
|
||||
state = libdecor_state_new(size_next[0], size_next[1]);
|
||||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
|
||||
win->decor_configured = true;
|
||||
}
|
||||
|
||||
static void frame_handle_close(struct libdecor_frame * /*frame*/, void *data)
|
||||
{
|
||||
static_cast<window_t *>(data)->w->close();
|
||||
}
|
||||
|
||||
static void frame_handle_commit(struct libdecor_frame * /*frame*/, void *data)
|
||||
{
|
||||
/* we have to swap twice to keep any pop-up menues alive */
|
||||
static_cast<window_t *>(data)->w->swapBuffers();
|
||||
static_cast<window_t *>(data)->w->swapBuffers();
|
||||
}
|
||||
|
||||
static struct libdecor_frame_interface libdecor_frame_iface = {
|
||||
frame_handle_configure,
|
||||
frame_handle_close,
|
||||
frame_handle_commit,
|
||||
};
|
||||
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (XDG Decoration Listener), #zxdg_toplevel_decoration_v1_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static void xdg_toplevel_decoration_handle_configure(
|
||||
void *data,
|
||||
struct zxdg_toplevel_decoration_v1 * /*zxdg_toplevel_decoration_v1*/,
|
||||
|
@ -181,12 +265,16 @@ static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listene
|
|||
xdg_toplevel_decoration_handle_configure,
|
||||
};
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (XDG Surface Handle Configure), #xdg_surface_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static void xdg_surface_handle_configure(void *data,
|
||||
xdg_surface *xdg_surface,
|
||||
const uint32_t serial)
|
||||
|
@ -220,6 +308,8 @@ static const xdg_surface_listener xdg_surface_listener = {
|
|||
xdg_surface_handle_configure,
|
||||
};
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -316,6 +406,19 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
|
||||
w->egl_window = wl_egl_window_create(w->wl_surface, int(w->size[0]), int(w->size[1]));
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
/* create window decorations */
|
||||
w->decor_frame = libdecor_decorate(
|
||||
m_system->decor_context(), w->wl_surface, &libdecor_frame_iface, w);
|
||||
libdecor_frame_map(w->decor_frame);
|
||||
|
||||
if (parentWindow) {
|
||||
libdecor_frame_set_parent(
|
||||
w->decor_frame, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->decor_frame);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->xdg_shell(), w->wl_surface);
|
||||
w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
|
||||
|
||||
|
@ -334,8 +437,6 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
}
|
||||
|
||||
wl_surface_set_user_data(w->wl_surface, this);
|
||||
|
||||
xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
|
||||
xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
|
||||
|
||||
|
@ -344,15 +445,31 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
|
||||
}
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
wl_surface_set_user_data(w->wl_surface, this);
|
||||
|
||||
/* Call top-level callbacks. */
|
||||
wl_surface_commit(w->wl_surface);
|
||||
wl_display_roundtrip(m_system->display());
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
/* It's important not to return until the window is configured or
|
||||
* calls to `setState` from Blender will crash `libdecor`. */
|
||||
while (!w->decor_configured) {
|
||||
if (libdecor_dispatch(m_system->decor_context(), 0) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GHOST_OPENGL_ALPHA
|
||||
setOpaque();
|
||||
#endif
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR /* Causes a glicth with libdecor for some reason. */
|
||||
setState(state);
|
||||
#endif
|
||||
|
||||
setTitle(title);
|
||||
|
||||
|
@ -512,8 +629,14 @@ GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
|
|||
|
||||
void GHOST_WindowWayland::setTitle(const char *title)
|
||||
{
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_app_id(w->decor_frame, title);
|
||||
libdecor_frame_set_title(w->decor_frame, title);
|
||||
#else
|
||||
xdg_toplevel_set_title(w->xdg_toplevel, title);
|
||||
xdg_toplevel_set_app_id(w->xdg_toplevel, title);
|
||||
#endif
|
||||
|
||||
this->title = title;
|
||||
}
|
||||
|
||||
|
@ -581,11 +704,17 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
|
|||
releaseNativeHandles();
|
||||
|
||||
wl_egl_window_destroy(w->egl_window);
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unref(w->decor_frame);
|
||||
#else
|
||||
if (w->xdg_toplevel_decoration) {
|
||||
zxdg_toplevel_decoration_v1_destroy(w->xdg_toplevel_decoration);
|
||||
}
|
||||
xdg_toplevel_destroy(w->xdg_toplevel);
|
||||
xdg_surface_destroy(w->xdg_surface);
|
||||
#endif
|
||||
|
||||
wl_surface_destroy(w->wl_surface);
|
||||
|
||||
/* NOTE(@campbellbarton): This is needed so the appropriate handlers event
|
||||
|
@ -622,23 +751,43 @@ GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state)
|
|||
/* Unset states. */
|
||||
switch (getState()) {
|
||||
case GHOST_kWindowStateMaximized:
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unset_maximized(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_unset_maximized(w->xdg_toplevel);
|
||||
#endif
|
||||
break;
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unset_fullscreen(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateMaximized:
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_maximized(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_set_maximized(w->xdg_toplevel);
|
||||
#endif
|
||||
break;
|
||||
case GHOST_kWindowStateMinimized:
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_minimized(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_set_minimized(w->xdg_toplevel);
|
||||
#endif
|
||||
break;
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
|
||||
#else
|
||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
||||
#endif
|
||||
break;
|
||||
case GHOST_kWindowStateEmbedded:
|
||||
return GHOST_kFailure;
|
||||
|
@ -669,13 +818,21 @@ GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/)
|
|||
|
||||
GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
|
||||
{
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
|
||||
#else
|
||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
||||
#endif
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
|
||||
{
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unset_fullscreen(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
||||
#endif
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue