src/video/wayland/SDL_waylandwindow.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 24 Jun 2018 22:42:36 -0700
changeset 12033 bc702c5a7c3a
parent 11944 295cf9910d75
child 12201 8bdc4d340419
child 12367 8256aaaafe54
permissions -rw-r--r--
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.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 #include "../../SDL_internal.h"
    23 
    24 #if SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL
    25 
    26 #include "../SDL_sysvideo.h"
    27 #include "../../events/SDL_windowevents_c.h"
    28 #include "../SDL_egl_c.h"
    29 #include "SDL_waylandevents_c.h"
    30 #include "SDL_waylandwindow.h"
    31 #include "SDL_waylandvideo.h"
    32 #include "SDL_waylandtouch.h"
    33 #include "SDL_waylanddyn.h"
    34 #include "SDL_hints.h"
    35 
    36 #include "xdg-shell-client-protocol.h"
    37 #include "xdg-shell-unstable-v6-client-protocol.h"
    38 
    39 /* On modern desktops, we probably will use the xdg-shell protocol instead
    40    of wl_shell, but wl_shell might be useful on older Wayland installs that
    41    don't have the newer protocol, or embedded things that don't have a full
    42    window manager. */
    43 
    44 static void
    45 handle_ping_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
    46             uint32_t serial)
    47 {
    48     wl_shell_surface_pong(shell_surface, serial);
    49 }
    50 
    51 static void
    52 handle_configure_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
    53                  uint32_t edges, int32_t width, int32_t height)
    54 {
    55     SDL_WindowData *wind = (SDL_WindowData *)data;
    56     SDL_Window *window = wind->sdlwindow;
    57     struct wl_region *region;
    58 
    59     /* wl_shell_surface spec states that this is a suggestion.
    60        Ignore if less than or greater than max/min size. */
    61 
    62     if (width == 0 || height == 0) {
    63         return;
    64     }
    65 
    66     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
    67         if ((window->flags & SDL_WINDOW_RESIZABLE)) {
    68             if (window->max_w > 0) {
    69                 width = SDL_min(width, window->max_w);
    70             } 
    71             width = SDL_max(width, window->min_w);
    72 
    73             if (window->max_h > 0) {
    74                 height = SDL_min(height, window->max_h);
    75             }
    76             height = SDL_max(height, window->min_h);
    77         } else {
    78             return;
    79         }
    80     }
    81 
    82     if (width == window->w && height == window->h) {
    83         return;
    84     }
    85 
    86     window->w = width;
    87     window->h = height;
    88     WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
    89 
    90     region = wl_compositor_create_region(wind->waylandData->compositor);
    91     wl_region_add(region, 0, 0, window->w, window->h);
    92     wl_surface_set_opaque_region(wind->surface, region);
    93     wl_region_destroy(region);
    94     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
    95 }
    96 
    97 static void
    98 handle_popup_done_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface)
    99 {
   100 }
   101 
   102 static const struct wl_shell_surface_listener shell_surface_listener_wl = {
   103     handle_ping_wl_shell_surface,
   104     handle_configure_wl_shell_surface,
   105     handle_popup_done_wl_shell_surface
   106 };
   107 
   108 
   109 
   110 
   111 static void
   112 handle_configure_zxdg_shell_surface(void *data, struct zxdg_surface_v6 *zxdg, uint32_t serial)
   113 {
   114     SDL_WindowData *wind = (SDL_WindowData *)data;
   115     SDL_Window *window = wind->sdlwindow;
   116     struct wl_region *region;
   117 
   118     wind->shell_surface.zxdg.initial_configure_seen = SDL_TRUE;
   119 
   120     WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
   121 
   122     region = wl_compositor_create_region(wind->waylandData->compositor);
   123     wl_region_add(region, 0, 0, window->w, window->h);
   124     wl_surface_set_opaque_region(wind->surface, region);
   125     wl_region_destroy(region);
   126     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
   127     zxdg_surface_v6_ack_configure(zxdg, serial);
   128 }
   129 
   130 static const struct zxdg_surface_v6_listener shell_surface_listener_zxdg = {
   131     handle_configure_zxdg_shell_surface
   132 };
   133 
   134 
   135 static void
   136 handle_configure_zxdg_toplevel(void *data,
   137 			  struct zxdg_toplevel_v6 *zxdg_toplevel_v6,
   138 			  int32_t width,
   139 			  int32_t height,
   140 			  struct wl_array *states)
   141 {
   142     SDL_WindowData *wind = (SDL_WindowData *)data;
   143     SDL_Window *window = wind->sdlwindow;
   144 
   145     /* wl_shell_surface spec states that this is a suggestion.
   146        Ignore if less than or greater than max/min size. */
   147 
   148     if (width == 0 || height == 0) {
   149         return;
   150     }
   151 
   152     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   153         if ((window->flags & SDL_WINDOW_RESIZABLE)) {
   154             if (window->max_w > 0) {
   155                 width = SDL_min(width, window->max_w);
   156             } 
   157             width = SDL_max(width, window->min_w);
   158 
   159             if (window->max_h > 0) {
   160                 height = SDL_min(height, window->max_h);
   161             }
   162             height = SDL_max(height, window->min_h);
   163         } else {
   164             return;
   165         }
   166     }
   167 
   168     if (width == window->w && height == window->h) {
   169         return;
   170     }
   171 
   172     window->w = width;
   173     window->h = height;
   174 }
   175 
   176 static void
   177 handle_close_zxdg_toplevel(void *data, struct zxdg_toplevel_v6 *zxdg_toplevel_v6)
   178 {
   179     SDL_WindowData *window = (SDL_WindowData *)data;
   180     SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
   181 }
   182 
   183 static const struct zxdg_toplevel_v6_listener toplevel_listener_zxdg = {
   184     handle_configure_zxdg_toplevel,
   185     handle_close_zxdg_toplevel
   186 };
   187 
   188 
   189 
   190 static void
   191 handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
   192 {
   193     SDL_WindowData *wind = (SDL_WindowData *)data;
   194     SDL_Window *window = wind->sdlwindow;
   195     struct wl_region *region;
   196 
   197     wind->shell_surface.xdg.initial_configure_seen = SDL_TRUE;
   198 
   199     WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
   200 
   201     region = wl_compositor_create_region(wind->waylandData->compositor);
   202     wl_region_add(region, 0, 0, window->w, window->h);
   203     wl_surface_set_opaque_region(wind->surface, region);
   204     wl_region_destroy(region);
   205     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
   206     xdg_surface_ack_configure(xdg, serial);
   207 }
   208 
   209 static const struct xdg_surface_listener shell_surface_listener_xdg = {
   210     handle_configure_xdg_shell_surface
   211 };
   212 
   213 
   214 static void
   215 handle_configure_xdg_toplevel(void *data,
   216 			  struct xdg_toplevel *xdg_toplevel,
   217 			  int32_t width,
   218 			  int32_t height,
   219 			  struct wl_array *states)
   220 {
   221     SDL_WindowData *wind = (SDL_WindowData *)data;
   222     SDL_Window *window = wind->sdlwindow;
   223 
   224     /* wl_shell_surface spec states that this is a suggestion.
   225        Ignore if less than or greater than max/min size. */
   226 
   227     if (width == 0 || height == 0) {
   228         return;
   229     }
   230 
   231     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   232         if ((window->flags & SDL_WINDOW_RESIZABLE)) {
   233             if (window->max_w > 0) {
   234                 width = SDL_min(width, window->max_w);
   235             } 
   236             width = SDL_max(width, window->min_w);
   237 
   238             if (window->max_h > 0) {
   239                 height = SDL_min(height, window->max_h);
   240             }
   241             height = SDL_max(height, window->min_h);
   242         } else {
   243             return;
   244         }
   245     }
   246 
   247     if (width == window->w && height == window->h) {
   248         return;
   249     }
   250 
   251     window->w = width;
   252     window->h = height;
   253 }
   254 
   255 static void
   256 handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
   257 {
   258     SDL_WindowData *window = (SDL_WindowData *)data;
   259     SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
   260 }
   261 
   262 static const struct xdg_toplevel_listener toplevel_listener_xdg = {
   263     handle_configure_xdg_toplevel,
   264     handle_close_xdg_toplevel
   265 };
   266 
   267 
   268 
   269 
   270 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   271 static void
   272 handle_onscreen_visibility(void *data,
   273         struct qt_extended_surface *qt_extended_surface, int32_t visible)
   274 {
   275 }
   276 
   277 static void
   278 handle_set_generic_property(void *data,
   279         struct qt_extended_surface *qt_extended_surface, const char *name,
   280         struct wl_array *value)
   281 {
   282 }
   283 
   284 static void
   285 handle_close(void *data, struct qt_extended_surface *qt_extended_surface)
   286 {
   287     SDL_WindowData *window = (SDL_WindowData *)data;
   288     SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
   289 }
   290 
   291 static const struct qt_extended_surface_listener extended_surface_listener = {
   292     handle_onscreen_visibility,
   293     handle_set_generic_property,
   294     handle_close,
   295 };
   296 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   297 
   298 SDL_bool
   299 Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   300 {
   301     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   302     const Uint32 version = ((((Uint32) info->version.major) * 1000000) +
   303                             (((Uint32) info->version.minor) * 10000) +
   304                             (((Uint32) info->version.patch)));
   305 
   306     /* Before 2.0.6, it was possible to build an SDL with Wayland support
   307        (SDL_SysWMinfo will be large enough to hold Wayland info), but build
   308        your app against SDL headers that didn't have Wayland support
   309        (SDL_SysWMinfo could be smaller than Wayland needs. This would lead
   310        to an app properly using SDL_GetWindowWMInfo() but we'd accidentally
   311        overflow memory on the stack or heap. To protect against this, we've
   312        padded out the struct unconditionally in the headers and Wayland will
   313        just return an error for older apps using this function. Those apps
   314        will need to be recompiled against newer headers or not use Wayland,
   315        maybe by forcing SDL_VIDEODRIVER=x11. */
   316     if (version < 2000006) {
   317         info->subsystem = SDL_SYSWM_UNKNOWN;
   318         SDL_SetError("Version must be 2.0.6 or newer");
   319         return SDL_FALSE;
   320     }
   321 
   322     info->info.wl.display = data->waylandData->display;
   323     info->info.wl.surface = data->surface;
   324     info->info.wl.shell_surface = data->shell_surface.wl;
   325     info->subsystem = SDL_SYSWM_WAYLAND;
   326 
   327     return SDL_TRUE;
   328 }
   329 
   330 int
   331 Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
   332 {
   333     return 0;  /* just succeed, the real work is done elsewhere. */
   334 }
   335 
   336 static void
   337 SetFullscreen(_THIS, SDL_Window * window, struct wl_output *output)
   338 {
   339     const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
   340     SDL_WindowData *wind = window->driverdata;
   341 
   342     if (viddata->shell.xdg) {
   343         if (output) {
   344             xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
   345         } else {
   346             xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
   347         }
   348     } else if (viddata->shell.zxdg) {
   349         if (output) {
   350             zxdg_toplevel_v6_set_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel, output);
   351         } else {
   352             zxdg_toplevel_v6_unset_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel);
   353         }
   354     } else {
   355         if (output) {
   356             wl_shell_surface_set_fullscreen(wind->shell_surface.wl,
   357                                             WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
   358                                             0, output);
   359         } else {
   360             wl_shell_surface_set_toplevel(wind->shell_surface.wl);
   361         }
   362     }
   363 
   364     WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
   365 }
   366 
   367 void Wayland_ShowWindow(_THIS, SDL_Window *window)
   368 {
   369     struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
   370     SetFullscreen(_this, window, (window->flags & SDL_WINDOW_FULLSCREEN) ? output : NULL);
   371 }
   372 
   373 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   374 static void SDLCALL
   375 QtExtendedSurface_OnHintChanged(void *userdata, const char *name,
   376         const char *oldValue, const char *newValue)
   377 {
   378     struct qt_extended_surface *qt_extended_surface = userdata;
   379 
   380     if (name == NULL) {
   381         return;
   382     }
   383 
   384     if (strcmp(name, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION) == 0) {
   385         int32_t orientation = QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION;
   386 
   387         if (newValue != NULL) {
   388             if (strcmp(newValue, "portrait") == 0) {
   389                 orientation = QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION;
   390             } else if (strcmp(newValue, "landscape") == 0) {
   391                 orientation = QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION;
   392             } else if (strcmp(newValue, "inverted-portrait") == 0) {
   393                 orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION;
   394             } else if (strcmp(newValue, "inverted-landscape") == 0) {
   395                 orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION;
   396             }
   397         }
   398 
   399         qt_extended_surface_set_content_orientation(qt_extended_surface, orientation);
   400     } else if (strcmp(name, SDL_HINT_QTWAYLAND_WINDOW_FLAGS) == 0) {
   401         uint32_t flags = 0;
   402 
   403         if (newValue != NULL) {
   404             char *tmp = strdup(newValue);
   405             char *saveptr = NULL;
   406 
   407             char *flag = strtok_r(tmp, " ", &saveptr);
   408             while (flag) {
   409                 if (strcmp(flag, "OverridesSystemGestures") == 0) {
   410                     flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES;
   411                 } else if (strcmp(flag, "StaysOnTop") == 0) {
   412                     flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP;
   413                 } else if (strcmp(flag, "BypassWindowManager") == 0) {
   414                     // See https://github.com/qtproject/qtwayland/commit/fb4267103d
   415                     flags |= 4 /* QT_EXTENDED_SURFACE_WINDOWFLAG_BYPASSWINDOWMANAGER */;
   416                 }
   417 
   418                 flag = strtok_r(NULL, " ", &saveptr);
   419             }
   420 
   421             free(tmp);
   422         }
   423 
   424         qt_extended_surface_set_window_flags(qt_extended_surface, flags);
   425     }
   426 }
   427 
   428 static void QtExtendedSurface_Subscribe(struct qt_extended_surface *surface, const char *name)
   429 {
   430     SDL_AddHintCallback(name, QtExtendedSurface_OnHintChanged, surface);
   431 }
   432 
   433 static void QtExtendedSurface_Unsubscribe(struct qt_extended_surface *surface, const char *name)
   434 {
   435     SDL_DelHintCallback(name, QtExtendedSurface_OnHintChanged, surface);
   436 }
   437 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   438 
   439 void
   440 Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
   441                             SDL_VideoDisplay * _display, SDL_bool fullscreen)
   442 {
   443     struct wl_output *output = (struct wl_output *) _display->driverdata;
   444     SetFullscreen(_this, window, fullscreen ? output : NULL);
   445 }
   446 
   447 void
   448 Wayland_RestoreWindow(_THIS, SDL_Window * window)
   449 {
   450     SDL_WindowData *wind = window->driverdata;
   451     const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
   452 
   453     if (viddata->shell.xdg) {
   454     } else if (viddata->shell.zxdg) {
   455     } else {
   456         wl_shell_surface_set_toplevel(wind->shell_surface.wl);
   457     }
   458 
   459     WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
   460 }
   461 
   462 void
   463 Wayland_MaximizeWindow(_THIS, SDL_Window * window)
   464 {
   465     SDL_WindowData *wind = window->driverdata;
   466     SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
   467 
   468     if (viddata->shell.xdg) {
   469         xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
   470     } else if (viddata->shell.zxdg) {
   471         zxdg_toplevel_v6_set_maximized(wind->shell_surface.zxdg.roleobj.toplevel);
   472     } else {
   473         wl_shell_surface_set_maximized(wind->shell_surface.wl, NULL);
   474     }
   475 
   476     WAYLAND_wl_display_flush( viddata->display );
   477 }
   478 
   479 int Wayland_CreateWindow(_THIS, SDL_Window *window)
   480 {
   481     SDL_WindowData *data;
   482     SDL_VideoData *c;
   483     struct wl_region *region;
   484 
   485     data = calloc(1, sizeof *data);
   486     if (data == NULL)
   487         return SDL_OutOfMemory();
   488 
   489     c = _this->driverdata;
   490     window->driverdata = data;
   491 
   492     if (!(window->flags & SDL_WINDOW_OPENGL)) {
   493         SDL_GL_LoadLibrary(NULL);
   494         window->flags |= SDL_WINDOW_OPENGL;
   495     }
   496 
   497     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   498         window->x = 0;
   499     }
   500     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
   501         window->y = 0;
   502     }
   503 
   504     data->waylandData = c;
   505     data->sdlwindow = window;
   506 
   507     data->surface =
   508         wl_compositor_create_surface(c->compositor);
   509     wl_surface_set_user_data(data->surface, data);
   510 
   511     if (c->shell.xdg) {
   512         data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
   513         /* !!! FIXME: add popup role */
   514         data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
   515         xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
   516         xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
   517     } else if (c->shell.zxdg) {
   518         data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface);
   519         /* !!! FIXME: add popup role */
   520         data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(data->shell_surface.zxdg.surface);
   521         zxdg_toplevel_v6_add_listener(data->shell_surface.zxdg.roleobj.toplevel, &toplevel_listener_zxdg, data);
   522         zxdg_toplevel_v6_set_app_id(data->shell_surface.zxdg.roleobj.toplevel, c->classname);
   523     } else {
   524         data->shell_surface.wl = wl_shell_get_shell_surface(c->shell.wl, data->surface);
   525         wl_shell_surface_set_class(data->shell_surface.wl, c->classname);
   526     }
   527 
   528 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   529     if (c->surface_extension) {
   530         data->extended_surface = qt_surface_extension_get_extended_surface(
   531                 c->surface_extension, data->surface);
   532 
   533         QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION);
   534         QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS);
   535     }
   536 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   537 
   538     data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
   539                                             window->w, window->h);
   540 
   541     /* Create the GLES window surface */
   542     data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
   543     
   544     if (data->egl_surface == EGL_NO_SURFACE) {
   545         return SDL_SetError("failed to create a window surface");
   546     }
   547 
   548     if (c->shell.xdg) {
   549         if (data->shell_surface.xdg.surface) {
   550             xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
   551             xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
   552         }
   553     } else if (c->shell.zxdg) {
   554         if (data->shell_surface.zxdg.surface) {
   555             zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data);
   556             zxdg_surface_v6_add_listener(data->shell_surface.zxdg.surface, &shell_surface_listener_zxdg, data);
   557         }
   558     } else {
   559         if (data->shell_surface.wl) {
   560             wl_shell_surface_set_user_data(data->shell_surface.wl, data);
   561             wl_shell_surface_add_listener(data->shell_surface.wl, &shell_surface_listener_wl, data);
   562         }
   563     }
   564 
   565 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   566     if (data->extended_surface) {
   567         qt_extended_surface_set_user_data(data->extended_surface, data);
   568         qt_extended_surface_add_listener(data->extended_surface,
   569                                          &extended_surface_listener, data);
   570     }
   571 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   572 
   573     region = wl_compositor_create_region(c->compositor);
   574     wl_region_add(region, 0, 0, window->w, window->h);
   575     wl_surface_set_opaque_region(data->surface, region);
   576     wl_region_destroy(region);
   577 
   578     if (c->relative_mouse_mode) {
   579         Wayland_input_lock_pointer(c->input);
   580     }
   581 
   582     wl_surface_commit(data->surface);
   583     WAYLAND_wl_display_flush(c->display);
   584 
   585     /* we have to wait until the surface gets a "configure" event, or
   586        use of this surface will fail. This is a new rule for xdg_shell. */
   587     if (c->shell.xdg) {
   588         if (data->shell_surface.xdg.surface) {
   589             while (!data->shell_surface.xdg.initial_configure_seen) {
   590                 WAYLAND_wl_display_flush(c->display);
   591                 WAYLAND_wl_display_dispatch(c->display);
   592             }
   593         }
   594     } else if (c->shell.zxdg) {
   595         if (data->shell_surface.zxdg.surface) {
   596             while (!data->shell_surface.zxdg.initial_configure_seen) {
   597                 WAYLAND_wl_display_flush(c->display);
   598                 WAYLAND_wl_display_dispatch(c->display);
   599             }
   600         }
   601     }
   602 
   603     return 0;
   604 }
   605 
   606 void Wayland_SetWindowSize(_THIS, SDL_Window * window)
   607 {
   608     SDL_VideoData *data = _this->driverdata;
   609     SDL_WindowData *wind = window->driverdata;
   610     struct wl_region *region;
   611 
   612     WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
   613 
   614     region =wl_compositor_create_region(data->compositor);
   615     wl_region_add(region, 0, 0, window->w, window->h);
   616     wl_surface_set_opaque_region(wind->surface, region);
   617     wl_region_destroy(region);
   618 }
   619 
   620 void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
   621 {
   622     SDL_WindowData *wind = window->driverdata;
   623     SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
   624     
   625     if (window->title != NULL) {
   626         if (viddata->shell.xdg) {
   627             xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, window->title);
   628         } else if (viddata->shell.zxdg) {
   629             zxdg_toplevel_v6_set_title(wind->shell_surface.zxdg.roleobj.toplevel, window->title);
   630         } else {
   631             wl_shell_surface_set_title(wind->shell_surface.wl, window->title);
   632         }
   633     }
   634 
   635     WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
   636 }
   637 
   638 void Wayland_DestroyWindow(_THIS, SDL_Window *window)
   639 {
   640     SDL_VideoData *data = _this->driverdata;
   641     SDL_WindowData *wind = window->driverdata;
   642 
   643     if (data) {
   644         SDL_EGL_DestroySurface(_this, wind->egl_surface);
   645         WAYLAND_wl_egl_window_destroy(wind->egl_window);
   646 
   647         if (data->shell.xdg) {
   648             if (wind->shell_surface.xdg.roleobj.toplevel) {
   649                 xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
   650             }
   651             if (wind->shell_surface.zxdg.surface) {
   652                 xdg_surface_destroy(wind->shell_surface.xdg.surface);
   653             }
   654         } else if (data->shell.zxdg) {
   655             if (wind->shell_surface.zxdg.roleobj.toplevel) {
   656                 zxdg_toplevel_v6_destroy(wind->shell_surface.zxdg.roleobj.toplevel);
   657             }
   658             if (wind->shell_surface.zxdg.surface) {
   659                 zxdg_surface_v6_destroy(wind->shell_surface.zxdg.surface);
   660             }
   661         } else {
   662             if (wind->shell_surface.wl) {
   663                 wl_shell_surface_destroy(wind->shell_surface.wl);
   664             }
   665         }
   666 
   667 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   668         if (wind->extended_surface) {
   669             QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION);
   670             QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS);
   671             qt_extended_surface_destroy(wind->extended_surface);
   672         }
   673 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   674         wl_surface_destroy(wind->surface);
   675 
   676         SDL_free(wind);
   677         WAYLAND_wl_display_flush(data->display);
   678     }
   679     window->driverdata = NULL;
   680 }
   681 
   682 #endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
   683 
   684 /* vi: set ts=4 sw=4 expandtab: */