src/video/wayland/SDL_waylandwindow.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 01 Sep 2016 01:26:56 -0700
changeset 10304 ee83e0b4a36f
parent 10302 729eff9ee77a
child 10492 786e10ab72d8
permissions -rw-r--r--
wayland: Add support for relative mouse mode, by Jonas Ådahl <jadahl@gmail.com>

Generate the C protocol files from the protocol XML files installed by
wayland-protocols, and use them to implement support for relative pointer
motions and pointer locking.

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