src/video/wayland/SDL_waylandvideo.c
author Ryan C. Gordon
Tue, 07 Apr 2020 13:30:46 -0400
changeset 13701 3cc182fa6110
parent 13422 fd6a12de91c7
child 13805 4709c1dfeabb
permissions -rw-r--r--
wayland: Support wayland compositors with wl_seat version < 5 (thanks, Nia!).

Fixes Bugzilla #5074.
gabomdq@8062
     1
/*
gabomdq@8062
     2
  Simple DirectMedia Layer
slouken@13422
     3
  Copyright (C) 1997-2020 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
icculus@8116
    25
gabomdq@8062
    26
#include "SDL_video.h"
gabomdq@8062
    27
#include "SDL_mouse.h"
gabomdq@8104
    28
#include "SDL_stdinc.h"
gabomdq@8062
    29
#include "../../events/SDL_events_c.h"
gabomdq@8062
    30
gabomdq@8062
    31
#include "SDL_waylandvideo.h"
gabomdq@8062
    32
#include "SDL_waylandevents_c.h"
gabomdq@8062
    33
#include "SDL_waylandwindow.h"
gabomdq@8062
    34
#include "SDL_waylandopengles.h"
gabomdq@8062
    35
#include "SDL_waylandmouse.h"
gabomdq@8082
    36
#include "SDL_waylandtouch.h"
slouken@10583
    37
#include "SDL_waylandclipboard.h"
icculus@11365
    38
#include "SDL_waylandvulkan.h"
gabomdq@8062
    39
hadess@10302
    40
#include <sys/types.h>
hadess@10302
    41
#include <unistd.h>
gabomdq@8062
    42
#include <fcntl.h>
gabomdq@8062
    43
#include <xkbcommon/xkbcommon.h>
gabomdq@8062
    44
gabomdq@8104
    45
#include "SDL_waylanddyn.h"
gabomdq@8104
    46
#include <wayland-util.h>
gabomdq@8104
    47
icculus@12033
    48
#include "xdg-shell-client-protocol.h"
icculus@11848
    49
#include "xdg-shell-unstable-v6-client-protocol.h"
dos@12426
    50
#include "xdg-decoration-unstable-v1-client-protocol.h"
icculus@12367
    51
#include "org-kde-kwin-server-decoration-manager-client-protocol.h"
icculus@11848
    52
gabomdq@8062
    53
#define WAYLANDVID_DRIVER_NAME "wayland"
gabomdq@8062
    54
gabomdq@8062
    55
/* Initialization/Query functions */
gabomdq@8062
    56
static int
gabomdq@8062
    57
Wayland_VideoInit(_THIS);
gabomdq@8062
    58
gabomdq@8062
    59
static void
gabomdq@8062
    60
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display);
gabomdq@8062
    61
static int
gabomdq@8062
    62
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
gabomdq@8062
    63
gabomdq@8062
    64
static void
gabomdq@8062
    65
Wayland_VideoQuit(_THIS);
gabomdq@8062
    66
hadess@10302
    67
/* Find out what class name we should use
hadess@10302
    68
 * Based on src/video/x11/SDL_x11video.c */
hadess@10302
    69
static char *
hadess@10302
    70
get_classname()
hadess@10302
    71
{
icculus@11848
    72
/* !!! FIXME: this is probably wrong, albeit harmless in many common cases. From protocol spec:
slouken@12201
    73
    "The surface class identifies the general class of applications
slouken@12201
    74
    to which the surface belongs. A common convention is to use the
slouken@12201
    75
    file name (or the full path if it is a non-standard location) of
slouken@12201
    76
    the application's .desktop file as the class." */
icculus@11848
    77
hadess@10302
    78
    char *spot;
hadess@10302
    79
#if defined(__LINUX__) || defined(__FREEBSD__)
hadess@10302
    80
    char procfile[1024];
hadess@10302
    81
    char linkfile[1024];
hadess@10302
    82
    int linksize;
hadess@10302
    83
#endif
hadess@10302
    84
hadess@10302
    85
    /* First allow environment variable override */
hadess@10302
    86
    spot = SDL_getenv("SDL_VIDEO_WAYLAND_WMCLASS");
hadess@10302
    87
    if (spot) {
hadess@10302
    88
        return SDL_strdup(spot);
hadess@10302
    89
    } else {
hadess@10302
    90
        /* Fallback to the "old" envvar */
hadess@10302
    91
        spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
hadess@10302
    92
        if (spot) {
hadess@10302
    93
            return SDL_strdup(spot);
hadess@10302
    94
        }
hadess@10302
    95
    }
hadess@10302
    96
hadess@10302
    97
    /* Next look at the application's executable name */
hadess@10302
    98
#if defined(__LINUX__) || defined(__FREEBSD__)
hadess@10302
    99
#if defined(__LINUX__)
hadess@10302
   100
    SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
hadess@10302
   101
#elif defined(__FREEBSD__)
hadess@10302
   102
    SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file",
hadess@10302
   103
                 getpid());
hadess@10302
   104
#else
hadess@10302
   105
#error Where can we find the executable name?
hadess@10302
   106
#endif
hadess@10302
   107
    linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
hadess@10302
   108
    if (linksize > 0) {
hadess@10302
   109
        linkfile[linksize] = '\0';
hadess@10302
   110
        spot = SDL_strrchr(linkfile, '/');
hadess@10302
   111
        if (spot) {
hadess@10302
   112
            return SDL_strdup(spot + 1);
hadess@10302
   113
        } else {
hadess@10302
   114
            return SDL_strdup(linkfile);
hadess@10302
   115
        }
hadess@10302
   116
    }
hadess@10302
   117
#endif /* __LINUX__ || __FREEBSD__ */
hadess@10302
   118
hadess@10302
   119
    /* Finally use the default we've used forever */
hadess@10302
   120
    return SDL_strdup("SDL_App");
hadess@10302
   121
}
hadess@10302
   122
gabomdq@8062
   123
/* Wayland driver bootstrap functions */
gabomdq@8062
   124
static int
gabomdq@8062
   125
Wayland_Available(void)
gabomdq@8062
   126
{
gabomdq@8062
   127
    struct wl_display *display = NULL;
gabomdq@8104
   128
    if (SDL_WAYLAND_LoadSymbols()) {
gabomdq@8104
   129
        display = WAYLAND_wl_display_connect(NULL);
gabomdq@8104
   130
        if (display != NULL) {
gabomdq@8104
   131
            WAYLAND_wl_display_disconnect(display);
gabomdq@8104
   132
        }
gabomdq@8104
   133
        SDL_WAYLAND_UnloadSymbols();
gabomdq@8062
   134
    }
gabomdq@8062
   135
gabomdq@8062
   136
    return (display != NULL);
gabomdq@8062
   137
}
gabomdq@8062
   138
gabomdq@8062
   139
static void
gabomdq@8062
   140
Wayland_DeleteDevice(SDL_VideoDevice *device)
gabomdq@8062
   141
{
gabomdq@8062
   142
    SDL_free(device);
gabomdq@8104
   143
    SDL_WAYLAND_UnloadSymbols();
gabomdq@8062
   144
}
gabomdq@8062
   145
gabomdq@8062
   146
static SDL_VideoDevice *
gabomdq@8062
   147
Wayland_CreateDevice(int devindex)
gabomdq@8062
   148
{
gabomdq@8062
   149
    SDL_VideoDevice *device;
linkmauve@9467
   150
gabomdq@8104
   151
    if (!SDL_WAYLAND_LoadSymbols()) {
gabomdq@8104
   152
        return NULL;
gabomdq@8104
   153
    }
gabomdq@8062
   154
gabomdq@8062
   155
    /* Initialize all variables that we clean on shutdown */
gabomdq@8062
   156
    device = SDL_calloc(1, sizeof(SDL_VideoDevice));
gabomdq@8062
   157
    if (!device) {
icculus@8160
   158
        SDL_WAYLAND_UnloadSymbols();
gabomdq@8062
   159
        SDL_OutOfMemory();
gabomdq@8062
   160
        return NULL;
gabomdq@8062
   161
    }
gabomdq@8062
   162
gabomdq@8062
   163
    /* Set the function pointers */
gabomdq@8062
   164
    device->VideoInit = Wayland_VideoInit;
gabomdq@8062
   165
    device->VideoQuit = Wayland_VideoQuit;
gabomdq@8062
   166
    device->SetDisplayMode = Wayland_SetDisplayMode;
gabomdq@8062
   167
    device->GetDisplayModes = Wayland_GetDisplayModes;
gabomdq@8062
   168
    device->GetWindowWMInfo = Wayland_GetWindowWMInfo;
gabomdq@8062
   169
gabomdq@8062
   170
    device->PumpEvents = Wayland_PumpEvents;
gabomdq@8062
   171
gabomdq@8062
   172
    device->GL_SwapWindow = Wayland_GLES_SwapWindow;
gabomdq@8062
   173
    device->GL_GetSwapInterval = Wayland_GLES_GetSwapInterval;
gabomdq@8062
   174
    device->GL_SetSwapInterval = Wayland_GLES_SetSwapInterval;
dos@12844
   175
    device->GL_GetDrawableSize = Wayland_GLES_GetDrawableSize;
gabomdq@8062
   176
    device->GL_MakeCurrent = Wayland_GLES_MakeCurrent;
gabomdq@8062
   177
    device->GL_CreateContext = Wayland_GLES_CreateContext;
gabomdq@8062
   178
    device->GL_LoadLibrary = Wayland_GLES_LoadLibrary;
gabomdq@8062
   179
    device->GL_UnloadLibrary = Wayland_GLES_UnloadLibrary;
gabomdq@8062
   180
    device->GL_GetProcAddress = Wayland_GLES_GetProcAddress;
gabomdq@8062
   181
    device->GL_DeleteContext = Wayland_GLES_DeleteContext;
gabomdq@8062
   182
slouken@11383
   183
    device->CreateSDLWindow = Wayland_CreateWindow;
gabomdq@8062
   184
    device->ShowWindow = Wayland_ShowWindow;
gabomdq@8062
   185
    device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
slouken@10492
   186
    device->MaximizeWindow = Wayland_MaximizeWindow;
slouken@10492
   187
    device->RestoreWindow = Wayland_RestoreWindow;
icculus@12367
   188
    device->SetWindowBordered = Wayland_SetWindowBordered;
gabomdq@8062
   189
    device->SetWindowSize = Wayland_SetWindowSize;
slouken@10492
   190
    device->SetWindowTitle = Wayland_SetWindowTitle;
gabomdq@8062
   191
    device->DestroyWindow = Wayland_DestroyWindow;
icculus@9554
   192
    device->SetWindowHitTest = Wayland_SetWindowHitTest;
gabomdq@8062
   193
slouken@10583
   194
    device->SetClipboardText = Wayland_SetClipboardText;
slouken@10583
   195
    device->GetClipboardText = Wayland_GetClipboardText;
slouken@10583
   196
    device->HasClipboardText = Wayland_HasClipboardText;
slouken@10583
   197
slouken@11381
   198
#if SDL_VIDEO_VULKAN
icculus@11365
   199
    device->Vulkan_LoadLibrary = Wayland_Vulkan_LoadLibrary;
icculus@11365
   200
    device->Vulkan_UnloadLibrary = Wayland_Vulkan_UnloadLibrary;
icculus@11365
   201
    device->Vulkan_GetInstanceExtensions = Wayland_Vulkan_GetInstanceExtensions;
icculus@11365
   202
    device->Vulkan_CreateSurface = Wayland_Vulkan_CreateSurface;
dos@12844
   203
    device->Vulkan_GetDrawableSize = Wayland_Vulkan_GetDrawableSize;
icculus@11365
   204
#endif
icculus@11365
   205
gabomdq@8062
   206
    device->free = Wayland_DeleteDevice;
gabomdq@8062
   207
gabomdq@8062
   208
    return device;
gabomdq@8062
   209
}
gabomdq@8062
   210
gabomdq@8062
   211
VideoBootStrap Wayland_bootstrap = {
gabomdq@8062
   212
    WAYLANDVID_DRIVER_NAME, "SDL Wayland video driver",
gabomdq@8062
   213
    Wayland_Available, Wayland_CreateDevice
gabomdq@8062
   214
};
gabomdq@8062
   215
gabomdq@8062
   216
static void
gabomdq@8062
   217
display_handle_geometry(void *data,
gabomdq@8062
   218
                        struct wl_output *output,
gabomdq@8062
   219
                        int x, int y,
gabomdq@8062
   220
                        int physical_width,
gabomdq@8062
   221
                        int physical_height,
gabomdq@8062
   222
                        int subpixel,
gabomdq@8062
   223
                        const char *make,
gabomdq@8062
   224
                        const char *model,
gabomdq@8062
   225
                        int transform)
gabomdq@8062
   226
gabomdq@8062
   227
{
linkmauve@9467
   228
    SDL_VideoDisplay *display = data;
gabomdq@8062
   229
philipp@10187
   230
    display->name = SDL_strdup(model);
gabomdq@8062
   231
}
gabomdq@8062
   232
gabomdq@8062
   233
static void
gabomdq@8062
   234
display_handle_mode(void *data,
linkmauve@9467
   235
                    struct wl_output *output,
gabomdq@8062
   236
                    uint32_t flags,
gabomdq@8062
   237
                    int width,
gabomdq@8062
   238
                    int height,
gabomdq@8062
   239
                    int refresh)
gabomdq@8062
   240
{
dos@12844
   241
    SDL_DisplayMode mode;
linkmauve@9467
   242
    SDL_VideoDisplay *display = data;
gabomdq@8062
   243
gabomdq@8062
   244
    SDL_zero(mode);
slouken@10744
   245
    mode.format = SDL_PIXELFORMAT_RGB888;
gabomdq@8062
   246
    mode.w = width;
gabomdq@8062
   247
    mode.h = height;
linkmauve@9467
   248
    mode.refresh_rate = refresh / 1000; // mHz to Hz
dos@12844
   249
    mode.driverdata = ((SDL_WaylandOutputData*)display->driverdata)->output;
linkmauve@9467
   250
    SDL_AddDisplayMode(display, &mode);
gabomdq@8062
   251
gabomdq@8062
   252
    if (flags & WL_OUTPUT_MODE_CURRENT) {
linkmauve@9467
   253
        display->current_mode = mode;
linkmauve@9467
   254
        display->desktop_mode = mode;
gabomdq@8062
   255
    }
gabomdq@8062
   256
}
gabomdq@8062
   257
linkmauve@9467
   258
static void
linkmauve@9467
   259
display_handle_done(void *data,
linkmauve@9467
   260
                    struct wl_output *output)
linkmauve@9467
   261
{
dos@12844
   262
    /* !!! FIXME: this will fail on any further property changes! */
linkmauve@9467
   263
    SDL_VideoDisplay *display = data;
linkmauve@9467
   264
    SDL_AddVideoDisplay(display);
dos@12844
   265
    wl_output_set_user_data(output, display->driverdata);
linkmauve@9467
   266
    SDL_free(display->name);
linkmauve@9467
   267
    SDL_free(display);
linkmauve@9467
   268
}
linkmauve@9467
   269
linkmauve@9467
   270
static void
linkmauve@9467
   271
display_handle_scale(void *data,
linkmauve@9467
   272
                     struct wl_output *output,
linkmauve@9467
   273
                     int32_t factor)
linkmauve@9467
   274
{
dos@12844
   275
    SDL_VideoDisplay *display = data;
dos@12844
   276
    ((SDL_WaylandOutputData*)display->driverdata)->scale_factor = factor;
linkmauve@9467
   277
}
linkmauve@9467
   278
gabomdq@8062
   279
static const struct wl_output_listener output_listener = {
gabomdq@8062
   280
    display_handle_geometry,
linkmauve@9467
   281
    display_handle_mode,
linkmauve@9467
   282
    display_handle_done,
linkmauve@9467
   283
    display_handle_scale
gabomdq@8062
   284
};
gabomdq@8062
   285
gabomdq@8062
   286
static void
linkmauve@9467
   287
Wayland_add_display(SDL_VideoData *d, uint32_t id)
gabomdq@8062
   288
{
icculus@9472
   289
    struct wl_output *output;
dos@12844
   290
    SDL_WaylandOutputData *data;
linkmauve@9467
   291
    SDL_VideoDisplay *display = SDL_malloc(sizeof *display);
linkmauve@9467
   292
    if (!display) {
linkmauve@9467
   293
        SDL_OutOfMemory();
linkmauve@9467
   294
        return;
linkmauve@9467
   295
    }
linkmauve@9467
   296
    SDL_zero(*display);
gabomdq@8062
   297
icculus@9472
   298
    output = wl_registry_bind(d->registry, id, &wl_output_interface, 2);
linkmauve@9467
   299
    if (!output) {
linkmauve@9467
   300
        SDL_SetError("Failed to retrieve output.");
philipp@10618
   301
        SDL_free(display);
linkmauve@9467
   302
        return;
linkmauve@9467
   303
    }
dos@12844
   304
    data = SDL_malloc(sizeof *data);
dos@12844
   305
    data->output = output;
dos@12844
   306
    data->scale_factor = 1.0;
dos@12844
   307
    display->driverdata = data;
gabomdq@8062
   308
linkmauve@9467
   309
    wl_output_add_listener(output, &output_listener, display);
linkmauve@9467
   310
}
gabomdq@8062
   311
gabomdq@8082
   312
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
gabomdq@8082
   313
static void
gabomdq@8082
   314
windowmanager_hints(void *data, struct qt_windowmanager *qt_windowmanager,
gabomdq@8082
   315
        int32_t show_is_fullscreen)
gabomdq@8082
   316
{
gabomdq@8082
   317
}
gabomdq@8082
   318
gabomdq@8082
   319
static void
gabomdq@8082
   320
windowmanager_quit(void *data, struct qt_windowmanager *qt_windowmanager)
gabomdq@8082
   321
{
gabomdq@8082
   322
    SDL_SendQuit();
gabomdq@8082
   323
}
gabomdq@8082
   324
gabomdq@8082
   325
static const struct qt_windowmanager_listener windowmanager_listener = {
gabomdq@8082
   326
    windowmanager_hints,
gabomdq@8082
   327
    windowmanager_quit,
gabomdq@8082
   328
};
gabomdq@8082
   329
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
gabomdq@8082
   330
icculus@11848
   331
icculus@11848
   332
static void
icculus@11848
   333
handle_ping_zxdg_shell(void *data, struct zxdg_shell_v6 *zxdg, uint32_t serial)
icculus@11848
   334
{
icculus@11848
   335
    zxdg_shell_v6_pong(zxdg, serial);
icculus@11848
   336
}
icculus@11848
   337
icculus@11848
   338
static const struct zxdg_shell_v6_listener shell_listener_zxdg = {
icculus@11848
   339
    handle_ping_zxdg_shell
icculus@11848
   340
};
icculus@11848
   341
icculus@11848
   342
gabomdq@8062
   343
static void
icculus@12033
   344
handle_ping_xdg_wm_base(void *data, struct xdg_wm_base *xdg, uint32_t serial)
icculus@12033
   345
{
icculus@12033
   346
    xdg_wm_base_pong(xdg, serial);
icculus@12033
   347
}
icculus@12033
   348
icculus@12033
   349
static const struct xdg_wm_base_listener shell_listener_xdg = {
icculus@12033
   350
    handle_ping_xdg_wm_base
icculus@12033
   351
};
icculus@12033
   352
icculus@12033
   353
icculus@12033
   354
static void
gabomdq@8062
   355
display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
linkmauve@9467
   356
                      const char *interface, uint32_t version)
gabomdq@8062
   357
{
gabomdq@8062
   358
    SDL_VideoData *d = data;
linkmauve@9467
   359
icculus@12367
   360
    /*printf("WAYLAND INTERFACE: %s\n", interface);*/
icculus@12367
   361
gabomdq@8062
   362
    if (strcmp(interface, "wl_compositor") == 0) {
dos@12844
   363
        d->compositor = wl_registry_bind(d->registry, id, &wl_compositor_interface, SDL_min(3, version));
gabomdq@8062
   364
    } else if (strcmp(interface, "wl_output") == 0) {
linkmauve@9467
   365
        Wayland_add_display(d, id);
gabomdq@8062
   366
    } else if (strcmp(interface, "wl_seat") == 0) {
icculus@13701
   367
        Wayland_display_add_input(d, id, version);
icculus@12033
   368
    } else if (strcmp(interface, "xdg_wm_base") == 0) {
icculus@12033
   369
        d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, 1);
icculus@12033
   370
        xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
icculus@11848
   371
    } else if (strcmp(interface, "zxdg_shell_v6") == 0) {
icculus@11848
   372
        d->shell.zxdg = wl_registry_bind(d->registry, id, &zxdg_shell_v6_interface, 1);
icculus@11848
   373
        zxdg_shell_v6_add_listener(d->shell.zxdg, &shell_listener_zxdg, NULL);
gabomdq@8062
   374
    } else if (strcmp(interface, "wl_shell") == 0) {
icculus@11848
   375
        d->shell.wl = wl_registry_bind(d->registry, id, &wl_shell_interface, 1);
gabomdq@8062
   376
    } else if (strcmp(interface, "wl_shm") == 0) {
gabomdq@8062
   377
        d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
gabomdq@8104
   378
        d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm);
slouken@10304
   379
    } else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
slouken@10304
   380
        Wayland_display_add_relative_pointer_manager(d, id);
slouken@10304
   381
    } else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
slouken@10304
   382
        Wayland_display_add_pointer_constraints(d, id);
slouken@10583
   383
    } else if (strcmp(interface, "wl_data_device_manager") == 0) {
mforney@13391
   384
        d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, SDL_min(3, version));
dos@12426
   385
    } else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
dos@12426
   386
        d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, 1);
icculus@12367
   387
    } else if (strcmp(interface, "org_kde_kwin_server_decoration_manager") == 0) {
icculus@12367
   388
        d->kwin_server_decoration_manager = wl_registry_bind(d->registry, id, &org_kde_kwin_server_decoration_manager_interface, 1);
icculus@11848
   389
gabomdq@8082
   390
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
gabomdq@8082
   391
    } else if (strcmp(interface, "qt_touch_extension") == 0) {
gabomdq@8082
   392
        Wayland_touch_create(d, id);
gabomdq@8082
   393
    } else if (strcmp(interface, "qt_surface_extension") == 0) {
gabomdq@8082
   394
        d->surface_extension = wl_registry_bind(registry, id,
gabomdq@8082
   395
                &qt_surface_extension_interface, 1);
gabomdq@8082
   396
    } else if (strcmp(interface, "qt_windowmanager") == 0) {
gabomdq@8082
   397
        d->windowmanager = wl_registry_bind(registry, id,
gabomdq@8082
   398
                &qt_windowmanager_interface, 1);
gabomdq@8082
   399
        qt_windowmanager_add_listener(d->windowmanager, &windowmanager_listener, d);
gabomdq@8082
   400
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
gabomdq@8062
   401
    }
gabomdq@8062
   402
}
gabomdq@8062
   403
sylvain@12623
   404
static void
sylvain@12623
   405
display_remove_global(void *data, struct wl_registry *registry, uint32_t id) {}
sylvain@12623
   406
gabomdq@8062
   407
static const struct wl_registry_listener registry_listener = {
brandon@11552
   408
    display_handle_global,
sylvain@12623
   409
    display_remove_global
gabomdq@8062
   410
};
gabomdq@8062
   411
gabomdq@8062
   412
int
gabomdq@8062
   413
Wayland_VideoInit(_THIS)
gabomdq@8062
   414
{
slouken@13000
   415
    SDL_VideoData *data = SDL_calloc(1, sizeof(*data));
gabomdq@8062
   416
    if (data == NULL)
philipp@9484
   417
        return SDL_OutOfMemory();
gabomdq@8062
   418
gabomdq@8062
   419
    _this->driverdata = data;
gabomdq@8062
   420
slouken@10530
   421
    data->xkb_context = WAYLAND_xkb_context_new(0);
slouken@10530
   422
    if (!data->xkb_context) {
slouken@10530
   423
        return SDL_SetError("Failed to create XKB context");
slouken@10530
   424
    }
slouken@10530
   425
gabomdq@8104
   426
    data->display = WAYLAND_wl_display_connect(NULL);
gabomdq@8062
   427
    if (data->display == NULL) {
philipp@9484
   428
        return SDL_SetError("Failed to connect to a Wayland display");
gabomdq@8062
   429
    }
gabomdq@8062
   430
gabomdq@8062
   431
    data->registry = wl_display_get_registry(data->display);
linkmauve@9467
   432
    if (data->registry == NULL) {
philipp@9484
   433
        return SDL_SetError("Failed to get the Wayland registry");
gabomdq@8104
   434
    }
linkmauve@9467
   435
gabomdq@8062
   436
    wl_registry_add_listener(data->registry, &registry_listener, data);
gabomdq@8062
   437
linkmauve@9467
   438
    // First roundtrip to receive all registry objects.
icculus@9476
   439
    WAYLAND_wl_display_roundtrip(data->display);
linkmauve@9467
   440
linkmauve@9467
   441
    // Second roundtrip to receive all output events.
icculus@9476
   442
    WAYLAND_wl_display_roundtrip(data->display);
gabomdq@8062
   443
linkmauve@9467
   444
    Wayland_InitMouse();
gabomdq@8062
   445
hadess@10302
   446
    /* Get the surface class name, usually the name of the application */
hadess@10302
   447
    data->classname = get_classname();
hadess@10302
   448
gabomdq@8104
   449
    WAYLAND_wl_display_flush(data->display);
gabomdq@8062
   450
gabomdq@8062
   451
    return 0;
gabomdq@8062
   452
}
gabomdq@8062
   453
gabomdq@8062
   454
static void
gabomdq@8062
   455
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display)
gabomdq@8062
   456
{
linkmauve@9467
   457
    // Nothing to do here, everything was already done in the wl_output
linkmauve@9467
   458
    // callbacks.
gabomdq@8062
   459
}
gabomdq@8062
   460
gabomdq@8062
   461
static int
gabomdq@8062
   462
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
gabomdq@8062
   463
{
icculus@9469
   464
    return SDL_Unsupported();
gabomdq@8062
   465
}
gabomdq@8062
   466
gabomdq@8062
   467
void
gabomdq@8062
   468
Wayland_VideoQuit(_THIS)
gabomdq@8062
   469
{
gabomdq@8062
   470
    SDL_VideoData *data = _this->driverdata;
slouken@11814
   471
    int i, j;
gabomdq@8062
   472
gabomdq@8062
   473
    Wayland_FiniMouse ();
gabomdq@8062
   474
linkmauve@9467
   475
    for (i = 0; i < _this->num_displays; ++i) {
linkmauve@9467
   476
        SDL_VideoDisplay *display = &_this->displays[i];
dos@12844
   477
dos@12844
   478
        wl_output_destroy(((SDL_WaylandOutputData*)display->driverdata)->output);
dos@12844
   479
        SDL_free(display->driverdata);
linkmauve@9467
   480
        display->driverdata = NULL;
slouken@11814
   481
slouken@11814
   482
        for (j = display->num_display_modes; j--;) {
slouken@11814
   483
            display->display_modes[j].driverdata = NULL;
slouken@11814
   484
        }
slouken@11814
   485
        display->desktop_mode.driverdata = NULL;
linkmauve@9467
   486
    }
gabomdq@8062
   487
gabomdq@8062
   488
    Wayland_display_destroy_input(data);
slouken@10304
   489
    Wayland_display_destroy_pointer_constraints(data);
slouken@10304
   490
    Wayland_display_destroy_relative_pointer_manager(data);
gabomdq@8062
   491
gabomdq@8062
   492
    if (data->xkb_context) {
gabomdq@8104
   493
        WAYLAND_xkb_context_unref(data->xkb_context);
gabomdq@8062
   494
        data->xkb_context = NULL;
gabomdq@8062
   495
    }
gabomdq@8082
   496
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
gabomdq@8082
   497
    if (data->windowmanager)
gabomdq@8082
   498
        qt_windowmanager_destroy(data->windowmanager);
gabomdq@8082
   499
gabomdq@8082
   500
    if (data->surface_extension)
gabomdq@8082
   501
        qt_surface_extension_destroy(data->surface_extension);
gabomdq@8082
   502
gabomdq@8082
   503
    Wayland_touch_destroy(data);
gabomdq@8082
   504
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
gabomdq@8062
   505
gabomdq@8062
   506
    if (data->shm)
gabomdq@8062
   507
        wl_shm_destroy(data->shm);
gabomdq@8062
   508
gabomdq@8062
   509
    if (data->cursor_theme)
gabomdq@8104
   510
        WAYLAND_wl_cursor_theme_destroy(data->cursor_theme);
gabomdq@8062
   511
icculus@11848
   512
    if (data->shell.wl)
icculus@11848
   513
        wl_shell_destroy(data->shell.wl);
icculus@11848
   514
icculus@12033
   515
    if (data->shell.xdg)
icculus@12033
   516
        xdg_wm_base_destroy(data->shell.xdg);
icculus@12033
   517
icculus@11848
   518
    if (data->shell.zxdg)
icculus@11848
   519
        zxdg_shell_v6_destroy(data->shell.zxdg);
gabomdq@8062
   520
gabomdq@8062
   521
    if (data->compositor)
gabomdq@8062
   522
        wl_compositor_destroy(data->compositor);
gabomdq@8062
   523
linkmauve@9467
   524
    if (data->registry)
linkmauve@9467
   525
        wl_registry_destroy(data->registry);
linkmauve@9467
   526
gabomdq@8062
   527
    if (data->display) {
gabomdq@8104
   528
        WAYLAND_wl_display_flush(data->display);
gabomdq@8104
   529
        WAYLAND_wl_display_disconnect(data->display);
gabomdq@8062
   530
    }
gabomdq@8062
   531
hadess@10302
   532
    SDL_free(data->classname);
philipp@11030
   533
    SDL_free(data);
gabomdq@8062
   534
    _this->driverdata = NULL;
gabomdq@8062
   535
}
gabomdq@8062
   536
icculus@8116
   537
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
icculus@8116
   538
gabomdq@8062
   539
/* vi: set ts=4 sw=4 expandtab: */