From c32c98e667e352bd8f44dcab496050339d4af043 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Sat, 17 Nov 2018 16:01:51 +0400 Subject: [PATCH 1/9] Very WIP: xdg-shell support --- Makefile.common | 10 ++ gfx/common/wayland/generate_wayland_protos.sh | 12 ++ gfx/drivers_context/wayland_ctx.c | 156 +++++++++--------- qb/config.libs.sh | 13 +- 4 files changed, 114 insertions(+), 77 deletions(-) create mode 100755 gfx/common/wayland/generate_wayland_protos.sh diff --git a/Makefile.common b/Makefile.common index 0ec1079549..4bbb694a77 100644 --- a/Makefile.common +++ b/Makefile.common @@ -858,6 +858,15 @@ ifeq ($(TARGET), retroarch_switch) endif ifeq ($(HAVE_WAYLAND), 1) + 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) + OBJ += gfx/drivers_context/wayland_ctx.o \ input/drivers/wayland_input.o ifeq ($(HAVE_EGL), 1) @@ -865,6 +874,7 @@ ifeq ($(HAVE_WAYLAND), 1) 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..84bfcf47db 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -51,6 +51,8 @@ #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 { @@ -71,6 +73,8 @@ typedef struct gfx_ctx_wayland_data struct wl_egl_window *win; #endif bool resize; + bool fullscreen; + bool maximized; unsigned width; unsigned height; unsigned physical_width; @@ -79,8 +83,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; @@ -242,7 +247,7 @@ static const struct wl_keyboard_listener keyboard_listener = { keyboard_handle_repeat_info }; -static void gfx_ctx_wl_show_mouse(void *data, bool state); +static int gfx_ctx_wl_show_mouse(void *data, bool state); static void pointer_handle_enter(void *data, struct wl_pointer *pointer, @@ -303,9 +308,6 @@ 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); } else if (button == BTN_RIGHT) wl->input.mouse.right = true; @@ -344,6 +346,8 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis, }; +// Check for resize + static void touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, @@ -542,41 +546,57 @@ 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 const struct xdg_wm_base_listener xdg_shell_listener = { + xdg_shell_ping, +}; + +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_configure(void *data, - struct wl_shell_surface *shell_surface, - uint32_t edges, int32_t width, int32_t height) +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) { - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - (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); + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + int prev_fs_state = wl->fullscreen; + wl->maximized = false; + wl->fullscreen = false; + enum xdg_toplevel_state *state; + wl_array_for_each(state, states) { + switch (*state) { + case XDG_TOPLEVEL_STATE_FULLSCREEN: + wl->fullscreen = true; + break; + case XDG_TOPLEVEL_STATE_RESIZING: + wl->resize = true; + break; + case XDG_TOPLEVEL_STATE_ACTIVATED: + break; + case XDG_TOPLEVEL_STATE_TILED_TOP: + case XDG_TOPLEVEL_STATE_TILED_LEFT: + case XDG_TOPLEVEL_STATE_TILED_RIGHT: + case XDG_TOPLEVEL_STATE_TILED_BOTTOM: + case XDG_TOPLEVEL_STATE_MAXIMIZED: + wl->maximized = true; + break; + } + } } -static void shell_surface_handle_popup_done(void *data, - struct wl_shell_surface *shell_surface) -{ - (void)data; - (void)shell_surface; -} +//TODO: Setup resize here -static const struct wl_shell_surface_listener shell_surface_listener = { - shell_surface_handle_ping, - shell_surface_handle_configure, - shell_surface_handle_popup_done, +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + handle_toplevel_config, }; static void display_handle_geometry(void *data, @@ -666,12 +686,11 @@ static void registry_handle_global(void *data, struct wl_registry *reg, { output = (struct wl_output*)wl_registry_bind(reg, id, &wl_output_interface, 2); - 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 +771,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 +794,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; @@ -892,18 +911,18 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height) return true; } -static void gfx_ctx_wl_update_title(void *data, void *data2) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - char title[128]; +//static void gfx_ctx_wl_update_title(void *data, void *data2) +//{ +// gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; +// char title[128]; - title[0] = '\0'; +// title[0] = '\0'; - video_driver_get_window_title(title, sizeof(title)); +// video_driver_get_window_title(title, sizeof(title)); - if (wl && title[0]) - wl_shell_surface_set_title(wl->shell_surf, title); -} +// if (wl && title[0]) +// xdg_surface_set_title(wl->xdg_surface, title); +//} static bool gfx_ctx_wl_get_metrics(void *data, @@ -1064,7 +1083,7 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) if (!wl->shell) { - RARCH_ERR("[Wayland]: Failed to create shell.\n"); + RARCH_ERR("[Wayland]: Compositor doesn't support xdg-shell interface.\n"); goto error; } @@ -1293,12 +1312,15 @@ 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->xdg_toplevel = xdg_surface_get_toplevel(wl->xdg_surface); + xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, wl); + + xdg_toplevel_set_title (wl->xdg_toplevel, "RetroArch"); + xdg_toplevel_set_app_id (wl->xdg_toplevel, "RetroArch"); - 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"); switch (wl_api) { @@ -1323,12 +1345,6 @@ static bool gfx_ctx_wl_set_video_mode(void *data, break; } - if (fullscreen) - wl_shell_surface_set_fullscreen(wl->shell_surf, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); - - flush_wayland_fd(&wl->input); - switch (wl_api) { case GFX_CTX_VULKAN_API: @@ -1400,12 +1416,6 @@ static bool gfx_ctx_wl_suppress_screensaver(void *data, bool enable) return true; } -static bool gfx_ctx_wl_has_windowed(void *data) -{ - (void)data; - return true; -} - static enum gfx_ctx_api gfx_ctx_wl_get_api(void *data) { return wl_api; @@ -1557,11 +1567,11 @@ static void gfx_ctx_wl_set_flags(void *data, uint32_t flags) wl->core_hw_context_enable = true; } -static void gfx_ctx_wl_show_mouse(void *data, bool state) +static int gfx_ctx_wl_show_mouse(void *data, bool state) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; if (!wl->wl_pointer) - return; + return 1; if (state) { @@ -1591,19 +1601,15 @@ const gfx_ctx_driver_t gfx_ctx_wayland = { gfx_ctx_wl_bind_api, gfx_ctx_wl_set_swap_interval, gfx_ctx_wl_set_video_mode, - gfx_ctx_wl_get_video_size, gfx_ctx_wl_get_refresh_rate, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ NULL, /* get_video_output_next */ gfx_ctx_wl_get_metrics, NULL, - gfx_ctx_wl_update_title, gfx_ctx_wl_check_window, - gfx_ctx_wl_set_resize, gfx_ctx_wl_has_focus, gfx_ctx_wl_suppress_screensaver, - gfx_ctx_wl_has_windowed, gfx_ctx_wl_swap_buffers, gfx_ctx_wl_input_driver, gfx_ctx_wl_get_proc_address, 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 From c0adb18eff4c5d02fd66779a1d51e69e325bc862 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Sun, 18 Nov 2018 21:29:31 +0400 Subject: [PATCH 2/9] Fix build --- Makefile.common | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Makefile.common b/Makefile.common index 4bbb694a77..0554d01f7f 100644 --- a/Makefile.common +++ b/Makefile.common @@ -867,14 +867,6 @@ ifeq ($(HAVE_WAYLAND), 1) DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS) LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS) - 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) - endif #Input From 4d8defb4c98b815d5e95435d56d4963a6859ed7f Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Sun, 18 Nov 2018 21:50:39 +0400 Subject: [PATCH 3/9] Remove D-bus based screensaver inhibition (will replaced to idle-inhibit in future) --- gfx/drivers_context/wayland_ctx.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 84bfcf47db..5045f77cd0 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -42,10 +42,6 @@ #include "../common/gl_common.h" #endif -#ifdef HAVE_DBUS -#include "../common/dbus_common.h" -#endif - #include "../common/wayland_common.h" #include "../../frontend/frontend_driver.h" #include "../../input/input_driver.h" @@ -799,11 +795,6 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl) wl->width = 0; wl->height = 0; - -#ifdef HAVE_DBUS - dbus_screensaver_uninhibit(); - dbus_close_connection(); -#endif } void flush_wayland_fd(void *data) @@ -1138,10 +1129,6 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) flush_wayland_fd(&wl->input); -#ifdef HAVE_DBUS - dbus_ensure_connection(); -#endif - return wl; error: @@ -1404,18 +1391,6 @@ static bool gfx_ctx_wl_has_focus(void *data) return wl->input.keyboard_focus; } -static bool gfx_ctx_wl_suppress_screensaver(void *data, bool enable) -{ - (void)data; - (void)enable; - -#ifdef HAVE_DBUS - return dbus_suspend_screensaver(enable); -#endif - - return true; -} - static enum gfx_ctx_api gfx_ctx_wl_get_api(void *data) { return wl_api; @@ -1609,7 +1584,6 @@ const gfx_ctx_driver_t gfx_ctx_wayland = { NULL, gfx_ctx_wl_check_window, gfx_ctx_wl_has_focus, - gfx_ctx_wl_suppress_screensaver, gfx_ctx_wl_swap_buffers, gfx_ctx_wl_input_driver, gfx_ctx_wl_get_proc_address, From b64f302eb7c53f730543b5321033e212d31c32d1 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Mon, 19 Nov 2018 22:31:17 +0400 Subject: [PATCH 4/9] Check for resize --- gfx/drivers_context/wayland_ctx.c | 60 +++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 5045f77cd0..4171d05088 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -68,14 +68,15 @@ typedef struct gfx_ctx_wayland_data egl_ctx_data_t egl; struct wl_egl_window *win; #endif - bool resize; bool fullscreen; bool maximized; + bool resize; unsigned width; unsigned height; unsigned physical_width; unsigned physical_height; int refresh_rate; + int touch_entries; struct wl_registry *registry; struct wl_compositor *compositor; struct wl_surface *surface; @@ -342,7 +343,42 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis, }; -// Check for resize +static int check_for_resize(void *data, wl_fixed_t x_w, wl_fixed_t y_w, + enum xdg_toplevel_resize_edge *edge) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + if (wl->touch_entries || wl->fullscreen || wl->maximized) + return 0; + + const int edge_pixels = 64; + int pos[2] = { wl_fixed_to_double(x_w), wl_fixed_to_double(y_w) }; + int left_edge = pos[0] < edge_pixels; + int top_edge = pos[1] < edge_pixels; + int right_edge = pos[0] > edge_pixels; + int bottom_edge = pos[1] > edge_pixels; + + if (left_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + if (top_edge) + *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + } else if (right_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + if (top_edge) + *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + else if (bottom_edge) + *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + } else if (top_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP; + } else if (bottom_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + } else { + *edge = 0; + return 0; + } + + return 1; +} static void touch_handle_down(void *data, struct wl_touch *wl_touch, @@ -902,18 +938,18 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height) return true; } -//static void gfx_ctx_wl_update_title(void *data, void *data2) -//{ -// gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; -// char title[128]; +static void gfx_ctx_wl_update_title(void *data, void *data2) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + char title[128]; -// title[0] = '\0'; + title[0] = '\0'; -// video_driver_get_window_title(title, sizeof(title)); + video_driver_get_window_title(title, sizeof(title)); -// if (wl && title[0]) -// xdg_surface_set_title(wl->xdg_surface, title); -//} + if (wl && title[0]) + xdg_toplevel_set_title (wl->xdg_toplevel, title); +} static bool gfx_ctx_wl_get_metrics(void *data, @@ -1582,7 +1618,9 @@ const gfx_ctx_driver_t gfx_ctx_wayland = { NULL, /* get_video_output_next */ gfx_ctx_wl_get_metrics, NULL, + gfx_ctx_wl_update_title, gfx_ctx_wl_check_window, + gfx_ctx_wl_set_resize, gfx_ctx_wl_has_focus, gfx_ctx_wl_swap_buffers, gfx_ctx_wl_input_driver, From 2615ad3f5538f2f19c2b83f782030746ed042fd1 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Wed, 21 Nov 2018 21:28:32 +0400 Subject: [PATCH 5/9] Make it works! --- gfx/drivers_context/wayland_ctx.c | 124 +++++++++++++++++++----------- 1 file changed, 78 insertions(+), 46 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 4171d05088..2e6937f976 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -42,6 +42,10 @@ #include "../common/gl_common.h" #endif +#ifdef HAVE_DBUS +#include "../common/dbus_common.h" +#endif + #include "../common/wayland_common.h" #include "../../frontend/frontend_driver.h" #include "../../input/input_driver.h" @@ -50,6 +54,7 @@ // Generated from xdg-shell.xml #include "../common/wayland/xdg-shell.h" + typedef struct touch_pos { bool active; @@ -76,7 +81,6 @@ typedef struct gfx_ctx_wayland_data unsigned physical_width; unsigned physical_height; int refresh_rate; - int touch_entries; struct wl_registry *registry; struct wl_compositor *compositor; struct wl_surface *surface; @@ -244,7 +248,7 @@ static const struct wl_keyboard_listener keyboard_listener = { keyboard_handle_repeat_info }; -static int gfx_ctx_wl_show_mouse(void *data, bool state); +static void gfx_ctx_wl_show_mouse(void *data, bool state); static void pointer_handle_enter(void *data, struct wl_pointer *pointer, @@ -305,6 +309,8 @@ static void pointer_handle_button(void *data, { wl->input.mouse.left = true; + 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; @@ -343,43 +349,6 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis, }; -static int check_for_resize(void *data, wl_fixed_t x_w, wl_fixed_t y_w, - enum xdg_toplevel_resize_edge *edge) -{ - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - if (wl->touch_entries || wl->fullscreen || wl->maximized) - return 0; - - const int edge_pixels = 64; - int pos[2] = { wl_fixed_to_double(x_w), wl_fixed_to_double(y_w) }; - int left_edge = pos[0] < edge_pixels; - int top_edge = pos[1] < edge_pixels; - int right_edge = pos[0] > edge_pixels; - int bottom_edge = pos[1] > edge_pixels; - - if (left_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; - if (top_edge) - *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; - } else if (right_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; - if (top_edge) - *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; - else if (bottom_edge) - *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; - } else if (top_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP; - } else if (bottom_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; - } else { - *edge = 0; - return 0; - } - - return 1; -} - static void touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, @@ -625,12 +594,39 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, } } -//TODO: Setup resize here - static const struct xdg_toplevel_listener xdg_toplevel_listener = { handle_toplevel_config, }; +//static void shell_surface_handle_configure(void *data, + //struct xdg_surface *xdg_surface, + //uint32_t edges, int32_t width, int32_t height) +//{ + //gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + //(void)xdg_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 shell_surface_handle_popup_done(void *data, + //struct wl_shell_surface *shell_surface) +//{ + //(void)data; + //(void)shell_surface; +//} + +//static const struct wl_shell_surface_listener shell_surface_listener = { + //shell_surface_handle_ping, + //shell_surface_handle_configure, + //shell_surface_handle_popup_done, +//}; + static void display_handle_geometry(void *data, struct wl_output *output, int x, int y, @@ -718,6 +714,7 @@ static void registry_handle_global(void *data, struct wl_registry *reg, { output = (struct wl_output*)wl_registry_bind(reg, id, &wl_output_interface, 2); + wl_output_add_listener(output, &output_listener, wl); wl_display_roundtrip(wl->input.dpy); } else if (string_is_equal(interface, "xdg_wm_base")) @@ -831,6 +828,11 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl) wl->width = 0; wl->height = 0; + +#ifdef HAVE_DBUS + dbus_screensaver_uninhibit(); + dbus_close_connection(); +#endif } void flush_wayland_fd(void *data) @@ -1110,7 +1112,7 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) if (!wl->shell) { - RARCH_ERR("[Wayland]: Compositor doesn't support xdg-shell interface.\n"); + RARCH_ERR("[Wayland]: Failed to create shell.\n"); goto error; } @@ -1165,6 +1167,10 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) flush_wayland_fd(&wl->input); +#ifdef HAVE_DBUS + dbus_ensure_connection(); +#endif + return wl; error: @@ -1341,9 +1347,8 @@ static bool gfx_ctx_wl_set_video_mode(void *data, wl->xdg_toplevel = xdg_surface_get_toplevel(wl->xdg_surface); xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, wl); - xdg_toplevel_set_title (wl->xdg_toplevel, "RetroArch"); xdg_toplevel_set_app_id (wl->xdg_toplevel, "RetroArch"); - + xdg_toplevel_set_title (wl->xdg_toplevel, "RetroArch"); switch (wl_api) { @@ -1368,6 +1373,12 @@ static bool gfx_ctx_wl_set_video_mode(void *data, break; } + //if (fullscreen) + //wl_shell_surface_set_fullscreen(wl->shell_surf, + //WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); + + //flush_wayland_fd(&wl->input); + switch (wl_api) { case GFX_CTX_VULKAN_API: @@ -1427,6 +1438,24 @@ static bool gfx_ctx_wl_has_focus(void *data) return wl->input.keyboard_focus; } +static bool gfx_ctx_wl_suppress_screensaver(void *data, bool enable) +{ + (void)data; + (void)enable; + +#ifdef HAVE_DBUS + return dbus_suspend_screensaver(enable); +#endif + + return true; +} + +static bool gfx_ctx_wl_has_windowed(void *data) +{ + (void)data; + return true; +} + static enum gfx_ctx_api gfx_ctx_wl_get_api(void *data) { return wl_api; @@ -1578,11 +1607,11 @@ static void gfx_ctx_wl_set_flags(void *data, uint32_t flags) wl->core_hw_context_enable = true; } -static int gfx_ctx_wl_show_mouse(void *data, bool state) +static void gfx_ctx_wl_show_mouse(void *data, bool state) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; if (!wl->wl_pointer) - return 1; + return; if (state) { @@ -1612,6 +1641,7 @@ const gfx_ctx_driver_t gfx_ctx_wayland = { gfx_ctx_wl_bind_api, gfx_ctx_wl_set_swap_interval, gfx_ctx_wl_set_video_mode, + gfx_ctx_wl_get_video_size, gfx_ctx_wl_get_refresh_rate, NULL, /* get_video_output_size */ NULL, /* get_video_output_prev */ @@ -1622,6 +1652,8 @@ const gfx_ctx_driver_t gfx_ctx_wayland = { gfx_ctx_wl_check_window, gfx_ctx_wl_set_resize, gfx_ctx_wl_has_focus, + gfx_ctx_wl_suppress_screensaver, + gfx_ctx_wl_has_windowed, gfx_ctx_wl_swap_buffers, gfx_ctx_wl_input_driver, gfx_ctx_wl_get_proc_address, From 9d5cb529c1249e6ceaa6d139cabb4d994b0243cd Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Fri, 23 Nov 2018 21:08:42 +0400 Subject: [PATCH 6/9] Add wait event for surface configure --- gfx/drivers_context/wayland_ctx.c | 71 ++++++------------------------- 1 file changed, 13 insertions(+), 58 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 2e6937f976..f17b79f614 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -76,6 +76,7 @@ typedef struct gfx_ctx_wayland_data bool fullscreen; bool maximized; bool resize; + bool configured; unsigned width; unsigned height; unsigned physical_width; @@ -557,7 +558,7 @@ static const struct xdg_wm_base_listener xdg_shell_listener = { static void handle_surface_config(void *data, struct xdg_surface *surface, uint32_t serial) -{ +{ xdg_surface_ack_configure(surface, serial); } @@ -568,65 +569,14 @@ static const struct xdg_surface_listener xdg_surface_listener = { static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, int width, int height, struct wl_array *states) { - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - int prev_fs_state = wl->fullscreen; - wl->maximized = false; - wl->fullscreen = false; - enum xdg_toplevel_state *state; - wl_array_for_each(state, states) { - switch (*state) { - case XDG_TOPLEVEL_STATE_FULLSCREEN: - wl->fullscreen = true; - break; - case XDG_TOPLEVEL_STATE_RESIZING: - wl->resize = true; - break; - case XDG_TOPLEVEL_STATE_ACTIVATED: - break; - case XDG_TOPLEVEL_STATE_TILED_TOP: - case XDG_TOPLEVEL_STATE_TILED_LEFT: - case XDG_TOPLEVEL_STATE_TILED_RIGHT: - case XDG_TOPLEVEL_STATE_TILED_BOTTOM: - case XDG_TOPLEVEL_STATE_MAXIMIZED: - wl->maximized = true; - break; - } - } + // TODO } + static const struct xdg_toplevel_listener xdg_toplevel_listener = { handle_toplevel_config, }; -//static void shell_surface_handle_configure(void *data, - //struct xdg_surface *xdg_surface, - //uint32_t edges, int32_t width, int32_t height) -//{ - //gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - //(void)xdg_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 shell_surface_handle_popup_done(void *data, - //struct wl_shell_surface *shell_surface) -//{ - //(void)data; - //(void)shell_surface; -//} - -//static const struct wl_shell_surface_listener shell_surface_listener = { - //shell_surface_handle_ping, - //shell_surface_handle_configure, - //shell_surface_handle_popup_done, -//}; - static void display_handle_geometry(void *data, struct wl_output *output, int x, int y, @@ -1341,6 +1291,7 @@ static bool gfx_ctx_wl_set_video_mode(void *data, default: break; } + wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->shell, wl->surface); xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl); @@ -1349,6 +1300,12 @@ static bool gfx_ctx_wl_set_video_mode(void *data, xdg_toplevel_set_app_id (wl->xdg_toplevel, "RetroArch"); xdg_toplevel_set_title (wl->xdg_toplevel, "RetroArch"); + + wl_surface_commit(wl->surface); + wl->configured = true; + + while (wl->configured) + wl_display_dispatch(wl->input.dpy); switch (wl_api) { @@ -1373,11 +1330,9 @@ static bool gfx_ctx_wl_set_video_mode(void *data, break; } - //if (fullscreen) - //wl_shell_surface_set_fullscreen(wl->shell_surf, - //WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); + //TODO: fullscreen; - //flush_wayland_fd(&wl->input); + flush_wayland_fd(&wl->input); switch (wl_api) { From cd8bf003d12af4591e8eb5bf9a91a823275f9bfe Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Fri, 23 Nov 2018 21:23:53 +0400 Subject: [PATCH 7/9] Add toplevel configuration --- gfx/drivers_context/wayland_ctx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index f17b79f614..e7a94c9d9a 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -569,7 +569,15 @@ static const struct xdg_surface_listener xdg_surface_listener = { static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, int width, int height, struct wl_array *states) { - // TODO + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + 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); + + wl->configured = false; } From fbcab67d8b04b3d812cc017266e3c780ba355025 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Fri, 23 Nov 2018 23:04:06 +0400 Subject: [PATCH 8/9] Fix wrong toplevel geometry --- gfx/drivers_context/wayland_ctx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index e7a94c9d9a..d50bb6db54 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -571,11 +571,7 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - 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); + // TODO: implement resizing wl->configured = false; } @@ -1338,7 +1334,8 @@ static bool gfx_ctx_wl_set_video_mode(void *data, break; } - //TODO: fullscreen; + if (fullscreen) + xdg_toplevel_set_fullscreen(wl->xdg_toplevel, NULL); flush_wayland_fd(&wl->input); From 17fd203141c575e4769f7d82591808c2fe37cef5 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Sat, 24 Nov 2018 20:52:22 +0400 Subject: [PATCH 9/9] Waiting for the "initial" set of globals to appear (fixed xdg_wm_base_ping working) --- gfx/drivers_context/wayland_ctx.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index d50bb6db54..480cb20c03 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -350,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, @@ -548,10 +550,11 @@ bool wayland_context_gettouchpos(void *data, unsigned id, /* Shell surface callbacks. */ -static void xdg_shell_ping (void *data, struct xdg_wm_base *shell, uint32_t serial) +static void xdg_shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) { xdg_wm_base_pong(shell, serial); } + static const struct xdg_wm_base_listener xdg_shell_listener = { xdg_shell_ping, }; @@ -576,6 +579,8 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, wl->configured = false; } +// TODO: implement xdg_toplevel close + static const struct xdg_toplevel_listener xdg_toplevel_listener = { handle_toplevel_config, @@ -1305,11 +1310,16 @@ static bool gfx_ctx_wl_set_video_mode(void *data, 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) {