src/video/wayland/SDL_waylandwindow.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 07 Feb 2018 13:13:55 -0500
changeset 11848 2f157c1ca383
parent 11811 5d94cb6b24d3
child 11944 295cf9910d75
permissions -rw-r--r--
wayland: Add support for xdg-shell protocol (unstable v6).

This is meant to be the desktop-enhanced version of wl_shell. Right now we
just match what the existing wl_shell code does, but there are other areas of
functionality available to us now, that we can fill in later.

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