aboutsummaryrefslogtreecommitdiff
path: root/cube/cube.cpp
diff options
context:
space:
mode:
authorManuel Stoeckl <code@mstoeckl.com>2019-06-26 20:55:53 -0400
committerTony Barbour <tony@lunarg.com>2021-06-14 09:43:18 -0600
commitac9393317a5cf7b077ff7d40e65c7ab9bc53ce90 (patch)
tree6f4638a8d42a62f9857f3a15442d986cae35c0b3 /cube/cube.cpp
parent53231a96c0a69f03fd8a4d8770662df570ef9504 (diff)
downloadusermoji-ac9393317a5cf7b077ff7d40e65c7ab9bc53ce90.tar.xz
cube: Port Wayland impl from wl-shell to xdg-shell
This change ports vkcube in both C and C++ versions to use the stable xdg-shell protocol for Wayland compositors. The original wl-shell protocol has been deprecated and is being removed from major compositor libraries; wlroots has already dropped support. New cmake modules have been added to look for Wayland-Protocols (containing XML descriptions of all common protocols) and `wayland-scanner`, the tool used to convert the XML files to a usable C interface. The change also adds support for the xdg-decoration protocol, which for some compositors is provided and needed to let them know that they should draw a titlebar, borders with resize controls, and other standard features. Change-Id: I39bedda93a7c5d0aeeb59c68023552723b413567
Diffstat (limited to 'cube/cube.cpp')
-rw-r--r--cube/cube.cpp107
1 files changed, 90 insertions, 17 deletions
diff --git a/cube/cube.cpp b/cube/cube.cpp
index e5b2782b..9ff103c5 100644
--- a/cube/cube.cpp
+++ b/cube/cube.cpp
@@ -22,6 +22,8 @@
#include <X11/Xutil.h>
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
#include <linux/input.h>
+#include "xdg-shell-client-header.h"
+#include "xdg-decoration-client-header.h"
#endif
#include <cassert>
@@ -286,8 +288,12 @@ struct Demo {
wl_registry *registry;
wl_compositor *compositor;
wl_surface *window;
- wl_shell *shell;
- wl_shell_surface *shell_surface;
+ xdg_wm_base *wm_base;
+ zxdg_decoration_manager_v1 *xdg_decoration_mgr;
+ zxdg_toplevel_decoration_v1 *toplevel_decoration;
+ xdg_surface *window_surface;
+ bool xdg_surface_has_been_configured;
+ xdg_toplevel *window_toplevel;
wl_seat *seat;
wl_pointer *pointer;
wl_keyboard *keyboard;
@@ -420,7 +426,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uin
uint32_t state) {
Demo *demo = (Demo *)data;
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) {
- wl_shell_surface_move(demo->shell_surface, demo->seat, serial);
+ xdg_toplevel_move(demo->window_toplevel, demo->seat, serial);
}
}
@@ -488,16 +494,24 @@ static const wl_seat_listener seat_listener = {
seat_handle_capabilities,
};
+static void wm_base_ping(void *data, xdg_wm_base *xdg_wm_base, uint32_t serial) { xdg_wm_base_pong(xdg_wm_base, serial); }
+
+static const struct xdg_wm_base_listener wm_base_listener = {wm_base_ping};
+
static void registry_handle_global(void *data, wl_registry *registry, uint32_t id, const char *interface, uint32_t version) {
Demo *demo = (Demo *)data;
// pickup wayland objects when they appear
- if (strcmp(interface, "wl_compositor") == 0) {
+ if (strcmp(interface, wl_compositor_interface.name) == 0) {
demo->compositor = (wl_compositor *)wl_registry_bind(registry, id, &wl_compositor_interface, 1);
- } else if (strcmp(interface, "wl_shell") == 0) {
- demo->shell = (wl_shell *)wl_registry_bind(registry, id, &wl_shell_interface, 1);
- } else if (strcmp(interface, "wl_seat") == 0) {
+ } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
+ demo->wm_base = (xdg_wm_base *)wl_registry_bind(registry, id, &xdg_wm_base_interface, 1);
+ xdg_wm_base_add_listener(demo->wm_base, &wm_base_listener, nullptr);
+ } else if (strcmp(interface, wl_seat_interface.name) == 0) {
demo->seat = (wl_seat *)wl_registry_bind(registry, id, &wl_seat_interface, 1);
wl_seat_add_listener(demo->seat, &seat_listener, demo);
+ } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
+ demo->xdg_decoration_mgr =
+ (zxdg_decoration_manager_v1 *)wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
}
}
@@ -527,8 +541,12 @@ Demo::Demo()
registry{nullptr},
compositor{nullptr},
window{nullptr},
- shell{nullptr},
- shell_surface{nullptr},
+ wm_base{nullptr},
+ xdg_decoration_mgr{nullptr},
+ toplevel_decoration{nullptr},
+ window_surface{nullptr},
+ xdg_surface_has_been_configured{false},
+ window_toplevel{nullptr},
seat{nullptr},
pointer{nullptr},
keyboard{nullptr},
@@ -676,9 +694,14 @@ void Demo::cleanup() {
wl_keyboard_destroy(keyboard);
wl_pointer_destroy(pointer);
wl_seat_destroy(seat);
- wl_shell_surface_destroy(shell_surface);
+ xdg_toplevel_destroy(window_toplevel);
+ xdg_surface_destroy(window_surface);
wl_surface_destroy(window);
- wl_shell_destroy(shell);
+ xdg_wm_base_destroy(wm_base);
+ if (xdg_decoration_mgr) {
+ zxdg_toplevel_decoration_v1_destroy(toplevel_decoration);
+ zxdg_decoration_manager_v1_destroy(xdg_decoration_mgr);
+ }
wl_compositor_destroy(compositor);
wl_registry_destroy(registry);
wl_display_disconnect(display);
@@ -2808,7 +2831,45 @@ void Demo::run() {
}
}
+static void handle_surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial) {
+ Demo *demo = (Demo *)data;
+ xdg_surface_ack_configure(xdg_surface, serial);
+ if (demo->xdg_surface_has_been_configured) {
+ demo->resize();
+ }
+ demo->xdg_surface_has_been_configured = true;
+}
+
+static const xdg_surface_listener surface_listener = {handle_surface_configure};
+
+static void handle_toplevel_configure(void *data, xdg_toplevel *xdg_toplevel, int32_t width, int32_t height,
+ struct wl_array *states) {
+ Demo *demo = (Demo *)data;
+ /* zero values imply the program may choose its own size, so in that case
+ * stay with the existing value (which on startup is the default) */
+ if (width > 0) {
+ demo->width = width;
+ }
+ if (height > 0) {
+ demo->height = height;
+ }
+ // This will be followed by a surface configure
+}
+
+static void handle_toplevel_close(void *data, xdg_toplevel *xdg_toplevel) {
+ Demo *demo = (Demo *)data;
+ demo->quit = true;
+}
+
+static const xdg_toplevel_listener toplevel_listener = {handle_toplevel_configure, handle_toplevel_close};
+
void Demo::create_window() {
+ if (!wm_base) {
+ printf("Compositor did not provide the standard protocol xdg-wm-base\n");
+ fflush(stdout);
+ exit(1);
+ }
+
window = wl_compositor_create_surface(compositor);
if (!window) {
printf("Can not create wayland_surface from compositor!\n");
@@ -2816,16 +2877,28 @@ void Demo::create_window() {
exit(1);
}
- shell_surface = wl_shell_get_shell_surface(shell, window);
- if (!shell_surface) {
- printf("Can not get shell_surface from wayland_surface!\n");
+ window_surface = xdg_wm_base_get_xdg_surface(wm_base, window);
+ if (!window_surface) {
+ printf("Can not get xdg_surface from wayland_surface!\n");
+ fflush(stdout);
+ exit(1);
+ }
+ window_toplevel = xdg_surface_get_toplevel(window_surface);
+ if (!window_toplevel) {
+ printf("Can not allocate xdg_toplevel for xdg_surface!\n");
fflush(stdout);
exit(1);
}
+ xdg_surface_add_listener(window_surface, &surface_listener, this);
+ xdg_toplevel_add_listener(window_toplevel, &toplevel_listener, this);
+ xdg_toplevel_set_title(window_toplevel, APP_SHORT_NAME);
+ if (xdg_decoration_mgr) {
+ // if supported, let the compositor render titlebars for us
+ toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(xdg_decoration_mgr, window_toplevel);
+ zxdg_toplevel_decoration_v1_set_mode(toplevel_decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+ }
- wl_shell_surface_add_listener(shell_surface, &shell_surface_listener, this);
- wl_shell_surface_set_toplevel(shell_surface);
- wl_shell_surface_set_title(shell_surface, APP_SHORT_NAME);
+ wl_surface_commit(window);
}
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)