diff --git a/client/displayservers/Wayland/CMakeLists.txt b/client/displayservers/Wayland/CMakeLists.txt index a4b496c6..52e7f1fe 100644 --- a/client/displayservers/Wayland/CMakeLists.txt +++ b/client/displayservers/Wayland/CMakeLists.txt @@ -19,6 +19,7 @@ add_library(displayserver_Wayland STATIC poll.c state.c registry.c + shell_xdg.c wayland.c window.c ) diff --git a/client/displayservers/Wayland/gl.c b/client/displayservers/Wayland/gl.c index 2da30a39..fb8a3221 100644 --- a/client/displayservers/Wayland/gl.c +++ b/client/displayservers/Wayland/gl.c @@ -85,11 +85,7 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface) wlWm.needsResize = false; } - if (wlWm.resizeSerial) - { - xdg_surface_ack_configure(wlWm.xdgSurface, wlWm.resizeSerial); - wlWm.resizeSerial = 0; - } + waylandShellAckConfigureIfNeeded(); } #endif diff --git a/client/displayservers/Wayland/shell_xdg.c b/client/displayservers/Wayland/shell_xdg.c new file mode 100644 index 00000000..38bec4c3 --- /dev/null +++ b/client/displayservers/Wayland/shell_xdg.c @@ -0,0 +1,148 @@ +/* +Looking Glass - KVM FrameRelay (KVMFR) Client +Copyright (C) 2021 Guanzhong Chen (quantum2048@gmail.com) +Copyright (C) 2021 Tudor Brindus (contact@tbrindus.ca) +https://looking-glass.io + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "wayland.h" + +#include +#include + +#include "app.h" +#include "common/debug.h" + +// XDG WM base listeners. + +static void xdgWmBasePing(void * data, struct xdg_wm_base * xdgWmBase, uint32_t serial) +{ + xdg_wm_base_pong(xdgWmBase, serial); +} + +static const struct xdg_wm_base_listener xdgWmBaseListener = { + .ping = xdgWmBasePing, +}; + +// XDG Surface listeners. + +static void xdgSurfaceConfigure(void * data, struct xdg_surface * xdgSurface, + uint32_t serial) +{ + if (wlWm.configured) + { + wlWm.needsResize = true; + wlWm.resizeSerial = serial; + } + else + { + xdg_surface_ack_configure(xdgSurface, serial); + wlWm.configured = true; + } +} + +static const struct xdg_surface_listener xdgSurfaceListener = { + .configure = xdgSurfaceConfigure, +}; + +// XDG Toplevel listeners. + +static void xdgToplevelConfigure(void * data, struct xdg_toplevel * xdgToplevel, + int32_t width, int32_t height, struct wl_array * states) +{ + wlWm.width = width; + wlWm.height = height; + wlWm.fullscreen = false; + + enum xdg_toplevel_state * state; + wl_array_for_each(state, states) + { + if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) + wlWm.fullscreen = true; + } +} + +static void xdgToplevelClose(void * data, struct xdg_toplevel * xdgToplevel) +{ + app_handleCloseEvent(); +} + +static const struct xdg_toplevel_listener xdgToplevelListener = { + .configure = xdgToplevelConfigure, + .close = xdgToplevelClose, +}; + +bool waylandShellInit(const char * title, bool fullscreen, bool maximize, bool borderless) +{ + if (!wlWm.xdgWmBase) + { + DEBUG_ERROR("Compositor missing xdg_wm_base, will not proceed"); + return false; + } + + xdg_wm_base_add_listener(wlWm.xdgWmBase, &xdgWmBaseListener, NULL); + + wlWm.xdgSurface = xdg_wm_base_get_xdg_surface(wlWm.xdgWmBase, wlWm.surface); + xdg_surface_add_listener(wlWm.xdgSurface, &xdgSurfaceListener, NULL); + + wlWm.xdgToplevel = xdg_surface_get_toplevel(wlWm.xdgSurface); + xdg_toplevel_add_listener(wlWm.xdgToplevel, &xdgToplevelListener, NULL); + xdg_toplevel_set_title(wlWm.xdgToplevel, title); + xdg_toplevel_set_app_id(wlWm.xdgToplevel, "looking-glass-client"); + + if (fullscreen) + xdg_toplevel_set_fullscreen(wlWm.xdgToplevel, NULL); + + if (maximize) + xdg_toplevel_set_maximized(wlWm.xdgToplevel); + + if (wlWm.xdgDecorationManager) + { + wlWm.xdgToplevelDecoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + wlWm.xdgDecorationManager, wlWm.xdgToplevel); + if (wlWm.xdgToplevelDecoration) + { + zxdg_toplevel_decoration_v1_set_mode(wlWm.xdgToplevelDecoration, + borderless ? + ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE : + ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } + } + + return true; +} + +void waylandShellAckConfigureIfNeeded(void) +{ + if (wlWm.resizeSerial) + { + xdg_surface_ack_configure(wlWm.xdgSurface, wlWm.resizeSerial); + wlWm.resizeSerial = 0; + } +} + +void waylandSetFullscreen(bool fs) +{ + if (fs) + xdg_toplevel_set_fullscreen(wlWm.xdgToplevel, NULL); + else + xdg_toplevel_unset_fullscreen(wlWm.xdgToplevel); +} + +bool waylandGetFullscreen(void) +{ + return wlWm.fullscreen; +} diff --git a/client/displayservers/Wayland/wayland.h b/client/displayservers/Wayland/wayland.h index becf4333..baa43150 100644 --- a/client/displayservers/Wayland/wayland.h +++ b/client/displayservers/Wayland/wayland.h @@ -236,11 +236,15 @@ bool waylandPollUnregister(int fd); bool waylandRegistryInit(void); void waylandRegistryFree(void); +// shell module +bool waylandShellInit(const char * title, bool fullscreen, bool maximize, bool borderless); +void waylandShellAckConfigureIfNeeded(void); +void waylandSetFullscreen(bool fs); +bool waylandGetFullscreen(void); + // window module bool waylandWindowInit(const char * title, bool fullscreen, bool maximize, bool borderless); void waylandWindowFree(void); void waylandWindowUpdateScale(void); void waylandSetWindowSize(int x, int y); -void waylandSetFullscreen(bool fs); -bool waylandGetFullscreen(void); bool waylandIsValidPointerPos(int x, int y); diff --git a/client/displayservers/Wayland/window.c b/client/displayservers/Wayland/window.c index 1198a154..aa1196f1 100644 --- a/client/displayservers/Wayland/window.c +++ b/client/displayservers/Wayland/window.c @@ -28,17 +28,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "app.h" #include "common/debug.h" -// XDG WM base listeners. - -static void xdgWmBasePing(void * data, struct xdg_wm_base * xdgWmBase, uint32_t serial) -{ - xdg_wm_base_pong(xdgWmBase, serial); -} - -static const struct xdg_wm_base_listener xdgWmBaseListener = { - .ping = xdgWmBasePing, -}; - // Surface-handling listeners. void waylandWindowUpdateScale(void) @@ -85,54 +74,6 @@ static const struct wl_surface_listener wlSurfaceListener = { .leave = wlSurfaceLeaveHandler, }; -// XDG Surface listeners. - -static void xdgSurfaceConfigure(void * data, struct xdg_surface * xdgSurface, - uint32_t serial) -{ - if (wlWm.configured) - { - wlWm.needsResize = true; - wlWm.resizeSerial = serial; - } - else - { - xdg_surface_ack_configure(xdgSurface, serial); - wlWm.configured = true; - } -} - -static const struct xdg_surface_listener xdgSurfaceListener = { - .configure = xdgSurfaceConfigure, -}; - -// XDG Toplevel listeners. - -static void xdgToplevelConfigure(void * data, struct xdg_toplevel * xdgToplevel, - int32_t width, int32_t height, struct wl_array * states) -{ - wlWm.width = width; - wlWm.height = height; - wlWm.fullscreen = false; - - enum xdg_toplevel_state * state; - wl_array_for_each(state, states) - { - if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) - wlWm.fullscreen = true; - } -} - -static void xdgToplevelClose(void * data, struct xdg_toplevel * xdgToplevel) -{ - app_handleCloseEvent(); -} - -static const struct xdg_toplevel_listener xdgToplevelListener = { - .configure = xdgToplevelConfigure, - .close = xdgToplevelClose, -}; - bool waylandWindowInit(const char * title, bool fullscreen, bool maximize, bool borderless) { wlWm.scale = 1; @@ -143,14 +84,6 @@ bool waylandWindowInit(const char * title, bool fullscreen, bool maximize, bool return false; } - if (!wlWm.xdgWmBase) - { - DEBUG_ERROR("Compositor missing xdg_wm_base, will not proceed"); - return false; - } - - xdg_wm_base_add_listener(wlWm.xdgWmBase, &xdgWmBaseListener, NULL); - wlWm.surface = wl_compositor_create_surface(wlWm.compositor); if (!wlWm.surface) { @@ -160,35 +93,10 @@ bool waylandWindowInit(const char * title, bool fullscreen, bool maximize, bool wl_surface_add_listener(wlWm.surface, &wlSurfaceListener, NULL); - wlWm.xdgSurface = xdg_wm_base_get_xdg_surface(wlWm.xdgWmBase, wlWm.surface); - xdg_surface_add_listener(wlWm.xdgSurface, &xdgSurfaceListener, NULL); - - wlWm.xdgToplevel = xdg_surface_get_toplevel(wlWm.xdgSurface); - xdg_toplevel_add_listener(wlWm.xdgToplevel, &xdgToplevelListener, NULL); - xdg_toplevel_set_title(wlWm.xdgToplevel, title); - xdg_toplevel_set_app_id(wlWm.xdgToplevel, "looking-glass-client"); - - if (fullscreen) - xdg_toplevel_set_fullscreen(wlWm.xdgToplevel, NULL); - - if (maximize) - xdg_toplevel_set_maximized(wlWm.xdgToplevel); + if (!waylandShellInit(title, fullscreen, maximize, borderless)) + return false; wl_surface_commit(wlWm.surface); - - if (wlWm.xdgDecorationManager) - { - wlWm.xdgToplevelDecoration = zxdg_decoration_manager_v1_get_toplevel_decoration( - wlWm.xdgDecorationManager, wlWm.xdgToplevel); - if (wlWm.xdgToplevelDecoration) - { - zxdg_toplevel_decoration_v1_set_mode(wlWm.xdgToplevelDecoration, - borderless ? - ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE : - ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); - } - } - return true; } @@ -202,19 +110,6 @@ void waylandSetWindowSize(int x, int y) // FIXME: implement. } -void waylandSetFullscreen(bool fs) -{ - if (fs) - xdg_toplevel_set_fullscreen(wlWm.xdgToplevel, NULL); - else - xdg_toplevel_unset_fullscreen(wlWm.xdgToplevel); -} - -bool waylandGetFullscreen(void) -{ - return wlWm.fullscreen; -} - bool waylandIsValidPointerPos(int x, int y) { return x >= 0 && x < wlWm.width && y >= 0 && y < wlWm.height;