Browse Source

wayland: Implemented xdg-wm-base support.

This is just in parity with the existing zxdg-shell-unstable-v6 code. Making
the Wayland target robust (and uh, with title bars) is going to take a lot
of work on top of this.
Ryan C. Gordon 6 years ago
parent
commit
c8ac909674

+ 29 - 8
configure

@@ -19228,6 +19228,7 @@ $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h
             fi
 
             WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1 xdg-shell-unstable-v6"
+            WAYLAND_PROTOCOLS_STABLE="xdg-shell"
 
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
             EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
@@ -24712,21 +24713,21 @@ SDLTEST_SOURCES="$srcdir/src/test/*.c"
 if test x$video_wayland = xyes; then
     WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
     WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
-    WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+    WAYLAND_PROTOCOLS_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE $WAYLAND_PROTOCOLS_STABLE |\
         sed 's,[^ ]\+,\\$(gen)/&-protocol.c,g'`
-    WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+    WAYLAND_PROTOCOLS_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE $WAYLAND_PROTOCOLS_STABLE |\
         sed 's,[^ ]\+,\\$(gen)/&-client-protocol.h,g'`
-    GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES"
-    GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS"
+    GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_SOURCES"
+    GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_HEADERS"
 
     WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS="
 $WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
-	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	@\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
 	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) code \$< \$@"
 
     WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS="
 $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
-	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	@\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
 	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) client-header \$< \$@"
 
     WAYLAND_CORE_PROTOCOL_OBJECT="
@@ -24736,13 +24737,25 @@ $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
     WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
         do echo ; echo \$p | sed\
         "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
-	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_CLIENT_HEADER_STABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_STABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([a-z\\-]\\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/stable/\1/&.xml\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
 	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
 
     WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
         do echo ; echo \$p | sed\
         "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
-	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_CODE_STABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_STABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([a-z\\-]\\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/stable/\1/&.xml\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
 	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
 
     WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
@@ -24750,13 +24763,21 @@ $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
         "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
 	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
 
+    WAYLAND_PROTOCOLS_OBJECTS_STABLE=`for p in $WAYLAND_PROTOCOLS_STABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([a-z\\-]\\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
+	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
+
     WAYLAND_PROTOCOLS_DEPENDS="
 $WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
 $WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
 $WAYLAND_CORE_PROTOCOL_OBJECT
 $WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CLIENT_HEADER_STABLE_DEPENDS
 $WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CODE_STABLE_DEPENDS
 $WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
+$WAYLAND_PROTOCOLS_OBJECTS_STABLE
 "
 fi
 

+ 29 - 8
configure.in

@@ -1417,6 +1417,7 @@ AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for
             fi
 
             WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1 xdg-shell-unstable-v6"
+            WAYLAND_PROTOCOLS_STABLE="xdg-shell"
 
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
             EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
@@ -3979,21 +3980,21 @@ SDLTEST_SOURCES="$srcdir/src/test/*.c"
 if test x$video_wayland = xyes; then
     WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
     WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
-    WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+    WAYLAND_PROTOCOLS_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE $WAYLAND_PROTOCOLS_STABLE |\
         sed 's,[[^ ]]\+,\\$(gen)/&-protocol.c,g'`
-    WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+    WAYLAND_PROTOCOLS_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE $WAYLAND_PROTOCOLS_STABLE |\
         sed 's,[[^ ]]\+,\\$(gen)/&-client-protocol.h,g'`
-    GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES"
-    GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS"
+    GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_SOURCES"
+    GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_HEADERS"
 
     WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS="
 $WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
-	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	@\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
 	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) code \$< \$@"
 
     WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS="
 $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
-	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	@\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
 	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) client-header \$< \$@"
 
     WAYLAND_CORE_PROTOCOL_OBJECT="
@@ -4003,13 +4004,25 @@ $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
     WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
         do echo ; echo \$p | sed\
         "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
-	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_CLIENT_HEADER_STABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_STABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([[a-z\\-]]\\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/stable/\1/&.xml\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
 	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
 
     WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
         do echo ; echo \$p | sed\
         "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
-	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_CODE_STABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_STABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([[a-z\\-]]\\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/stable/\1/&.xml\\\\
+	@\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
 	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
 
     WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
@@ -4017,13 +4030,21 @@ $WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
         "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
 	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
 
+    WAYLAND_PROTOCOLS_OBJECTS_STABLE=`for p in $WAYLAND_PROTOCOLS_STABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([[a-z\\-]]\\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
+	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
+
     WAYLAND_PROTOCOLS_DEPENDS="
 $WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
 $WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
 $WAYLAND_CORE_PROTOCOL_OBJECT
 $WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CLIENT_HEADER_STABLE_DEPENDS
 $WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CODE_STABLE_DEPENDS
 $WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
+$WAYLAND_PROTOCOLS_OBJECTS_STABLE
 "
 fi
 

+ 7 - 2
src/video/wayland/SDL_waylandevents.c

@@ -40,6 +40,7 @@
 
 #include "pointer-constraints-unstable-v1-client-protocol.h"
 #include "relative-pointer-unstable-v1-client-protocol.h"
+#include "xdg-shell-client-protocol.h"
 #include "xdg-shell-unstable-v6-client-protocol.h"
 
 #include <linux/input.h>
@@ -263,7 +264,9 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
 
         switch (rc) {
             case SDL_HITTEST_DRAGGABLE:
-                if (input->display->shell.zxdg) {
+                if (input->display->shell.xdg) {
+                    xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel, input->seat, serial);
+                } else if (input->display->shell.zxdg) {
                     zxdg_toplevel_v6_move(window_data->shell_surface.zxdg.roleobj.toplevel, input->seat, serial);
                 } else {
                     wl_shell_surface_move(window_data->shell_surface.wl, input->seat, serial);
@@ -278,7 +281,9 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
             case SDL_HITTEST_RESIZE_BOTTOM:
             case SDL_HITTEST_RESIZE_BOTTOMLEFT:
             case SDL_HITTEST_RESIZE_LEFT:
-                if (input->display->shell.zxdg) {
+                if (input->display->shell.xdg) {
+                    xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel, input->seat, serial, directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+                } else if (input->display->shell.zxdg) {
                     zxdg_toplevel_v6_resize(window_data->shell_surface.zxdg.roleobj.toplevel, input->seat, serial, directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
                 } else {
                     wl_shell_surface_resize(window_data->shell_surface.wl, input->seat, serial, directions_wl[rc - SDL_HITTEST_RESIZE_TOPLEFT]);

+ 18 - 0
src/video/wayland/SDL_waylandvideo.c

@@ -45,6 +45,7 @@
 #include "SDL_waylanddyn.h"
 #include <wayland-util.h>
 
+#include "xdg-shell-client-protocol.h"
 #include "xdg-shell-unstable-v6-client-protocol.h"
 
 #define WAYLANDVID_DRIVER_NAME "wayland"
@@ -327,6 +328,17 @@ static const struct zxdg_shell_v6_listener shell_listener_zxdg = {
 };
 
 
+static void
+handle_ping_xdg_wm_base(void *data, struct xdg_wm_base *xdg, uint32_t serial)
+{
+    xdg_wm_base_pong(xdg, serial);
+}
+
+static const struct xdg_wm_base_listener shell_listener_xdg = {
+    handle_ping_xdg_wm_base
+};
+
+
 static void
 display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
                       const char *interface, uint32_t version)
@@ -339,6 +351,9 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
         Wayland_add_display(d, id);
     } else if (strcmp(interface, "wl_seat") == 0) {
         Wayland_display_add_input(d, id);
+    } else if (strcmp(interface, "xdg_wm_base") == 0) {
+        d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, 1);
+        xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
     } else if (strcmp(interface, "zxdg_shell_v6") == 0) {
         d->shell.zxdg = wl_registry_bind(d->registry, id, &zxdg_shell_v6_interface, 1);
         zxdg_shell_v6_add_listener(d->shell.zxdg, &shell_listener_zxdg, NULL);
@@ -475,6 +490,9 @@ Wayland_VideoQuit(_THIS)
     if (data->shell.wl)
         wl_shell_destroy(data->shell.wl);
 
+    if (data->shell.xdg)
+        xdg_wm_base_destroy(data->shell.xdg);
+
     if (data->shell.zxdg)
         zxdg_shell_v6_destroy(data->shell.zxdg);
 

+ 11 - 1
src/video/wayland/SDL_waylandvideo.h

@@ -24,6 +24,16 @@
 #ifndef SDL_waylandvideo_h_
 #define SDL_waylandvideo_h_
 
+
+/*
+!!! FIXME: xdg_wm_base is the stable replacement for zxdg_shell_v6. While it's
+!!! FIXME:  harmless to leave it here, consider deleting the obsolete codepath
+!!! FIXME:  soon, since Wayland (with xdg_wm_base) will probably be mainline
+!!! FIXME:  by the time people are relying on this SDL target. It's available
+!!! FIXME:  in Ubuntu 18.04 (and other distros).
+*/
+
+
 #include <EGL/egl.h>
 #include "wayland-util.h"
 
@@ -44,7 +54,7 @@ typedef struct {
     struct wl_cursor_theme *cursor_theme;
     struct wl_pointer *pointer;
     struct {
-        /* !!! FIXME: add stable xdg_shell from 1.12 */
+        struct xdg_wm_base *xdg;
         struct zxdg_shell_v6 *zxdg;
         struct wl_shell *wl;
     } shell;

+ 126 - 8
src/video/wayland/SDL_waylandwindow.c

@@ -33,6 +33,7 @@
 #include "SDL_waylanddyn.h"
 #include "SDL_hints.h"
 
+#include "xdg-shell-client-protocol.h"
 #include "xdg-shell-unstable-v6-client-protocol.h"
 
 /* On modern desktops, we probably will use the xdg-shell protocol instead
@@ -185,6 +186,87 @@ static const struct zxdg_toplevel_v6_listener toplevel_listener_zxdg = {
 };
 
 
+
+static void
+handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
+{
+    SDL_WindowData *wind = (SDL_WindowData *)data;
+    SDL_Window *window = wind->sdlwindow;
+    struct wl_region *region;
+
+    wind->shell_surface.xdg.initial_configure_seen = SDL_TRUE;
+
+    WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
+
+    region = wl_compositor_create_region(wind->waylandData->compositor);
+    wl_region_add(region, 0, 0, window->w, window->h);
+    wl_surface_set_opaque_region(wind->surface, region);
+    wl_region_destroy(region);
+    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
+    xdg_surface_ack_configure(xdg, serial);
+}
+
+static const struct xdg_surface_listener shell_surface_listener_xdg = {
+    handle_configure_xdg_shell_surface
+};
+
+
+static void
+handle_configure_xdg_toplevel(void *data,
+			  struct xdg_toplevel *xdg_toplevel,
+			  int32_t width,
+			  int32_t height,
+			  struct wl_array *states)
+{
+    SDL_WindowData *wind = (SDL_WindowData *)data;
+    SDL_Window *window = wind->sdlwindow;
+
+    /* wl_shell_surface spec states that this is a suggestion.
+       Ignore if less than or greater than max/min size. */
+
+    if (width == 0 || height == 0) {
+        return;
+    }
+
+    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
+        if ((window->flags & SDL_WINDOW_RESIZABLE)) {
+            if (window->max_w > 0) {
+                width = SDL_min(width, window->max_w);
+            } 
+            width = SDL_max(width, window->min_w);
+
+            if (window->max_h > 0) {
+                height = SDL_min(height, window->max_h);
+            }
+            height = SDL_max(height, window->min_h);
+        } else {
+            return;
+        }
+    }
+
+    if (width == window->w && height == window->h) {
+        return;
+    }
+
+    window->w = width;
+    window->h = height;
+}
+
+static void
+handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
+{
+    SDL_WindowData *window = (SDL_WindowData *)data;
+    SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
+}
+
+static const struct xdg_toplevel_listener toplevel_listener_xdg = {
+    handle_configure_xdg_toplevel,
+    handle_close_xdg_toplevel
+};
+
+
+
+
 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
 static void
 handle_onscreen_visibility(void *data,
@@ -257,7 +339,13 @@ SetFullscreen(_THIS, SDL_Window * window, struct wl_output *output)
     const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
     SDL_WindowData *wind = window->driverdata;
 
-    if (viddata->shell.zxdg) {
+    if (viddata->shell.xdg) {
+        if (output) {
+            xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
+        } else {
+            xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
+        }
+    } else if (viddata->shell.zxdg) {
         if (output) {
             zxdg_toplevel_v6_set_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel, output);
         } else {
@@ -362,7 +450,8 @@ Wayland_RestoreWindow(_THIS, SDL_Window * window)
     SDL_WindowData *wind = window->driverdata;
     const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
 
-    if (viddata->shell.zxdg) {
+    if (viddata->shell.xdg) {
+    } else if (viddata->shell.zxdg) {
     } else {
         wl_shell_surface_set_toplevel(wind->shell_surface.wl);
     }
@@ -376,7 +465,9 @@ Wayland_MaximizeWindow(_THIS, SDL_Window * window)
     SDL_WindowData *wind = window->driverdata;
     SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
 
-    if (viddata->shell.zxdg) {
+    if (viddata->shell.xdg) {
+        xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
+    } else if (viddata->shell.zxdg) {
         zxdg_toplevel_v6_set_maximized(wind->shell_surface.zxdg.roleobj.toplevel);
     } else {
         wl_shell_surface_set_maximized(wind->shell_surface.wl, NULL);
@@ -417,7 +508,13 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
         wl_compositor_create_surface(c->compositor);
     wl_surface_set_user_data(data->surface, data);
 
-    if (c->shell.zxdg) {
+    if (c->shell.xdg) {
+        data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
+        /* !!! FIXME: add popup role */
+        data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
+        xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
+        xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
+    } else if (c->shell.zxdg) {
         data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface);
         /* !!! FIXME: add popup role */
         data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(data->shell_surface.zxdg.surface);
@@ -448,7 +545,12 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
         return SDL_SetError("failed to create a window surface");
     }
 
-    if (c->shell.zxdg) {
+    if (c->shell.xdg) {
+        if (data->shell_surface.xdg.surface) {
+            xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
+            xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
+        }
+    } else if (c->shell.zxdg) {
         if (data->shell_surface.zxdg.surface) {
             zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data);
             zxdg_surface_v6_add_listener(data->shell_surface.zxdg.surface, &shell_surface_listener_zxdg, data);
@@ -482,7 +584,14 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
 
     /* we have to wait until the surface gets a "configure" event, or
        use of this surface will fail. This is a new rule for xdg_shell. */
-    if (c->shell.zxdg) {
+    if (c->shell.xdg) {
+        if (data->shell_surface.xdg.surface) {
+            while (!data->shell_surface.xdg.initial_configure_seen) {
+                WAYLAND_wl_display_flush(c->display);
+                WAYLAND_wl_display_dispatch(c->display);
+            }
+        }
+    } else if (c->shell.zxdg) {
         if (data->shell_surface.zxdg.surface) {
             while (!data->shell_surface.zxdg.initial_configure_seen) {
                 WAYLAND_wl_display_flush(c->display);
@@ -514,7 +623,9 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
     SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
     
     if (window->title != NULL) {
-        if (viddata->shell.zxdg) {
+        if (viddata->shell.xdg) {
+            xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, window->title);
+        } else if (viddata->shell.zxdg) {
             zxdg_toplevel_v6_set_title(wind->shell_surface.zxdg.roleobj.toplevel, window->title);
         } else {
             wl_shell_surface_set_title(wind->shell_surface.wl, window->title);
@@ -533,7 +644,14 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
         SDL_EGL_DestroySurface(_this, wind->egl_surface);
         WAYLAND_wl_egl_window_destroy(wind->egl_window);
 
-        if (data->shell.zxdg) {
+        if (data->shell.xdg) {
+            if (wind->shell_surface.xdg.roleobj.toplevel) {
+                xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
+            }
+            if (wind->shell_surface.zxdg.surface) {
+                xdg_surface_destroy(wind->shell_surface.xdg.surface);
+            }
+        } else if (data->shell.zxdg) {
             if (wind->shell_surface.zxdg.roleobj.toplevel) {
                 zxdg_toplevel_v6_destroy(wind->shell_surface.zxdg.roleobj.toplevel);
             }

+ 10 - 1
src/video/wayland/SDL_waylandwindow.h

@@ -40,12 +40,21 @@ typedef struct {
     SDL_bool initial_configure_seen;
 } SDL_zxdg_shell_surface;
 
+typedef struct {
+    struct xdg_surface *surface;
+    union {
+        struct xdg_toplevel *toplevel;
+        struct xdg_popup *popup;
+    } roleobj;
+    SDL_bool initial_configure_seen;
+} SDL_xdg_shell_surface;
+
 typedef struct {
     SDL_Window *sdlwindow;
     SDL_VideoData *waylandData;
     struct wl_surface *surface;
     union {
-        /* !!! FIXME: add stable xdg_shell from 1.12 */
+        SDL_xdg_shell_surface xdg;
         SDL_zxdg_shell_surface zxdg;
         struct wl_shell_surface *wl;
     } shell_surface;