src/video/wayland/SDL_waylandwindow.c
author Bastien Nocera <hadess@hadess.net>
Thu, 01 Sep 2016 01:22:58 -0700
changeset 10302 729eff9ee77a
parent 9998 f67cf37e9cd4
child 10304 ee83e0b4a36f
permissions -rw-r--r--
Wayland: Set "class" for each window we create
This will be used by Wayland compositors to match the application ID and
.desktop file to the SDL window(s).

Applications can set the SDL_VIDEO_WAYLAND_WMCLASS environemnt variable
early in the process to override using the binary name as a fallback.

Note that we also support the SDL_VIDEO_X11_WMCLASS in the Wayland
backend so that if a program correctly associated the desktop file with
the window under X11, only a newer SDL would be needed for it to work
under Wayland.

https://bugzilla.libsdl.org/show_bug.cgi?id=3376
gabomdq@8062
     1
/*
gabomdq@8062
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 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"
gabomdq@8062
    29
#include "SDL_waylandwindow.h"
gabomdq@8062
    30
#include "SDL_waylandvideo.h"
gabomdq@8082
    31
#include "SDL_waylandtouch.h"
arnej@9362
    32
#include "SDL_waylanddyn.h"
gabomdq@8062
    33
gabomdq@8062
    34
static void
gabomdq@8062
    35
handle_ping(void *data, struct wl_shell_surface *shell_surface,
gabomdq@8062
    36
            uint32_t serial)
gabomdq@8062
    37
{
gabomdq@8062
    38
    wl_shell_surface_pong(shell_surface, serial);
gabomdq@8062
    39
}
gabomdq@8062
    40
gabomdq@8062
    41
static void
gabomdq@8062
    42
handle_configure(void *data, struct wl_shell_surface *shell_surface,
gabomdq@8062
    43
                 uint32_t edges, int32_t width, int32_t height)
gabomdq@8062
    44
{
gabomdq@8766
    45
    SDL_WindowData *wind = (SDL_WindowData *)data;
gabomdq@8766
    46
    SDL_Window *window = wind->sdlwindow;
gabomdq@8766
    47
    struct wl_region *region;
gabomdq@8766
    48
gabomdq@8766
    49
    window->w = width;
gabomdq@8766
    50
    window->h = height;
gabomdq@8766
    51
    WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
gabomdq@8766
    52
gabomdq@8766
    53
    region = wl_compositor_create_region(wind->waylandData->compositor);
gabomdq@8766
    54
    wl_region_add(region, 0, 0, window->w, window->h);
gabomdq@8766
    55
    wl_surface_set_opaque_region(wind->surface, region);
gabomdq@8766
    56
    wl_region_destroy(region);
gabomdq@8766
    57
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
gabomdq@8062
    58
}
gabomdq@8062
    59
gabomdq@8062
    60
static void
gabomdq@8062
    61
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
gabomdq@8062
    62
{
gabomdq@8062
    63
}
gabomdq@8062
    64
gabomdq@8062
    65
static const struct wl_shell_surface_listener shell_surface_listener = {
gabomdq@8062
    66
    handle_ping,
gabomdq@8062
    67
    handle_configure,
gabomdq@8062
    68
    handle_popup_done
gabomdq@8062
    69
};
gabomdq@8062
    70
gabomdq@8082
    71
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
gabomdq@8082
    72
static void
gabomdq@8082
    73
handle_onscreen_visibility(void *data,
gabomdq@8082
    74
        struct qt_extended_surface *qt_extended_surface, int32_t visible)
gabomdq@8082
    75
{
gabomdq@8082
    76
}
gabomdq@8082
    77
gabomdq@8082
    78
static void
gabomdq@8082
    79
handle_set_generic_property(void *data,
gabomdq@8082
    80
        struct qt_extended_surface *qt_extended_surface, const char *name,
gabomdq@8082
    81
        struct wl_array *value)
gabomdq@8082
    82
{
gabomdq@8082
    83
}
gabomdq@8082
    84
gabomdq@8082
    85
static void
gabomdq@8082
    86
handle_close(void *data, struct qt_extended_surface *qt_extended_surface)
gabomdq@8082
    87
{
gabomdq@8082
    88
    SDL_WindowData *window = (SDL_WindowData *)data;
gabomdq@8082
    89
    SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
gabomdq@8082
    90
}
gabomdq@8082
    91
gabomdq@8082
    92
static const struct qt_extended_surface_listener extended_surface_listener = {
gabomdq@8082
    93
    handle_onscreen_visibility,
gabomdq@8082
    94
    handle_set_generic_property,
gabomdq@8082
    95
    handle_close,
gabomdq@8082
    96
};
gabomdq@8082
    97
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
gabomdq@8082
    98
gabomdq@8062
    99
SDL_bool
gabomdq@8062
   100
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
gabomdq@8062
   101
{
gabomdq@8062
   102
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
gabomdq@8062
   103
gabomdq@8062
   104
    info->info.wl.display = data->waylandData->display;
gabomdq@8062
   105
    info->info.wl.surface = data->surface;
gabomdq@8062
   106
    info->info.wl.shell_surface = data->shell_surface;
gabomdq@8062
   107
    info->subsystem = SDL_SYSWM_WAYLAND;
gabomdq@8062
   108
gabomdq@8062
   109
    return SDL_TRUE;
gabomdq@8062
   110
}
gabomdq@8062
   111
icculus@9554
   112
int
icculus@9554
   113
Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
icculus@9554
   114
{
icculus@9554
   115
    return 0;  /* just succeed, the real work is done elsewhere. */
icculus@9554
   116
}
icculus@9554
   117
gabomdq@8062
   118
void Wayland_ShowWindow(_THIS, SDL_Window *window)
gabomdq@8062
   119
{
gabomdq@8062
   120
    SDL_WindowData *wind = window->driverdata;
gabomdq@8062
   121
gabomdq@8062
   122
    if (window->flags & SDL_WINDOW_FULLSCREEN)
gabomdq@8062
   123
        wl_shell_surface_set_fullscreen(wind->shell_surface,
gabomdq@8062
   124
                                        WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
linkmauve@9468
   125
                                        0, (struct wl_output *)window->fullscreen_mode.driverdata);
gabomdq@8062
   126
    else
gabomdq@8062
   127
        wl_shell_surface_set_toplevel(wind->shell_surface);
gabomdq@8062
   128
gabomdq@8104
   129
    WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
gabomdq@8062
   130
}
gabomdq@8062
   131
gabomdq@8062
   132
void
gabomdq@8062
   133
Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
gabomdq@8062
   134
                            SDL_VideoDisplay * _display, SDL_bool fullscreen)
gabomdq@8062
   135
{
gabomdq@8062
   136
    SDL_WindowData *wind = window->driverdata;
gabomdq@8062
   137
gabomdq@8062
   138
    if (fullscreen)
gabomdq@8062
   139
        wl_shell_surface_set_fullscreen(wind->shell_surface,
gabomdq@8062
   140
                                        WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE,
linkmauve@9468
   141
                                        0, (struct wl_output *)_display->driverdata);
gabomdq@8062
   142
    else
gabomdq@8062
   143
        wl_shell_surface_set_toplevel(wind->shell_surface);
gabomdq@8062
   144
gabomdq@8104
   145
    WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
gabomdq@8062
   146
}
gabomdq@8062
   147
gabomdq@8062
   148
int Wayland_CreateWindow(_THIS, SDL_Window *window)
gabomdq@8062
   149
{
gabomdq@8062
   150
    SDL_WindowData *data;
gabomdq@8062
   151
    SDL_VideoData *c;
gabomdq@8062
   152
    struct wl_region *region;
gabomdq@8062
   153
gabomdq@8062
   154
    data = calloc(1, sizeof *data);
gabomdq@8062
   155
    if (data == NULL)
philipp@9483
   156
        return SDL_OutOfMemory();
gabomdq@8062
   157
gabomdq@8062
   158
    c = _this->driverdata;
gabomdq@8062
   159
    window->driverdata = data;
gabomdq@8062
   160
gabomdq@8062
   161
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
gabomdq@8062
   162
        SDL_GL_LoadLibrary(NULL);
gabomdq@8062
   163
        window->flags |= SDL_WINDOW_OPENGL;
gabomdq@8062
   164
    }
gabomdq@8062
   165
gabomdq@8062
   166
    if (window->x == SDL_WINDOWPOS_UNDEFINED) {
gabomdq@8062
   167
        window->x = 0;
gabomdq@8062
   168
    }
gabomdq@8062
   169
    if (window->y == SDL_WINDOWPOS_UNDEFINED) {
gabomdq@8062
   170
        window->y = 0;
gabomdq@8062
   171
    }
gabomdq@8062
   172
gabomdq@8062
   173
    data->waylandData = c;
gabomdq@8062
   174
    data->sdlwindow = window;
gabomdq@8062
   175
gabomdq@8062
   176
    data->surface =
gabomdq@8062
   177
        wl_compositor_create_surface(c->compositor);
gabomdq@8062
   178
    wl_surface_set_user_data(data->surface, data);
gabomdq@8062
   179
    data->shell_surface = wl_shell_get_shell_surface(c->shell,
gabomdq@8062
   180
                                                     data->surface);
hadess@10302
   181
    wl_shell_surface_set_class (data->shell_surface, c->classname);
gabomdq@8082
   182
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH    
gabomdq@8082
   183
    if (c->surface_extension) {
gabomdq@8082
   184
        data->extended_surface = qt_surface_extension_get_extended_surface(
gabomdq@8082
   185
                c->surface_extension, data->surface);
gabomdq@8082
   186
    }
gabomdq@8082
   187
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
m@8712
   188
gabomdq@8104
   189
    data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
gabomdq@8062
   190
                                            window->w, window->h);
gabomdq@8062
   191
gabomdq@8062
   192
    /* Create the GLES window surface */
gabomdq@8062
   193
    data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
gabomdq@8062
   194
    
gabomdq@8062
   195
    if (data->egl_surface == EGL_NO_SURFACE) {
philipp@9543
   196
        return SDL_SetError("failed to create a window surface");
gabomdq@8062
   197
    }
gabomdq@8062
   198
gabomdq@8062
   199
    if (data->shell_surface) {
gabomdq@8062
   200
        wl_shell_surface_set_user_data(data->shell_surface, data);
gabomdq@8062
   201
        wl_shell_surface_add_listener(data->shell_surface,
gabomdq@8062
   202
                                      &shell_surface_listener, data);
gabomdq@8062
   203
    }
gabomdq@8062
   204
gabomdq@8082
   205
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
gabomdq@8082
   206
    if (data->extended_surface) {
gabomdq@8082
   207
        qt_extended_surface_set_user_data(data->extended_surface, data);
gabomdq@8082
   208
        qt_extended_surface_add_listener(data->extended_surface,
gabomdq@8082
   209
                                         &extended_surface_listener, data);
gabomdq@8082
   210
    }
gabomdq@8082
   211
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
gabomdq@8082
   212
gabomdq@8062
   213
    region = wl_compositor_create_region(c->compositor);
gabomdq@8062
   214
    wl_region_add(region, 0, 0, window->w, window->h);
gabomdq@8062
   215
    wl_surface_set_opaque_region(data->surface, region);
gabomdq@8062
   216
    wl_region_destroy(region);
gabomdq@8062
   217
gabomdq@8104
   218
    WAYLAND_wl_display_flush(c->display);
gabomdq@8062
   219
gabomdq@8062
   220
    return 0;
gabomdq@8062
   221
}
gabomdq@8062
   222
gabomdq@8062
   223
void Wayland_SetWindowSize(_THIS, SDL_Window * window)
gabomdq@8062
   224
{
gabomdq@8062
   225
    SDL_VideoData *data = _this->driverdata;
gabomdq@8062
   226
    SDL_WindowData *wind = window->driverdata;
gabomdq@8062
   227
    struct wl_region *region;
gabomdq@8062
   228
gabomdq@8104
   229
    WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
gabomdq@8062
   230
gabomdq@8104
   231
    region =wl_compositor_create_region(data->compositor);
gabomdq@8062
   232
    wl_region_add(region, 0, 0, window->w, window->h);
gabomdq@8062
   233
    wl_surface_set_opaque_region(wind->surface, region);
gabomdq@8062
   234
    wl_region_destroy(region);
gabomdq@8062
   235
}
gabomdq@8062
   236
gabomdq@8062
   237
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
gabomdq@8062
   238
{
gabomdq@8062
   239
    SDL_VideoData *data = _this->driverdata;
gabomdq@8062
   240
    SDL_WindowData *wind = window->driverdata;
gabomdq@8062
   241
gabomdq@8062
   242
    if (data) {
gabomdq@8062
   243
        SDL_EGL_DestroySurface(_this, wind->egl_surface);
gabomdq@8104
   244
        WAYLAND_wl_egl_window_destroy(wind->egl_window);
gabomdq@8062
   245
gabomdq@8062
   246
        if (wind->shell_surface)
gabomdq@8062
   247
            wl_shell_surface_destroy(wind->shell_surface);
gabomdq@8062
   248
gabomdq@8082
   249
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
gabomdq@8082
   250
        if (wind->extended_surface)
gabomdq@8082
   251
            qt_extended_surface_destroy(wind->extended_surface);
gabomdq@8082
   252
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
gabomdq@8062
   253
        wl_surface_destroy(wind->surface);
gabomdq@8062
   254
gabomdq@8062
   255
        SDL_free(wind);
gabomdq@8104
   256
        WAYLAND_wl_display_flush(data->display);
gabomdq@8062
   257
    }
slouken@8978
   258
    window->driverdata = NULL;
gabomdq@8062
   259
}
gabomdq@8062
   260
icculus@8116
   261
#endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
icculus@8116
   262
gabomdq@8062
   263
/* vi: set ts=4 sw=4 expandtab: */