src/video/wayland/SDL_waylandevents.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 01 Jan 2017 18:33:28 -0800
changeset 10737 3406a0f8b041
parent 10583 974f8ebcb819
child 11296 44853f387017
permissions -rw-r--r--
Updated copyright for 2017
gabomdq@8062
     1
/*
gabomdq@8062
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 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_stdinc.h"
gabomdq@8062
    27
#include "SDL_assert.h"
slouken@10304
    28
#include "SDL_log.h"
gabomdq@8062
    29
gabomdq@8062
    30
#include "../../events/SDL_sysevents.h"
gabomdq@8062
    31
#include "../../events/SDL_events_c.h"
gabomdq@8062
    32
#include "../../events/scancodes_xfree86.h"
gabomdq@8062
    33
gabomdq@8062
    34
#include "SDL_waylandvideo.h"
gabomdq@8062
    35
#include "SDL_waylandevents_c.h"
gabomdq@8062
    36
#include "SDL_waylandwindow.h"
gabomdq@8062
    37
gabomdq@8104
    38
#include "SDL_waylanddyn.h"
gabomdq@8104
    39
slouken@10304
    40
#include "pointer-constraints-unstable-v1-client-protocol.h"
slouken@10304
    41
#include "relative-pointer-unstable-v1-client-protocol.h"
slouken@10304
    42
gabomdq@8062
    43
#include <linux/input.h>
gabomdq@8062
    44
#include <sys/select.h>
gabomdq@8062
    45
#include <sys/mman.h>
gabomdq@8062
    46
#include <poll.h>
gabomdq@8062
    47
#include <unistd.h>
gabomdq@8062
    48
#include <xkbcommon/xkbcommon.h>
gabomdq@8062
    49
gabomdq@8062
    50
struct SDL_WaylandInput {
gabomdq@8062
    51
    SDL_VideoData *display;
gabomdq@8062
    52
    struct wl_seat *seat;
gabomdq@8062
    53
    struct wl_pointer *pointer;
gabomdq@8062
    54
    struct wl_keyboard *keyboard;
slouken@10583
    55
    SDL_WaylandDataDevice *data_device;
slouken@10304
    56
    struct zwp_relative_pointer_v1 *relative_pointer;
gabomdq@8062
    57
    SDL_WindowData *pointer_focus;
gabomdq@8062
    58
    SDL_WindowData *keyboard_focus;
gabomdq@8062
    59
icculus@9554
    60
    /* Last motion location */
icculus@9554
    61
    wl_fixed_t sx_w;
icculus@9554
    62
    wl_fixed_t sy_w;
slouken@10304
    63
slouken@10304
    64
    double dx_frac;
slouken@10304
    65
    double dy_frac;
slouken@10304
    66
gabomdq@8062
    67
    struct {
gabomdq@8062
    68
        struct xkb_keymap *keymap;
gabomdq@8062
    69
        struct xkb_state *state;
gabomdq@8062
    70
    } xkb;
gabomdq@8062
    71
};
gabomdq@8062
    72
gabomdq@8062
    73
void
gabomdq@8062
    74
Wayland_PumpEvents(_THIS)
gabomdq@8062
    75
{
gabomdq@8062
    76
    SDL_VideoData *d = _this->driverdata;
gabomdq@8062
    77
    struct pollfd pfd[1];
gabomdq@8062
    78
gabomdq@8104
    79
    pfd[0].fd = WAYLAND_wl_display_get_fd(d->display);
gabomdq@8062
    80
    pfd[0].events = POLLIN;
gabomdq@8062
    81
    poll(pfd, 1, 0);
gabomdq@8062
    82
gabomdq@8062
    83
    if (pfd[0].revents & POLLIN)
gabomdq@8104
    84
        WAYLAND_wl_display_dispatch(d->display);
gabomdq@8062
    85
    else
gabomdq@8104
    86
        WAYLAND_wl_display_dispatch_pending(d->display);
gabomdq@8062
    87
}
gabomdq@8062
    88
gabomdq@8062
    89
static void
gabomdq@8062
    90
pointer_handle_enter(void *data, struct wl_pointer *pointer,
gabomdq@8062
    91
                     uint32_t serial, struct wl_surface *surface,
gabomdq@8062
    92
                     wl_fixed_t sx_w, wl_fixed_t sy_w)
gabomdq@8062
    93
{
gabomdq@8062
    94
    struct SDL_WaylandInput *input = data;
gabomdq@8062
    95
    SDL_WindowData *window;
gabomdq@8062
    96
gabomdq@8062
    97
    if (!surface) {
gabomdq@8062
    98
        /* enter event for a window we've just destroyed */
gabomdq@8062
    99
        return;
gabomdq@8062
   100
    }
gabomdq@8135
   101
    
gabomdq@8135
   102
    /* This handler will be called twice in Wayland 1.4
gabomdq@8135
   103
     * Once for the window surface which has valid user data
gabomdq@8135
   104
     * and again for the mouse cursor surface which does not have valid user data
gabomdq@8135
   105
     * We ignore the later
gabomdq@8135
   106
     */
gabomdq@8062
   107
gabomdq@8135
   108
    window = (SDL_WindowData *)wl_surface_get_user_data(surface);
gabomdq@8135
   109
    
gabomdq@8135
   110
    if (window) {
gabomdq@8135
   111
        input->pointer_focus = window;
gabomdq@8135
   112
        SDL_SetMouseFocus(window->sdlwindow);
gabomdq@8135
   113
    }
gabomdq@8062
   114
}
gabomdq@8062
   115
gabomdq@8062
   116
static void
gabomdq@8062
   117
pointer_handle_leave(void *data, struct wl_pointer *pointer,
gabomdq@8062
   118
                     uint32_t serial, struct wl_surface *surface)
gabomdq@8062
   119
{
gabomdq@8062
   120
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   121
gabomdq@8135
   122
    if (input->pointer_focus) {
gabomdq@8135
   123
        SDL_SetMouseFocus(NULL);
gabomdq@8135
   124
        input->pointer_focus = NULL;
gabomdq@8135
   125
    }
gabomdq@8062
   126
}
gabomdq@8062
   127
gabomdq@8062
   128
static void
gabomdq@8062
   129
pointer_handle_motion(void *data, struct wl_pointer *pointer,
gabomdq@8062
   130
                      uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
gabomdq@8062
   131
{
gabomdq@8062
   132
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   133
    SDL_WindowData *window = input->pointer_focus;
icculus@9554
   134
    input->sx_w = sx_w;
icculus@9554
   135
    input->sy_w = sy_w;
gabomdq@8135
   136
    if (input->pointer_focus) {
icculus@9556
   137
        const int sx = wl_fixed_to_int(sx_w);
icculus@9556
   138
        const int sy = wl_fixed_to_int(sy_w);
gabomdq@8135
   139
        SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
gabomdq@8135
   140
    }
gabomdq@8062
   141
}
gabomdq@8062
   142
icculus@9554
   143
static SDL_bool
icculus@9554
   144
ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
icculus@9554
   145
{
icculus@9554
   146
    SDL_WindowData *window_data = input->pointer_focus;
icculus@9554
   147
    SDL_Window *window = window_data->sdlwindow;
icculus@9554
   148
icculus@9554
   149
    if (window->hit_test) {
icculus@9554
   150
        const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
icculus@9554
   151
        const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
icculus@9555
   152
        static const uint32_t directions[] = {
icculus@9555
   153
            WL_SHELL_SURFACE_RESIZE_TOP_LEFT, WL_SHELL_SURFACE_RESIZE_TOP,
icculus@9555
   154
            WL_SHELL_SURFACE_RESIZE_TOP_RIGHT, WL_SHELL_SURFACE_RESIZE_RIGHT,
icculus@9555
   155
            WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, WL_SHELL_SURFACE_RESIZE_BOTTOM,
icculus@9555
   156
            WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT, WL_SHELL_SURFACE_RESIZE_LEFT
icculus@9555
   157
        };
icculus@9554
   158
        switch (rc) {
icculus@9555
   159
            case SDL_HITTEST_DRAGGABLE:
icculus@9555
   160
                wl_shell_surface_move(window_data->shell_surface, input->seat, serial);
icculus@9555
   161
                return SDL_TRUE;
icculus@9555
   162
icculus@9555
   163
            case SDL_HITTEST_RESIZE_TOPLEFT:
icculus@9555
   164
            case SDL_HITTEST_RESIZE_TOP:
icculus@9555
   165
            case SDL_HITTEST_RESIZE_TOPRIGHT:
icculus@9555
   166
            case SDL_HITTEST_RESIZE_RIGHT:
icculus@9555
   167
            case SDL_HITTEST_RESIZE_BOTTOMRIGHT:
icculus@9555
   168
            case SDL_HITTEST_RESIZE_BOTTOM:
icculus@9555
   169
            case SDL_HITTEST_RESIZE_BOTTOMLEFT:
icculus@9555
   170
            case SDL_HITTEST_RESIZE_LEFT:
icculus@9555
   171
                wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
icculus@9555
   172
                return SDL_TRUE;
icculus@9555
   173
icculus@9555
   174
            default: return SDL_FALSE;
icculus@9554
   175
        }
icculus@9554
   176
    }
icculus@9554
   177
icculus@9555
   178
    return SDL_FALSE;
icculus@9554
   179
}
icculus@9554
   180
gabomdq@8062
   181
static void
slouken@10304
   182
pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
slouken@10304
   183
                             uint32_t time, uint32_t button, uint32_t state_w)
gabomdq@8062
   184
{
gabomdq@8062
   185
    SDL_WindowData *window = input->pointer_focus;
gabomdq@8062
   186
    enum wl_pointer_button_state state = state_w;
gabomdq@8062
   187
    uint32_t sdl_button;
gabomdq@8135
   188
    
gabomdq@8135
   189
    if  (input->pointer_focus) {
gabomdq@8135
   190
        switch (button) {
gabomdq@8135
   191
            case BTN_LEFT:
gabomdq@8135
   192
                sdl_button = SDL_BUTTON_LEFT;
slouken@10304
   193
                if (ProcessHitTest(input, serial)) {
icculus@9554
   194
                    return;  /* don't pass this event on to app. */
icculus@9554
   195
                }
gabomdq@8135
   196
                break;
gabomdq@8135
   197
            case BTN_MIDDLE:
gabomdq@8135
   198
                sdl_button = SDL_BUTTON_MIDDLE;
gabomdq@8135
   199
                break;
gabomdq@8135
   200
            case BTN_RIGHT:
gabomdq@8135
   201
                sdl_button = SDL_BUTTON_RIGHT;
gabomdq@8135
   202
                break;
gabomdq@8135
   203
            case BTN_SIDE:
gabomdq@8135
   204
                sdl_button = SDL_BUTTON_X1;
gabomdq@8135
   205
                break;
gabomdq@8135
   206
            case BTN_EXTRA:
gabomdq@8135
   207
                sdl_button = SDL_BUTTON_X2;
gabomdq@8135
   208
                break;
gabomdq@8135
   209
            default:
gabomdq@8135
   210
                return;
gabomdq@8135
   211
        }
slouken@10583
   212
            
slouken@10583
   213
        Wayland_data_device_set_serial(input->data_device, serial); 
gabomdq@8062
   214
gabomdq@8135
   215
        SDL_SendMouseButton(window->sdlwindow, 0,
gabomdq@8135
   216
                            state ? SDL_PRESSED : SDL_RELEASED, sdl_button);
gabomdq@8062
   217
    }
gabomdq@8062
   218
}
gabomdq@8062
   219
gabomdq@8062
   220
static void
slouken@10304
   221
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
slouken@10304
   222
                      uint32_t time, uint32_t button, uint32_t state_w)
gabomdq@8062
   223
{
gabomdq@8062
   224
    struct SDL_WaylandInput *input = data;
slouken@10304
   225
slouken@10304
   226
    pointer_handle_button_common(input, serial, time, button, state_w);
slouken@10304
   227
}
slouken@10304
   228
slouken@10304
   229
static void
slouken@10304
   230
pointer_handle_axis_common(struct SDL_WaylandInput *input,
slouken@10304
   231
                           uint32_t time, uint32_t axis, wl_fixed_t value)
slouken@10304
   232
{
gabomdq@8062
   233
    SDL_WindowData *window = input->pointer_focus;
gabomdq@8062
   234
    enum wl_pointer_axis a = axis;
gabomdq@8062
   235
    int x, y;
gabomdq@8062
   236
gabomdq@8135
   237
    if (input->pointer_focus) {
gabomdq@8135
   238
        switch (a) {
gabomdq@8135
   239
            case WL_POINTER_AXIS_VERTICAL_SCROLL:
gabomdq@8135
   240
                x = 0;
gabomdq@8135
   241
                y = wl_fixed_to_int(value);
gabomdq@8135
   242
                break;
gabomdq@8135
   243
            case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
gabomdq@8135
   244
                x = wl_fixed_to_int(value);
gabomdq@8135
   245
                y = 0;
gabomdq@8135
   246
                break;
gabomdq@8135
   247
            default:
gabomdq@8135
   248
                return;
gabomdq@8135
   249
        }
gabomdq@8135
   250
urkle@9257
   251
        SDL_SendMouseWheel(window->sdlwindow, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
gabomdq@8062
   252
    }
gabomdq@8062
   253
}
gabomdq@8062
   254
slouken@10304
   255
static void
slouken@10304
   256
pointer_handle_axis(void *data, struct wl_pointer *pointer,
slouken@10304
   257
                    uint32_t time, uint32_t axis, wl_fixed_t value)
slouken@10304
   258
{
slouken@10304
   259
    struct SDL_WaylandInput *input = data;
slouken@10304
   260
slouken@10304
   261
    pointer_handle_axis_common(input, time, axis, value);
slouken@10304
   262
}
slouken@10304
   263
gabomdq@8062
   264
static const struct wl_pointer_listener pointer_listener = {
gabomdq@8062
   265
    pointer_handle_enter,
gabomdq@8062
   266
    pointer_handle_leave,
gabomdq@8062
   267
    pointer_handle_motion,
gabomdq@8062
   268
    pointer_handle_button,
gabomdq@8062
   269
    pointer_handle_axis,
gabomdq@8062
   270
};
gabomdq@8062
   271
gabomdq@8062
   272
static void
gabomdq@8062
   273
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   274
                       uint32_t format, int fd, uint32_t size)
gabomdq@8062
   275
{
gabomdq@8062
   276
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   277
    char *map_str;
gabomdq@8062
   278
gabomdq@8062
   279
    if (!data) {
gabomdq@8062
   280
        close(fd);
gabomdq@8062
   281
        return;
gabomdq@8062
   282
    }
gabomdq@8062
   283
gabomdq@8062
   284
    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
gabomdq@8062
   285
        close(fd);
gabomdq@8062
   286
        return;
gabomdq@8062
   287
    }
gabomdq@8062
   288
gabomdq@8062
   289
    map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
gabomdq@8062
   290
    if (map_str == MAP_FAILED) {
gabomdq@8062
   291
        close(fd);
gabomdq@8062
   292
        return;
gabomdq@8062
   293
    }
gabomdq@8062
   294
gabomdq@8104
   295
    input->xkb.keymap = WAYLAND_xkb_keymap_new_from_string(input->display->xkb_context,
gabomdq@8062
   296
                                                map_str,
gabomdq@8062
   297
                                                XKB_KEYMAP_FORMAT_TEXT_V1,
gabomdq@8062
   298
                                                0);
gabomdq@8062
   299
    munmap(map_str, size);
gabomdq@8062
   300
    close(fd);
gabomdq@8062
   301
gabomdq@8062
   302
    if (!input->xkb.keymap) {
gabomdq@8062
   303
        fprintf(stderr, "failed to compile keymap\n");
gabomdq@8062
   304
        return;
gabomdq@8062
   305
    }
gabomdq@8062
   306
gabomdq@8104
   307
    input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap);
gabomdq@8062
   308
    if (!input->xkb.state) {
gabomdq@8062
   309
        fprintf(stderr, "failed to create XKB state\n");
gabomdq@8104
   310
        WAYLAND_xkb_keymap_unref(input->xkb.keymap);
gabomdq@8062
   311
        input->xkb.keymap = NULL;
gabomdq@8062
   312
        return;
gabomdq@8062
   313
    }
gabomdq@8062
   314
}
gabomdq@8062
   315
gabomdq@8062
   316
static void
gabomdq@8062
   317
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   318
                      uint32_t serial, struct wl_surface *surface,
gabomdq@8062
   319
                      struct wl_array *keys)
gabomdq@8062
   320
{
gabomdq@8062
   321
    struct SDL_WaylandInput *input = data;
icculus@9656
   322
    SDL_WindowData *window;
icculus@9655
   323
icculus@9655
   324
    if (!surface) {
icculus@9655
   325
        /* enter event for a window we've just destroyed */
icculus@9655
   326
        return;
icculus@9655
   327
    }
icculus@9655
   328
 
icculus@9656
   329
    window = wl_surface_get_user_data(surface);
gabomdq@8062
   330
gabomdq@8135
   331
    if (window) {
philipp@10099
   332
        input->keyboard_focus = window;
philipp@10099
   333
        window->keyboard_device = input;
gabomdq@8135
   334
        SDL_SetKeyboardFocus(window->sdlwindow);
gabomdq@8135
   335
    }
gabomdq@8062
   336
}
gabomdq@8062
   337
gabomdq@8062
   338
static void
gabomdq@8062
   339
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   340
                      uint32_t serial, struct wl_surface *surface)
gabomdq@8062
   341
{
gabomdq@8062
   342
    SDL_SetKeyboardFocus(NULL);
gabomdq@8062
   343
}
gabomdq@8062
   344
gabomdq@8062
   345
static void
gabomdq@8062
   346
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   347
                    uint32_t serial, uint32_t time, uint32_t key,
gabomdq@8062
   348
                    uint32_t state_w)
gabomdq@8062
   349
{
gabomdq@8062
   350
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   351
    SDL_WindowData *window = input->keyboard_focus;
gabomdq@8062
   352
    enum wl_keyboard_key_state state = state_w;
gabomdq@8062
   353
    const xkb_keysym_t *syms;
gabomdq@8062
   354
    uint32_t scancode;
gabomdq@8062
   355
    char text[8];
gabomdq@8062
   356
    int size;
gabomdq@8062
   357
gabomdq@8062
   358
    if (key < SDL_arraysize(xfree86_scancode_table2)) {
gabomdq@8062
   359
        scancode = xfree86_scancode_table2[key];
gabomdq@8062
   360
gabomdq@8062
   361
        // TODO when do we get WL_KEYBOARD_KEY_STATE_REPEAT?
gabomdq@8062
   362
        if (scancode != SDL_SCANCODE_UNKNOWN)
gabomdq@8062
   363
            SDL_SendKeyboardKey(state == WL_KEYBOARD_KEY_STATE_PRESSED ?
gabomdq@8062
   364
                                SDL_PRESSED : SDL_RELEASED, scancode);
gabomdq@8062
   365
    }
gabomdq@8062
   366
gabomdq@8062
   367
    if (!window || window->keyboard_device != input || !input->xkb.state)
gabomdq@8062
   368
        return;
gabomdq@8062
   369
gabomdq@8062
   370
    // TODO can this happen?
gabomdq@8104
   371
    if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
gabomdq@8062
   372
        return;
gabomdq@8062
   373
gabomdq@8062
   374
    if (state) {
gabomdq@8104
   375
        size = WAYLAND_xkb_keysym_to_utf8(syms[0], text, sizeof text);
gabomdq@8062
   376
gabomdq@8062
   377
        if (size > 0) {
gabomdq@8062
   378
            text[size] = 0;
slouken@10583
   379
slouken@10583
   380
            Wayland_data_device_set_serial(input->data_device, serial);
slouken@10583
   381
gabomdq@8062
   382
            SDL_SendKeyboardText(text);
gabomdq@8062
   383
        }
gabomdq@8062
   384
    }
gabomdq@8062
   385
}
gabomdq@8062
   386
gabomdq@8062
   387
static void
gabomdq@8062
   388
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   389
                          uint32_t serial, uint32_t mods_depressed,
gabomdq@8062
   390
                          uint32_t mods_latched, uint32_t mods_locked,
gabomdq@8062
   391
                          uint32_t group)
gabomdq@8062
   392
{
gabomdq@8062
   393
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   394
gabomdq@8104
   395
    WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
gabomdq@8062
   396
                          mods_locked, 0, 0, group);
gabomdq@8062
   397
}
gabomdq@8062
   398
gabomdq@8062
   399
static const struct wl_keyboard_listener keyboard_listener = {
gabomdq@8062
   400
    keyboard_handle_keymap,
gabomdq@8062
   401
    keyboard_handle_enter,
gabomdq@8062
   402
    keyboard_handle_leave,
gabomdq@8062
   403
    keyboard_handle_key,
gabomdq@8062
   404
    keyboard_handle_modifiers,
gabomdq@8062
   405
};
gabomdq@8062
   406
gabomdq@8062
   407
static void
gabomdq@8062
   408
seat_handle_capabilities(void *data, struct wl_seat *seat,
gabomdq@8062
   409
                         enum wl_seat_capability caps)
gabomdq@8062
   410
{
gabomdq@8062
   411
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   412
gabomdq@8062
   413
    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
gabomdq@8062
   414
        input->pointer = wl_seat_get_pointer(seat);
gabomdq@8062
   415
        input->display->pointer = input->pointer;
gabomdq@8062
   416
        wl_pointer_set_user_data(input->pointer, input);
gabomdq@8062
   417
        wl_pointer_add_listener(input->pointer, &pointer_listener,
gabomdq@8062
   418
                                input);
gabomdq@8062
   419
    } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
gabomdq@8062
   420
        wl_pointer_destroy(input->pointer);
gabomdq@8062
   421
        input->pointer = NULL;
gabomdq@8062
   422
    }
gabomdq@8062
   423
gabomdq@8062
   424
    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
gabomdq@8062
   425
        input->keyboard = wl_seat_get_keyboard(seat);
gabomdq@8062
   426
        wl_keyboard_set_user_data(input->keyboard, input);
gabomdq@8062
   427
        wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
gabomdq@8062
   428
                                 input);
gabomdq@8062
   429
    } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
gabomdq@8062
   430
        wl_keyboard_destroy(input->keyboard);
gabomdq@8062
   431
        input->keyboard = NULL;
gabomdq@8062
   432
    }
gabomdq@8062
   433
}
gabomdq@8062
   434
gabomdq@8062
   435
static const struct wl_seat_listener seat_listener = {
gabomdq@8062
   436
    seat_handle_capabilities,
gabomdq@8062
   437
};
gabomdq@8062
   438
slouken@10583
   439
static void
slouken@10583
   440
data_source_handle_target(void *data, struct wl_data_source *wl_data_source,
slouken@10583
   441
                          const char *mime_type)
slouken@10583
   442
{
slouken@10583
   443
}
slouken@10583
   444
slouken@10583
   445
static void
slouken@10583
   446
data_source_handle_send(void *data, struct wl_data_source *wl_data_source,
slouken@10583
   447
                        const char *mime_type, int32_t fd)
slouken@10583
   448
{
slouken@10583
   449
    Wayland_data_source_send((SDL_WaylandDataSource *)data, mime_type, fd);
slouken@10583
   450
}
slouken@10583
   451
                       
slouken@10583
   452
static void
slouken@10583
   453
data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source)
slouken@10583
   454
{
slouken@10583
   455
    Wayland_data_source_destroy(data);
slouken@10583
   456
}
slouken@10583
   457
                       
slouken@10583
   458
static void
slouken@10583
   459
data_source_handle_dnd_drop_performed(void *data, struct wl_data_source *wl_data_source)
slouken@10583
   460
{
slouken@10583
   461
}
slouken@10583
   462
slouken@10583
   463
static void
slouken@10583
   464
data_source_handle_dnd_finished(void *data, struct wl_data_source *wl_data_source)
slouken@10583
   465
{
slouken@10583
   466
}
slouken@10583
   467
slouken@10583
   468
static void
slouken@10583
   469
data_source_handle_action(void *data, struct wl_data_source *wl_data_source,
slouken@10583
   470
                          uint32_t dnd_action)
slouken@10583
   471
{
slouken@10583
   472
}
slouken@10583
   473
slouken@10583
   474
static const struct wl_data_source_listener data_source_listener = {
slouken@10583
   475
    data_source_handle_target,
slouken@10583
   476
    data_source_handle_send,
slouken@10583
   477
    data_source_handle_cancelled,
slouken@10583
   478
    data_source_handle_dnd_drop_performed, // Version 3
slouken@10583
   479
    data_source_handle_dnd_finished,       // Version 3
slouken@10583
   480
    data_source_handle_action,             // Version 3
slouken@10583
   481
};
slouken@10583
   482
slouken@10583
   483
SDL_WaylandDataSource*
slouken@10583
   484
Wayland_data_source_create(_THIS)
slouken@10583
   485
{
slouken@10583
   486
    SDL_WaylandDataSource *data_source = NULL;
slouken@10583
   487
    SDL_VideoData *driver_data = NULL;
slouken@10583
   488
    struct wl_data_source *id = NULL;
slouken@10583
   489
slouken@10583
   490
    if (_this == NULL || _this->driverdata == NULL) {
slouken@10583
   491
        SDL_SetError("Video driver uninitialized");
slouken@10583
   492
    } else {
slouken@10583
   493
        driver_data = _this->driverdata;
slouken@10583
   494
slouken@10583
   495
        if (driver_data->data_device_manager != NULL) {
slouken@10583
   496
            id = wl_data_device_manager_create_data_source(
slouken@10583
   497
                     driver_data->data_device_manager);
slouken@10583
   498
        }
slouken@10583
   499
slouken@10583
   500
        if (id == NULL) { 
slouken@10583
   501
            SDL_SetError("Wayland unable to create data source");
slouken@10583
   502
        } else {
slouken@10583
   503
            data_source = SDL_calloc(1, sizeof *data_source);
slouken@10583
   504
            if (data_source == NULL) {
slouken@10583
   505
                SDL_OutOfMemory();
slouken@10583
   506
                wl_data_source_destroy(id);
slouken@10583
   507
            } else {
slouken@10583
   508
                WAYLAND_wl_list_init(&(data_source->mimes));
slouken@10583
   509
                data_source->source = id;
slouken@10583
   510
                wl_data_source_set_user_data(id, data_source);
slouken@10583
   511
                wl_data_source_add_listener(id, &data_source_listener,
slouken@10583
   512
                                            data_source);
slouken@10583
   513
            }
slouken@10583
   514
        }
slouken@10583
   515
    }
slouken@10583
   516
    return data_source;
slouken@10583
   517
}
slouken@10583
   518
slouken@10583
   519
static void
slouken@10583
   520
data_offer_handle_offer(void *data, struct wl_data_offer *wl_data_offer,
slouken@10583
   521
                        const char *mime_type)
slouken@10583
   522
{
slouken@10583
   523
    SDL_WaylandDataOffer *offer = data;
slouken@10583
   524
    Wayland_data_offer_add_mime(offer, mime_type);
slouken@10583
   525
}
slouken@10583
   526
slouken@10583
   527
static void
slouken@10583
   528
data_offer_handle_source_actions(void *data, struct wl_data_offer *wl_data_offer,
slouken@10583
   529
                                 uint32_t source_actions)
slouken@10583
   530
{
slouken@10583
   531
}
slouken@10583
   532
slouken@10583
   533
static void
slouken@10583
   534
data_offer_handle_actions(void *data, struct wl_data_offer *wl_data_offer,
slouken@10583
   535
                          uint32_t dnd_action)
slouken@10583
   536
{
slouken@10583
   537
}
slouken@10583
   538
slouken@10583
   539
static const struct wl_data_offer_listener data_offer_listener = {
slouken@10583
   540
    data_offer_handle_offer,
slouken@10583
   541
    data_offer_handle_source_actions, // Version 3
slouken@10583
   542
    data_offer_handle_actions,        // Version 3
slouken@10583
   543
};
slouken@10583
   544
slouken@10583
   545
static void
slouken@10583
   546
data_device_handle_data_offer(void *data, struct wl_data_device *wl_data_device,
slouken@10583
   547
			                  struct wl_data_offer *id)
slouken@10583
   548
{
slouken@10583
   549
    SDL_WaylandDataOffer *data_offer = NULL;
slouken@10583
   550
slouken@10583
   551
    data_offer = SDL_calloc(1, sizeof *data_offer);
slouken@10583
   552
    if (data_offer == NULL) {
slouken@10583
   553
        SDL_OutOfMemory();
slouken@10583
   554
    } else {
slouken@10583
   555
        data_offer->offer = id;
slouken@10583
   556
        data_offer->data_device = data;
slouken@10583
   557
        WAYLAND_wl_list_init(&(data_offer->mimes));
slouken@10583
   558
        wl_data_offer_set_user_data(id, data_offer);
slouken@10583
   559
        wl_data_offer_add_listener(id, &data_offer_listener, data_offer);
slouken@10583
   560
    }
slouken@10583
   561
}
slouken@10583
   562
slouken@10583
   563
static void
slouken@10583
   564
data_device_handle_enter(void *data, struct wl_data_device *wl_data_device,
slouken@10583
   565
		                 uint32_t serial, struct wl_surface *surface,
slouken@10583
   566
                         wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id)
slouken@10583
   567
{
slouken@10583
   568
    SDL_WaylandDataDevice *data_device = data;
slouken@10583
   569
    SDL_bool has_mime = SDL_FALSE;
slouken@10583
   570
    uint32_t dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; 
slouken@10583
   571
        
slouken@10583
   572
    data_device->drag_serial = serial;
slouken@10583
   573
slouken@10583
   574
    if (id != NULL) {
slouken@10583
   575
        data_device->drag_offer = wl_data_offer_get_user_data(id);
slouken@10583
   576
slouken@10583
   577
        /* TODO: SDL Support more mime types */
slouken@10583
   578
        has_mime = Wayland_data_offer_has_mime(
slouken@10583
   579
            data_device->drag_offer, FILE_MIME);
slouken@10583
   580
slouken@10583
   581
        /* If drag_mime is NULL this will decline the offer */
slouken@10583
   582
        wl_data_offer_accept(id, serial,
slouken@10583
   583
                             (has_mime == SDL_TRUE) ? FILE_MIME : NULL);
slouken@10583
   584
slouken@10583
   585
        /* SDL only supports "copy" style drag and drop */
slouken@10583
   586
        if (has_mime == SDL_TRUE) {
slouken@10583
   587
            dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
slouken@10583
   588
        }
slouken@10583
   589
        wl_data_offer_set_actions(data_device->drag_offer->offer,
slouken@10583
   590
                                  dnd_action, dnd_action);
slouken@10583
   591
    }
slouken@10583
   592
}
slouken@10583
   593
slouken@10583
   594
static void
slouken@10583
   595
data_device_handle_leave(void *data, struct wl_data_device *wl_data_device)
slouken@10583
   596
{
slouken@10583
   597
    SDL_WaylandDataDevice *data_device = data;
slouken@10583
   598
    SDL_WaylandDataOffer *offer = NULL;
slouken@10583
   599
slouken@10583
   600
    if (data_device->selection_offer != NULL) {
slouken@10583
   601
        data_device->selection_offer = NULL;
slouken@10583
   602
        Wayland_data_offer_destroy(offer);
slouken@10583
   603
    }
slouken@10583
   604
}
slouken@10583
   605
slouken@10583
   606
static void
slouken@10583
   607
data_device_handle_motion(void *data, struct wl_data_device *wl_data_device,
slouken@10583
   608
		                  uint32_t time, wl_fixed_t x, wl_fixed_t y)
slouken@10583
   609
{
slouken@10583
   610
}
slouken@10583
   611
slouken@10583
   612
static void
slouken@10583
   613
data_device_handle_drop(void *data, struct wl_data_device *wl_data_device)
slouken@10583
   614
{
slouken@10583
   615
    SDL_WaylandDataDevice *data_device = data;
slouken@10583
   616
    void *buffer = NULL;
slouken@10583
   617
    size_t length = 0;
slouken@10583
   618
slouken@10583
   619
    const char *current_uri = NULL;
slouken@10583
   620
    const char *last_char = NULL;
slouken@10583
   621
    char *current_char = NULL;
slouken@10583
   622
    
slouken@10583
   623
    if (data_device->drag_offer != NULL) {
slouken@10583
   624
        /* TODO: SDL Support more mime types */
slouken@10583
   625
        buffer = Wayland_data_offer_receive(data_device->drag_offer,
slouken@10583
   626
                                            &length, FILE_MIME, SDL_FALSE);
slouken@10583
   627
slouken@10583
   628
        /* uri-list */
slouken@10583
   629
        current_uri = (const char *)buffer;
slouken@10583
   630
        last_char = (const char *)buffer + length;
slouken@10583
   631
        for (current_char = buffer; current_char < last_char; ++current_char) {
slouken@10583
   632
            if (*current_char == '\n' || *current_char == 0) {
slouken@10583
   633
                if (*current_uri != 0 && *current_uri != '#') {
slouken@10583
   634
                    *current_char = 0;
slouken@10583
   635
                    SDL_SendDropFile(NULL, current_uri);
slouken@10583
   636
                }
slouken@10583
   637
                current_uri = (const char *)current_char + 1;
slouken@10583
   638
            }
slouken@10583
   639
        }
slouken@10583
   640
slouken@10583
   641
        SDL_free(buffer);
slouken@10583
   642
    }
slouken@10583
   643
}
slouken@10583
   644
slouken@10583
   645
static void
slouken@10583
   646
data_device_handle_selection(void *data, struct wl_data_device *wl_data_device,
slouken@10583
   647
			                 struct wl_data_offer *id)
slouken@10583
   648
{    
slouken@10583
   649
    SDL_WaylandDataDevice *data_device = data;
slouken@10583
   650
    SDL_WaylandDataOffer *offer = NULL;
slouken@10583
   651
slouken@10583
   652
    if (id != NULL) {
slouken@10583
   653
        offer = wl_data_offer_get_user_data(id);
slouken@10583
   654
    }
slouken@10583
   655
slouken@10583
   656
    if (data_device->selection_offer != offer) {
slouken@10583
   657
        Wayland_data_offer_destroy(data_device->selection_offer);
slouken@10583
   658
        data_device->selection_offer = offer;
slouken@10583
   659
    }
slouken@10583
   660
slouken@10583
   661
    SDL_SendClipboardUpdate();
slouken@10583
   662
}
slouken@10583
   663
slouken@10583
   664
static const struct wl_data_device_listener data_device_listener = {
slouken@10583
   665
    data_device_handle_data_offer,
slouken@10583
   666
    data_device_handle_enter,
slouken@10583
   667
    data_device_handle_leave,
slouken@10583
   668
    data_device_handle_motion,
slouken@10583
   669
    data_device_handle_drop,
slouken@10583
   670
    data_device_handle_selection
slouken@10583
   671
};
slouken@10583
   672
gabomdq@8062
   673
void
gabomdq@8062
   674
Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
gabomdq@8062
   675
{
gabomdq@8062
   676
    struct SDL_WaylandInput *input;
slouken@10583
   677
    SDL_WaylandDataDevice *data_device = NULL;
gabomdq@8062
   678
gabomdq@8135
   679
    input = SDL_calloc(1, sizeof *input);
gabomdq@8062
   680
    if (input == NULL)
gabomdq@8062
   681
        return;
gabomdq@8062
   682
gabomdq@8062
   683
    input->display = d;
gabomdq@8062
   684
    input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
icculus@9554
   685
    input->sx_w = wl_fixed_from_int(0);
icculus@9554
   686
    input->sy_w = wl_fixed_from_int(0);
gabomdq@8062
   687
    d->input = input;
slouken@10583
   688
    
slouken@10583
   689
    if (d->data_device_manager != NULL) {
slouken@10583
   690
        data_device = SDL_calloc(1, sizeof *data_device);
slouken@10583
   691
        if (data_device == NULL) {
slouken@10583
   692
            return;
slouken@10583
   693
        }
slouken@10583
   694
slouken@10583
   695
        data_device->data_device = wl_data_device_manager_get_data_device(
slouken@10583
   696
            d->data_device_manager, input->seat
slouken@10583
   697
        );
slouken@10583
   698
        data_device->video_data = d;
slouken@10583
   699
slouken@10583
   700
        if (data_device->data_device == NULL) {
slouken@10583
   701
            SDL_free(data_device);
slouken@10583
   702
        } else {
slouken@10583
   703
            wl_data_device_set_user_data(data_device->data_device, data_device);
slouken@10583
   704
            wl_data_device_add_listener(data_device->data_device,
slouken@10583
   705
                                        &data_device_listener, data_device);
slouken@10583
   706
            input->data_device = data_device;
slouken@10583
   707
        }
slouken@10583
   708
    }
gabomdq@8062
   709
gabomdq@8062
   710
    wl_seat_add_listener(input->seat, &seat_listener, input);
gabomdq@8062
   711
    wl_seat_set_user_data(input->seat, input);
gabomdq@8062
   712
gabomdq@8104
   713
    WAYLAND_wl_display_flush(d->display);
gabomdq@8062
   714
}
gabomdq@8062
   715
gabomdq@8062
   716
void Wayland_display_destroy_input(SDL_VideoData *d)
gabomdq@8062
   717
{
gabomdq@8062
   718
    struct SDL_WaylandInput *input = d->input;
gabomdq@8062
   719
gabomdq@8062
   720
    if (!input)
gabomdq@8062
   721
        return;
gabomdq@8062
   722
slouken@10583
   723
    if (input->data_device != NULL) {
slouken@10583
   724
        Wayland_data_device_clear_selection(input->data_device);
slouken@10583
   725
        if (input->data_device->selection_offer != NULL) {
slouken@10583
   726
            Wayland_data_offer_destroy(input->data_device->selection_offer);
slouken@10583
   727
        }
slouken@10583
   728
        if (input->data_device->drag_offer != NULL) {
slouken@10583
   729
            Wayland_data_offer_destroy(input->data_device->drag_offer);
slouken@10583
   730
        }
slouken@10583
   731
        if (input->data_device->data_device != NULL) {
slouken@10583
   732
            wl_data_device_release(input->data_device->data_device);
slouken@10583
   733
        }
slouken@10583
   734
        SDL_free(input->data_device);
slouken@10583
   735
    }
slouken@10583
   736
gabomdq@8062
   737
    if (input->keyboard)
gabomdq@8062
   738
        wl_keyboard_destroy(input->keyboard);
gabomdq@8062
   739
gabomdq@8062
   740
    if (input->pointer)
gabomdq@8062
   741
        wl_pointer_destroy(input->pointer);
gabomdq@8062
   742
gabomdq@8062
   743
    if (input->seat)
gabomdq@8062
   744
        wl_seat_destroy(input->seat);
gabomdq@8062
   745
gabomdq@8062
   746
    if (input->xkb.state)
gabomdq@8104
   747
        WAYLAND_xkb_state_unref(input->xkb.state);
gabomdq@8062
   748
gabomdq@8062
   749
    if (input->xkb.keymap)
gabomdq@8104
   750
        WAYLAND_xkb_keymap_unref(input->xkb.keymap);
gabomdq@8062
   751
gabomdq@8135
   752
    SDL_free(input);
gabomdq@8062
   753
    d->input = NULL;
gabomdq@8062
   754
}
gabomdq@8062
   755
slouken@10583
   756
SDL_WaylandDataDevice* Wayland_get_data_device(struct SDL_WaylandInput *input)
slouken@10583
   757
{
slouken@10583
   758
    if (input == NULL) {
slouken@10583
   759
        return NULL;
slouken@10583
   760
    }
slouken@10583
   761
slouken@10583
   762
    return input->data_device;
slouken@10583
   763
}
slouken@10583
   764
slouken@10304
   765
void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id)
slouken@10304
   766
{
slouken@10304
   767
    d->relative_pointer_manager =
slouken@10304
   768
        wl_registry_bind(d->registry, id,
slouken@10304
   769
                         &zwp_relative_pointer_manager_v1_interface, 1);
slouken@10304
   770
}
slouken@10304
   771
slouken@10304
   772
void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d)
slouken@10304
   773
{
slouken@10304
   774
    if (d->relative_pointer_manager)
slouken@10304
   775
        zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager);
slouken@10304
   776
}
slouken@10304
   777
slouken@10304
   778
void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id)
slouken@10304
   779
{
slouken@10304
   780
    d->pointer_constraints =
slouken@10304
   781
        wl_registry_bind(d->registry, id,
slouken@10304
   782
                         &zwp_pointer_constraints_v1_interface, 1);
slouken@10304
   783
}
slouken@10304
   784
slouken@10304
   785
void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d)
slouken@10304
   786
{
slouken@10304
   787
    if (d->pointer_constraints)
slouken@10304
   788
        zwp_pointer_constraints_v1_destroy(d->pointer_constraints);
slouken@10304
   789
}
slouken@10304
   790
slouken@10304
   791
static void
slouken@10304
   792
relative_pointer_handle_relative_motion(void *data,
slouken@10304
   793
                                        struct zwp_relative_pointer_v1 *pointer,
slouken@10304
   794
                                        uint32_t time_hi,
slouken@10304
   795
                                        uint32_t time_lo,
slouken@10304
   796
                                        wl_fixed_t dx_w,
slouken@10304
   797
                                        wl_fixed_t dy_w,
slouken@10304
   798
                                        wl_fixed_t dx_unaccel_w,
slouken@10304
   799
                                        wl_fixed_t dy_unaccel_w)
slouken@10304
   800
{
slouken@10304
   801
    struct SDL_WaylandInput *input = data;
slouken@10304
   802
    SDL_VideoData *d = input->display;
slouken@10304
   803
    SDL_WindowData *window = input->pointer_focus;
slouken@10304
   804
    double dx_unaccel;
slouken@10304
   805
    double dy_unaccel;
slouken@10304
   806
    double dx;
slouken@10304
   807
    double dy;
slouken@10304
   808
slouken@10304
   809
    dx_unaccel = wl_fixed_to_double(dx_unaccel_w);
slouken@10304
   810
    dy_unaccel = wl_fixed_to_double(dy_unaccel_w);
slouken@10304
   811
slouken@10304
   812
    /* Add left over fraction from last event. */
slouken@10304
   813
    dx_unaccel += input->dx_frac;
slouken@10304
   814
    dy_unaccel += input->dy_frac;
slouken@10304
   815
slouken@10304
   816
    input->dx_frac = modf(dx_unaccel, &dx);
slouken@10304
   817
    input->dy_frac = modf(dy_unaccel, &dy);
slouken@10304
   818
slouken@10304
   819
    if (input->pointer_focus && d->relative_mouse_mode) {
slouken@10304
   820
        SDL_SendMouseMotion(window->sdlwindow, 0, 1, (int)dx, (int)dy);
slouken@10304
   821
    }
slouken@10304
   822
}
slouken@10304
   823
slouken@10304
   824
static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
slouken@10304
   825
    relative_pointer_handle_relative_motion,
slouken@10304
   826
};
slouken@10304
   827
slouken@10304
   828
static void
slouken@10304
   829
locked_pointer_locked(void *data,
slouken@10304
   830
                      struct zwp_locked_pointer_v1 *locked_pointer)
slouken@10304
   831
{
slouken@10304
   832
}
slouken@10304
   833
slouken@10304
   834
static void
slouken@10304
   835
locked_pointer_unlocked(void *data,
slouken@10304
   836
                        struct zwp_locked_pointer_v1 *locked_pointer)
slouken@10304
   837
{
slouken@10304
   838
}
slouken@10304
   839
slouken@10304
   840
static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
slouken@10304
   841
    locked_pointer_locked,
slouken@10304
   842
    locked_pointer_unlocked,
slouken@10304
   843
};
slouken@10304
   844
slouken@10304
   845
static void
slouken@10304
   846
lock_pointer_to_window(SDL_Window *window,
slouken@10304
   847
                       struct SDL_WaylandInput *input)
slouken@10304
   848
{
slouken@10304
   849
    SDL_WindowData *w = window->driverdata;
slouken@10304
   850
    SDL_VideoData *d = input->display;
slouken@10304
   851
    struct zwp_locked_pointer_v1 *locked_pointer;
slouken@10304
   852
slouken@10304
   853
    if (w->locked_pointer)
slouken@10304
   854
        return;
slouken@10304
   855
slouken@10304
   856
    locked_pointer =
slouken@10304
   857
        zwp_pointer_constraints_v1_lock_pointer(d->pointer_constraints,
slouken@10304
   858
                                                w->surface,
slouken@10304
   859
                                                input->pointer,
slouken@10304
   860
                                                NULL,
slouken@10304
   861
                                                ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
slouken@10304
   862
    zwp_locked_pointer_v1_add_listener(locked_pointer,
slouken@10304
   863
                                       &locked_pointer_listener,
slouken@10304
   864
                                       window);
slouken@10304
   865
slouken@10304
   866
    w->locked_pointer = locked_pointer;
slouken@10304
   867
}
slouken@10304
   868
slouken@10304
   869
int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
slouken@10304
   870
{
slouken@10304
   871
    SDL_VideoDevice *vd = SDL_GetVideoDevice();
slouken@10304
   872
    SDL_VideoData *d = input->display;
slouken@10304
   873
    SDL_Window *window;
slouken@10304
   874
    struct zwp_relative_pointer_v1 *relative_pointer;
slouken@10304
   875
slouken@10304
   876
    if (!d->relative_pointer_manager)
slouken@10304
   877
        return -1;
slouken@10304
   878
slouken@10304
   879
    if (!d->pointer_constraints)
slouken@10304
   880
        return -1;
slouken@10304
   881
slouken@10304
   882
    if (!input->relative_pointer) {
slouken@10304
   883
        relative_pointer =
slouken@10304
   884
            zwp_relative_pointer_manager_v1_get_relative_pointer(
slouken@10304
   885
                d->relative_pointer_manager,
slouken@10304
   886
                input->pointer);
slouken@10304
   887
        zwp_relative_pointer_v1_add_listener(relative_pointer,
slouken@10304
   888
                                             &relative_pointer_listener,
slouken@10304
   889
                                             input);
slouken@10304
   890
        input->relative_pointer = relative_pointer;
slouken@10304
   891
    }
slouken@10304
   892
slouken@10304
   893
    for (window = vd->windows; window; window = window->next)
slouken@10304
   894
        lock_pointer_to_window(window, input);
slouken@10304
   895
slouken@10304
   896
    d->relative_mouse_mode = 1;
slouken@10304
   897
slouken@10304
   898
    return 0;
slouken@10304
   899
}
slouken@10304
   900
slouken@10304
   901
int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
slouken@10304
   902
{
slouken@10304
   903
    SDL_VideoDevice *vd = SDL_GetVideoDevice();
slouken@10304
   904
    SDL_VideoData *d = input->display;
slouken@10304
   905
    SDL_Window *window;
slouken@10304
   906
    SDL_WindowData *w;
slouken@10304
   907
slouken@10304
   908
    for (window = vd->windows; window; window = window->next) {
slouken@10304
   909
        w = window->driverdata;
slouken@10304
   910
        if (w->locked_pointer)
slouken@10304
   911
            zwp_locked_pointer_v1_destroy(w->locked_pointer);
slouken@10304
   912
        w->locked_pointer = NULL;
slouken@10304
   913
    }
slouken@10304
   914
slouken@10304
   915
    zwp_relative_pointer_v1_destroy(input->relative_pointer);
slouken@10304
   916
    input->relative_pointer = NULL;
slouken@10304
   917
slouken@10304
   918
    d->relative_mouse_mode = 0;
slouken@10304
   919
slouken@10304
   920
    return 0;
slouken@10304
   921
}
slouken@10304
   922
icculus@8116
   923
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
icculus@8116
   924
gabomdq@8062
   925
/* vi: set ts=4 sw=4 expandtab: */