src/video/wayland/SDL_waylandwindow.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 05 Oct 2018 17:24:03 -0400
changeset 12298 c4d5e502c1f4
parent 12201 8bdc4d340419
child 12381 dc9108cd4340
permissions -rw-r--r--
wayland: Fixed missing window sizing events.

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