diff --git a/Makefile.common b/Makefile.common index ae3d10b3e4..72f88223ea 100644 --- a/Makefile.common +++ b/Makefile.common @@ -863,13 +863,15 @@ ifeq ($(TARGET), retroarch_switch) endif ifeq ($(HAVE_WAYLAND), 1) - OBJ += gfx/drivers_context/wayland_ctx.o \ - input/drivers/wayland_input.o - ifeq ($(HAVE_EGL), 1) - LIBS += $(EGL_LIBS) - endif - DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS) - LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS) + OBJ += gfx/drivers_context/wayland_ctx.o \ + input/drivers/wayland_input.o \ + gfx/common/wayland/xdg-shell.o + ifeq ($(HAVE_EGL), 1) + LIBS += $(EGL_LIBS) + endif + DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS) + LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS) + endif #Input diff --git a/gfx/common/wayland/generate_wayland_protos.sh b/gfx/common/wayland/generate_wayland_protos.sh new file mode 100755 index 0000000000..8abc2ed1a0 --- /dev/null +++ b/gfx/common/wayland/generate_wayland_protos.sh @@ -0,0 +1,12 @@ +#!/bin/sh +WAYSCAN=/usr/bin/wayland-scanner +WAYLAND_PROTOS=/usr/share/wayland-protocols +OUTPUT=gfx/common/wayland + +if [ ! -d $OUTPUT ]; then + mkdir $OUTPUT +fi + +#Generate xdg-shell header and .c files +$WAYSCAN client-header $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.h +$WAYSCAN private-code $WAYLAND_PROTOS/stable/xdg-shell/xdg-shell.xml $OUTPUT/xdg-shell.c diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index f22d184849..480cb20c03 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -51,6 +51,9 @@ #include "../../input/input_driver.h" #include "../../input/input_keymaps.h" +// Generated from xdg-shell.xml +#include "../common/wayland/xdg-shell.h" + typedef struct touch_pos { @@ -70,7 +73,10 @@ typedef struct gfx_ctx_wayland_data egl_ctx_data_t egl; struct wl_egl_window *win; #endif + bool fullscreen; + bool maximized; bool resize; + bool configured; unsigned width; unsigned height; unsigned physical_width; @@ -79,8 +85,9 @@ typedef struct gfx_ctx_wayland_data struct wl_registry *registry; struct wl_compositor *compositor; struct wl_surface *surface; - struct wl_shell_surface *shell_surf; - struct wl_shell *shell; + struct xdg_surface *xdg_surface; + struct xdg_wm_base *shell; + struct xdg_toplevel *xdg_toplevel; struct wl_keyboard *wl_keyboard; struct wl_pointer *wl_pointer; struct wl_touch *wl_touch; @@ -303,9 +310,8 @@ static void pointer_handle_button(void *data, { wl->input.mouse.left = true; - /* This behavior matches mpv, seems like a decent way to support window moving for now. */ - if (BIT_GET(wl->input.key_state, KEY_LEFTALT) && wl->shell_surf) - wl_shell_surface_move(wl->shell_surf, wl->seat, serial); + if (BIT_GET(wl->input.key_state, KEY_LEFTALT) && wl->xdg_toplevel) + xdg_toplevel_move(wl->xdg_toplevel, wl->seat, serial); } else if (button == BTN_RIGHT) wl->input.mouse.right = true; @@ -344,6 +350,8 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis, }; +// TODO: implement check for resize + static void touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, @@ -542,41 +550,40 @@ bool wayland_context_gettouchpos(void *data, unsigned id, /* Shell surface callbacks. */ -static void shell_surface_handle_ping(void *data, - struct wl_shell_surface *shell_surface, - uint32_t serial) +static void xdg_shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) { - (void)data; - wl_shell_surface_pong(shell_surface, serial); + xdg_wm_base_pong(shell, serial); } -static void shell_surface_handle_configure(void *data, - struct wl_shell_surface *shell_surface, - uint32_t edges, int32_t width, int32_t height) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; +static const struct xdg_wm_base_listener xdg_shell_listener = { + xdg_shell_ping, +}; - (void)shell_surface; - (void)edges; - - wl->width = wl->buffer_scale * width; - wl->height = wl->buffer_scale * height; - - RARCH_LOG("[Wayland]: Surface configure: %u x %u.\n", - wl->width, wl->height); +static void handle_surface_config(void *data, struct xdg_surface *surface, + uint32_t serial) +{ + xdg_surface_ack_configure(surface, serial); } -static void shell_surface_handle_popup_done(void *data, - struct wl_shell_surface *shell_surface) +static const struct xdg_surface_listener xdg_surface_listener = { + handle_surface_config, +}; + +static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, + int width, int height, struct wl_array *states) { - (void)data; - (void)shell_surface; + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + // TODO: implement resizing + + wl->configured = false; } -static const struct wl_shell_surface_listener shell_surface_listener = { - shell_surface_handle_ping, - shell_surface_handle_configure, - shell_surface_handle_popup_done, +// TODO: implement xdg_toplevel close + + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + handle_toplevel_config, }; static void display_handle_geometry(void *data, @@ -669,9 +676,9 @@ static void registry_handle_global(void *data, struct wl_registry *reg, wl_output_add_listener(output, &output_listener, wl); wl_display_roundtrip(wl->input.dpy); } - else if (string_is_equal(interface, "wl_shell")) - wl->shell = (struct wl_shell*) - wl_registry_bind(reg, id, &wl_shell_interface, 1); + else if (string_is_equal(interface, "xdg_wm_base")) + wl->shell = (struct xdg_wm_base*) + wl_registry_bind(reg, id, &xdg_wm_base_interface, 1); else if (string_is_equal(interface, "wl_shm")) wl->shm = (struct wl_shm*)wl_registry_bind(reg, id, &wl_shm_interface, 1); else if (string_is_equal(interface, "wl_seat")) @@ -752,13 +759,13 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl) if (wl->seat) wl_seat_destroy(wl->seat); if (wl->shell) - wl_shell_destroy(wl->shell); + xdg_wm_base_destroy(wl->shell); if (wl->compositor) wl_compositor_destroy(wl->compositor); if (wl->registry) wl_registry_destroy(wl->registry); - if (wl->shell_surf) - wl_shell_surface_destroy(wl->shell_surf); + if (wl->xdg_surface) + xdg_surface_destroy(wl->xdg_surface); if (wl->surface) wl_surface_destroy(wl->surface); @@ -775,7 +782,7 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl) wl->compositor = NULL; wl->registry = NULL; wl->input.dpy = NULL; - wl->shell_surf = NULL; + wl->xdg_surface = NULL; wl->surface = NULL; wl->width = 0; @@ -902,7 +909,7 @@ static void gfx_ctx_wl_update_title(void *data, void *data2) video_driver_get_window_title(title, sizeof(title)); if (wl && title[0]) - wl_shell_surface_set_title(wl->shell_surf, title); + xdg_toplevel_set_title (wl->xdg_toplevel, title); } @@ -1293,12 +1300,26 @@ static bool gfx_ctx_wl_set_video_mode(void *data, default: break; } - wl->shell_surf = wl_shell_get_shell_surface(wl->shell, wl->surface); + + wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->shell, wl->surface); + xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl); - wl_shell_surface_add_listener(wl->shell_surf, &shell_surface_listener, wl); - wl_shell_surface_set_toplevel(wl->shell_surf); - wl_shell_surface_set_class(wl->shell_surf, "RetroArch"); - wl_shell_surface_set_title(wl->shell_surf, "RetroArch"); + wl->xdg_toplevel = xdg_surface_get_toplevel(wl->xdg_surface); + xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, wl); + + xdg_toplevel_set_app_id (wl->xdg_toplevel, "RetroArch"); + xdg_toplevel_set_title (wl->xdg_toplevel, "RetroArch"); + + // Waiting for xdg_toplevel to be configured before starting to draw + wl_surface_commit(wl->surface); + wl->configured = true; + + while (wl->configured) + wl_display_dispatch(wl->input.dpy); + + // Waiting for the "initial" set of globals to appear + wl_display_roundtrip(wl->input.dpy); + xdg_wm_base_add_listener(wl->shell, &xdg_shell_listener, NULL); switch (wl_api) { @@ -1324,8 +1345,7 @@ static bool gfx_ctx_wl_set_video_mode(void *data, } if (fullscreen) - wl_shell_surface_set_fullscreen(wl->shell_surf, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); + xdg_toplevel_set_fullscreen(wl->xdg_toplevel, NULL); flush_wayland_fd(&wl->input); diff --git a/qb/config.libs.sh b/qb/config.libs.sh index a679058d35..0fd0fe4aa3 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -455,8 +455,9 @@ check_pkgconf V4L2 libv4l2 check_pkgconf FREETYPE freetype2 check_pkgconf X11 x11 check_pkgconf XCB xcb -check_pkgconf WAYLAND wayland-egl -check_pkgconf WAYLAND_CURSOR wayland-cursor +check_pkgconf WAYLAND wayland-egl 1.15 +check_pkgconf WAYLAND_CURSOR wayland-cursor 1.15 +check_pkgconf WAYLAND_PROTOS wayland-protocols 1.15 check_pkgconf XKBCOMMON xkbcommon 0.3.2 check_pkgconf DBUS dbus-1 check_pkgconf XEXT xext @@ -472,6 +473,14 @@ check_val '' XKBCOMMON -lxkbcommon check_val '' XEXT -lXext check_val '' XF86VM -lXxf86vm +if [ "$HAVE_WAYLAND_PROTOS" = yes ] && [ "$HAVE_WAYLAND" = yes ]; then + check_pkgconf WAYLAND_SCANNER wayland-scanner 1.15 + ./gfx/common/wayland/generate_wayland_protos.sh +else + die : 'Notice: wayland-egl or wayland-protocols not present. Skiping Wayland code paths.' + HAVE_WAYLAND='no' +fi + if [ "$HAVE_X11" = 'no' ]; then HAVE_XEXT=no; HAVE_XF86VM=no; HAVE_XINERAMA=no; HAVE_XSHM=no fi