src/video/wayland/SDL_waylandevents.c
author Ryan C. Gordon
Sun, 12 Apr 2015 20:40:06 -0400
changeset 9554 879f71e1478b
parent 9257 6f41196c2d6b
child 9555 fff4b6354b99
permissions -rw-r--r--
Implemented SetWindowHitTest() for Wayland (thanks, x414e54!).

Fixes Bugzilla #2941.
gabomdq@8062
     1
/*
gabomdq@8062
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 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"
gabomdq@8062
    28
gabomdq@8062
    29
#include "../../events/SDL_sysevents.h"
gabomdq@8062
    30
#include "../../events/SDL_events_c.h"
gabomdq@8062
    31
#include "../../events/scancodes_xfree86.h"
gabomdq@8062
    32
gabomdq@8062
    33
#include "SDL_waylandvideo.h"
gabomdq@8062
    34
#include "SDL_waylandevents_c.h"
gabomdq@8062
    35
#include "SDL_waylandwindow.h"
gabomdq@8062
    36
gabomdq@8104
    37
#include "SDL_waylanddyn.h"
gabomdq@8104
    38
gabomdq@8062
    39
#include <linux/input.h>
gabomdq@8062
    40
#include <sys/select.h>
gabomdq@8062
    41
#include <sys/mman.h>
gabomdq@8062
    42
#include <poll.h>
gabomdq@8062
    43
#include <errno.h>
gabomdq@8062
    44
#include <unistd.h>
gabomdq@8062
    45
#include <xkbcommon/xkbcommon.h>
gabomdq@8062
    46
gabomdq@8062
    47
struct SDL_WaylandInput {
gabomdq@8062
    48
    SDL_VideoData *display;
gabomdq@8062
    49
    struct wl_seat *seat;
gabomdq@8062
    50
    struct wl_pointer *pointer;
gabomdq@8062
    51
    struct wl_keyboard *keyboard;
gabomdq@8062
    52
    SDL_WindowData *pointer_focus;
gabomdq@8062
    53
    SDL_WindowData *keyboard_focus;
gabomdq@8062
    54
icculus@9554
    55
    /* Last motion location */
icculus@9554
    56
    wl_fixed_t sx_w;
icculus@9554
    57
    wl_fixed_t sy_w;
icculus@9554
    58
    
gabomdq@8062
    59
    struct {
gabomdq@8062
    60
        struct xkb_keymap *keymap;
gabomdq@8062
    61
        struct xkb_state *state;
gabomdq@8062
    62
    } xkb;
gabomdq@8062
    63
};
gabomdq@8062
    64
gabomdq@8062
    65
void
gabomdq@8062
    66
Wayland_PumpEvents(_THIS)
gabomdq@8062
    67
{
gabomdq@8062
    68
    SDL_VideoData *d = _this->driverdata;
gabomdq@8062
    69
    struct pollfd pfd[1];
gabomdq@8062
    70
gabomdq@8104
    71
    pfd[0].fd = WAYLAND_wl_display_get_fd(d->display);
gabomdq@8062
    72
    pfd[0].events = POLLIN;
gabomdq@8062
    73
    poll(pfd, 1, 0);
gabomdq@8062
    74
gabomdq@8062
    75
    if (pfd[0].revents & POLLIN)
gabomdq@8104
    76
        WAYLAND_wl_display_dispatch(d->display);
gabomdq@8062
    77
    else
gabomdq@8104
    78
        WAYLAND_wl_display_dispatch_pending(d->display);
gabomdq@8062
    79
}
gabomdq@8062
    80
gabomdq@8062
    81
static void
gabomdq@8062
    82
pointer_handle_enter(void *data, struct wl_pointer *pointer,
gabomdq@8062
    83
                     uint32_t serial, struct wl_surface *surface,
gabomdq@8062
    84
                     wl_fixed_t sx_w, wl_fixed_t sy_w)
gabomdq@8062
    85
{
gabomdq@8062
    86
    struct SDL_WaylandInput *input = data;
gabomdq@8062
    87
    SDL_WindowData *window;
gabomdq@8062
    88
gabomdq@8062
    89
    if (!surface) {
gabomdq@8062
    90
        /* enter event for a window we've just destroyed */
gabomdq@8062
    91
        return;
gabomdq@8062
    92
    }
gabomdq@8135
    93
    
gabomdq@8135
    94
    /* This handler will be called twice in Wayland 1.4
gabomdq@8135
    95
     * Once for the window surface which has valid user data
gabomdq@8135
    96
     * and again for the mouse cursor surface which does not have valid user data
gabomdq@8135
    97
     * We ignore the later
gabomdq@8135
    98
     */
gabomdq@8062
    99
gabomdq@8135
   100
    window = (SDL_WindowData *)wl_surface_get_user_data(surface);
gabomdq@8135
   101
    
gabomdq@8135
   102
    if (window) {
gabomdq@8135
   103
        input->pointer_focus = window;
gabomdq@8135
   104
        SDL_SetMouseFocus(window->sdlwindow);
gabomdq@8135
   105
    }
gabomdq@8062
   106
}
gabomdq@8062
   107
gabomdq@8062
   108
static void
gabomdq@8062
   109
pointer_handle_leave(void *data, struct wl_pointer *pointer,
gabomdq@8062
   110
                     uint32_t serial, struct wl_surface *surface)
gabomdq@8062
   111
{
gabomdq@8062
   112
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   113
gabomdq@8135
   114
    if (input->pointer_focus) {
gabomdq@8135
   115
        SDL_SetMouseFocus(NULL);
gabomdq@8135
   116
        input->pointer_focus = NULL;
gabomdq@8135
   117
    }
gabomdq@8062
   118
}
gabomdq@8062
   119
gabomdq@8062
   120
static void
gabomdq@8062
   121
pointer_handle_motion(void *data, struct wl_pointer *pointer,
gabomdq@8062
   122
                      uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
gabomdq@8062
   123
{
gabomdq@8062
   124
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   125
    SDL_WindowData *window = input->pointer_focus;
icculus@9554
   126
    input->sx_w = sx_w;
icculus@9554
   127
    input->sy_w = sy_w;
gabomdq@8062
   128
    int sx = wl_fixed_to_int(sx_w);
gabomdq@8062
   129
    int sy = wl_fixed_to_int(sy_w);
gabomdq@8135
   130
    if (input->pointer_focus) {
gabomdq@8135
   131
        SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
gabomdq@8135
   132
    }
gabomdq@8062
   133
}
gabomdq@8062
   134
icculus@9554
   135
static SDL_bool
icculus@9554
   136
ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
icculus@9554
   137
{
icculus@9554
   138
    SDL_WindowData *window_data = input->pointer_focus;
icculus@9554
   139
    SDL_Window *window = window_data->sdlwindow;
icculus@9554
   140
    SDL_bool ret = SDL_FALSE;
icculus@9554
   141
icculus@9554
   142
    if (window->hit_test) {
icculus@9554
   143
        const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
icculus@9554
   144
        const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
icculus@9554
   145
        switch (rc) {
icculus@9554
   146
            case SDL_HITTEST_DRAGGABLE: {
icculus@9554
   147
                    wl_shell_surface_move(window_data->shell_surface, input->seat, serial);
icculus@9554
   148
                    ret = SDL_TRUE;
icculus@9554
   149
                }
icculus@9554
   150
                break;
icculus@9554
   151
            case SDL_HITTEST_RESIZE_TOPLEFT: {
icculus@9554
   152
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_TOP_LEFT);
icculus@9554
   153
                    ret = SDL_TRUE;
icculus@9554
   154
                }
icculus@9554
   155
                break;
icculus@9554
   156
            case SDL_HITTEST_RESIZE_TOP: {
icculus@9554
   157
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_TOP);
icculus@9554
   158
                    ret = SDL_TRUE;
icculus@9554
   159
                }
icculus@9554
   160
                break;
icculus@9554
   161
            case SDL_HITTEST_RESIZE_TOPRIGHT: {
icculus@9554
   162
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial,  WL_SHELL_SURFACE_RESIZE_TOP_RIGHT);
icculus@9554
   163
                    ret = SDL_TRUE;
icculus@9554
   164
                }
icculus@9554
   165
                break;
icculus@9554
   166
            case SDL_HITTEST_RESIZE_RIGHT: {
icculus@9554
   167
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_RIGHT);
icculus@9554
   168
                    ret = SDL_TRUE;
icculus@9554
   169
                }
icculus@9554
   170
                break;
icculus@9554
   171
            case SDL_HITTEST_RESIZE_BOTTOMRIGHT: {
icculus@9554
   172
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial,  WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT);
icculus@9554
   173
                    ret = SDL_TRUE;
icculus@9554
   174
                }
icculus@9554
   175
                break;
icculus@9554
   176
            case SDL_HITTEST_RESIZE_BOTTOM: {
icculus@9554
   177
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_BOTTOM);
icculus@9554
   178
                    ret = SDL_TRUE;
icculus@9554
   179
                }
icculus@9554
   180
                break;
icculus@9554
   181
            case SDL_HITTEST_RESIZE_BOTTOMLEFT: {
icculus@9554
   182
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT);
icculus@9554
   183
                    ret = SDL_TRUE;
icculus@9554
   184
                }
icculus@9554
   185
                break;
icculus@9554
   186
            case SDL_HITTEST_RESIZE_LEFT: {
icculus@9554
   187
                    wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, WL_SHELL_SURFACE_RESIZE_LEFT);
icculus@9554
   188
                    ret = SDL_TRUE;
icculus@9554
   189
                }
icculus@9554
   190
                break;
icculus@9554
   191
            default:
icculus@9554
   192
                break;
icculus@9554
   193
        }
icculus@9554
   194
    }
icculus@9554
   195
icculus@9554
   196
    return ret;
icculus@9554
   197
}
icculus@9554
   198
gabomdq@8062
   199
static void
gabomdq@8062
   200
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
gabomdq@8062
   201
                      uint32_t time, uint32_t button, uint32_t state_w)
gabomdq@8062
   202
{
gabomdq@8062
   203
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   204
    SDL_WindowData *window = input->pointer_focus;
gabomdq@8062
   205
    enum wl_pointer_button_state state = state_w;
gabomdq@8062
   206
    uint32_t sdl_button;
gabomdq@8135
   207
    
gabomdq@8135
   208
    if  (input->pointer_focus) {
gabomdq@8135
   209
        switch (button) {
gabomdq@8135
   210
            case BTN_LEFT:
gabomdq@8135
   211
                sdl_button = SDL_BUTTON_LEFT;
icculus@9554
   212
                if (ProcessHitTest(data, serial)) {
icculus@9554
   213
                    return;  /* don't pass this event on to app. */
icculus@9554
   214
                }
gabomdq@8135
   215
                break;
gabomdq@8135
   216
            case BTN_MIDDLE:
gabomdq@8135
   217
                sdl_button = SDL_BUTTON_MIDDLE;
gabomdq@8135
   218
                break;
gabomdq@8135
   219
            case BTN_RIGHT:
gabomdq@8135
   220
                sdl_button = SDL_BUTTON_RIGHT;
gabomdq@8135
   221
                break;
gabomdq@8135
   222
            case BTN_SIDE:
gabomdq@8135
   223
                sdl_button = SDL_BUTTON_X1;
gabomdq@8135
   224
                break;
gabomdq@8135
   225
            case BTN_EXTRA:
gabomdq@8135
   226
                sdl_button = SDL_BUTTON_X2;
gabomdq@8135
   227
                break;
gabomdq@8135
   228
            default:
gabomdq@8135
   229
                return;
gabomdq@8135
   230
        }
gabomdq@8062
   231
gabomdq@8135
   232
        SDL_SendMouseButton(window->sdlwindow, 0,
gabomdq@8135
   233
                            state ? SDL_PRESSED : SDL_RELEASED, sdl_button);
gabomdq@8062
   234
    }
gabomdq@8062
   235
}
gabomdq@8062
   236
gabomdq@8062
   237
static void
gabomdq@8062
   238
pointer_handle_axis(void *data, struct wl_pointer *pointer,
gabomdq@8062
   239
                    uint32_t time, uint32_t axis, wl_fixed_t value)
gabomdq@8062
   240
{
gabomdq@8062
   241
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   242
    SDL_WindowData *window = input->pointer_focus;
gabomdq@8062
   243
    enum wl_pointer_axis a = axis;
gabomdq@8062
   244
    int x, y;
gabomdq@8062
   245
gabomdq@8135
   246
    if (input->pointer_focus) {
gabomdq@8135
   247
        switch (a) {
gabomdq@8135
   248
            case WL_POINTER_AXIS_VERTICAL_SCROLL:
gabomdq@8135
   249
                x = 0;
gabomdq@8135
   250
                y = wl_fixed_to_int(value);
gabomdq@8135
   251
                break;
gabomdq@8135
   252
            case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
gabomdq@8135
   253
                x = wl_fixed_to_int(value);
gabomdq@8135
   254
                y = 0;
gabomdq@8135
   255
                break;
gabomdq@8135
   256
            default:
gabomdq@8135
   257
                return;
gabomdq@8135
   258
        }
gabomdq@8135
   259
urkle@9257
   260
        SDL_SendMouseWheel(window->sdlwindow, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
gabomdq@8062
   261
    }
gabomdq@8062
   262
}
gabomdq@8062
   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;
gabomdq@8062
   322
    SDL_WindowData *window = wl_surface_get_user_data(surface);
gabomdq@8062
   323
gabomdq@8062
   324
    input->keyboard_focus = window;
gabomdq@8062
   325
    window->keyboard_device = input;
gabomdq@8135
   326
    if (window) {
gabomdq@8135
   327
        SDL_SetKeyboardFocus(window->sdlwindow);
gabomdq@8135
   328
    }
gabomdq@8062
   329
}
gabomdq@8062
   330
gabomdq@8062
   331
static void
gabomdq@8062
   332
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   333
                      uint32_t serial, struct wl_surface *surface)
gabomdq@8062
   334
{
gabomdq@8062
   335
    SDL_SetKeyboardFocus(NULL);
gabomdq@8062
   336
}
gabomdq@8062
   337
gabomdq@8062
   338
static void
gabomdq@8062
   339
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   340
                    uint32_t serial, uint32_t time, uint32_t key,
gabomdq@8062
   341
                    uint32_t state_w)
gabomdq@8062
   342
{
gabomdq@8062
   343
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   344
    SDL_WindowData *window = input->keyboard_focus;
gabomdq@8062
   345
    enum wl_keyboard_key_state state = state_w;
gabomdq@8062
   346
    const xkb_keysym_t *syms;
gabomdq@8062
   347
    uint32_t scancode;
gabomdq@8062
   348
    char text[8];
gabomdq@8062
   349
    int size;
gabomdq@8062
   350
gabomdq@8062
   351
    if (key < SDL_arraysize(xfree86_scancode_table2)) {
gabomdq@8062
   352
        scancode = xfree86_scancode_table2[key];
gabomdq@8062
   353
gabomdq@8062
   354
        // TODO when do we get WL_KEYBOARD_KEY_STATE_REPEAT?
gabomdq@8062
   355
        if (scancode != SDL_SCANCODE_UNKNOWN)
gabomdq@8062
   356
            SDL_SendKeyboardKey(state == WL_KEYBOARD_KEY_STATE_PRESSED ?
gabomdq@8062
   357
                                SDL_PRESSED : SDL_RELEASED, scancode);
gabomdq@8062
   358
    }
gabomdq@8062
   359
gabomdq@8062
   360
    if (!window || window->keyboard_device != input || !input->xkb.state)
gabomdq@8062
   361
        return;
gabomdq@8062
   362
gabomdq@8062
   363
    // TODO can this happen?
gabomdq@8104
   364
    if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
gabomdq@8062
   365
        return;
gabomdq@8062
   366
gabomdq@8062
   367
    if (state) {
gabomdq@8104
   368
        size = WAYLAND_xkb_keysym_to_utf8(syms[0], text, sizeof text);
gabomdq@8062
   369
gabomdq@8062
   370
        if (size > 0) {
gabomdq@8062
   371
            text[size] = 0;
gabomdq@8062
   372
            SDL_SendKeyboardText(text);
gabomdq@8062
   373
        }
gabomdq@8062
   374
    }
gabomdq@8062
   375
}
gabomdq@8062
   376
gabomdq@8062
   377
static void
gabomdq@8062
   378
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   379
                          uint32_t serial, uint32_t mods_depressed,
gabomdq@8062
   380
                          uint32_t mods_latched, uint32_t mods_locked,
gabomdq@8062
   381
                          uint32_t group)
gabomdq@8062
   382
{
gabomdq@8062
   383
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   384
gabomdq@8104
   385
    WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
gabomdq@8062
   386
                          mods_locked, 0, 0, group);
gabomdq@8062
   387
}
gabomdq@8062
   388
gabomdq@8062
   389
static const struct wl_keyboard_listener keyboard_listener = {
gabomdq@8062
   390
    keyboard_handle_keymap,
gabomdq@8062
   391
    keyboard_handle_enter,
gabomdq@8062
   392
    keyboard_handle_leave,
gabomdq@8062
   393
    keyboard_handle_key,
gabomdq@8062
   394
    keyboard_handle_modifiers,
gabomdq@8062
   395
};
gabomdq@8062
   396
gabomdq@8062
   397
static void
gabomdq@8062
   398
seat_handle_capabilities(void *data, struct wl_seat *seat,
gabomdq@8062
   399
                         enum wl_seat_capability caps)
gabomdq@8062
   400
{
gabomdq@8062
   401
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   402
gabomdq@8062
   403
    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
gabomdq@8062
   404
        input->pointer = wl_seat_get_pointer(seat);
gabomdq@8062
   405
        input->display->pointer = input->pointer;
gabomdq@8062
   406
        wl_pointer_set_user_data(input->pointer, input);
gabomdq@8062
   407
        wl_pointer_add_listener(input->pointer, &pointer_listener,
gabomdq@8062
   408
                                input);
gabomdq@8062
   409
    } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
gabomdq@8062
   410
        wl_pointer_destroy(input->pointer);
gabomdq@8062
   411
        input->pointer = NULL;
gabomdq@8062
   412
    }
gabomdq@8062
   413
gabomdq@8062
   414
    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
gabomdq@8062
   415
        input->keyboard = wl_seat_get_keyboard(seat);
gabomdq@8062
   416
        wl_keyboard_set_user_data(input->keyboard, input);
gabomdq@8062
   417
        wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
gabomdq@8062
   418
                                 input);
gabomdq@8062
   419
    } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
gabomdq@8062
   420
        wl_keyboard_destroy(input->keyboard);
gabomdq@8062
   421
        input->keyboard = NULL;
gabomdq@8062
   422
    }
gabomdq@8062
   423
}
gabomdq@8062
   424
gabomdq@8062
   425
static const struct wl_seat_listener seat_listener = {
gabomdq@8062
   426
    seat_handle_capabilities,
gabomdq@8062
   427
};
gabomdq@8062
   428
gabomdq@8062
   429
void
gabomdq@8062
   430
Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
gabomdq@8062
   431
{
gabomdq@8062
   432
    struct SDL_WaylandInput *input;
gabomdq@8062
   433
gabomdq@8135
   434
    input = SDL_calloc(1, sizeof *input);
gabomdq@8062
   435
    if (input == NULL)
gabomdq@8062
   436
        return;
gabomdq@8062
   437
gabomdq@8062
   438
    input->display = d;
gabomdq@8062
   439
    input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
icculus@9554
   440
    input->sx_w = wl_fixed_from_int(0);
icculus@9554
   441
    input->sy_w = wl_fixed_from_int(0);
gabomdq@8062
   442
    d->input = input;
gabomdq@8062
   443
gabomdq@8062
   444
    wl_seat_add_listener(input->seat, &seat_listener, input);
gabomdq@8062
   445
    wl_seat_set_user_data(input->seat, input);
gabomdq@8062
   446
gabomdq@8104
   447
    WAYLAND_wl_display_flush(d->display);
gabomdq@8062
   448
}
gabomdq@8062
   449
gabomdq@8062
   450
void Wayland_display_destroy_input(SDL_VideoData *d)
gabomdq@8062
   451
{
gabomdq@8062
   452
    struct SDL_WaylandInput *input = d->input;
gabomdq@8062
   453
gabomdq@8062
   454
    if (!input)
gabomdq@8062
   455
        return;
gabomdq@8062
   456
gabomdq@8062
   457
    if (input->keyboard)
gabomdq@8062
   458
        wl_keyboard_destroy(input->keyboard);
gabomdq@8062
   459
gabomdq@8062
   460
    if (input->pointer)
gabomdq@8062
   461
        wl_pointer_destroy(input->pointer);
gabomdq@8062
   462
gabomdq@8062
   463
    if (input->seat)
gabomdq@8062
   464
        wl_seat_destroy(input->seat);
gabomdq@8062
   465
gabomdq@8062
   466
    if (input->xkb.state)
gabomdq@8104
   467
        WAYLAND_xkb_state_unref(input->xkb.state);
gabomdq@8062
   468
gabomdq@8062
   469
    if (input->xkb.keymap)
gabomdq@8104
   470
        WAYLAND_xkb_keymap_unref(input->xkb.keymap);
gabomdq@8062
   471
gabomdq@8135
   472
    SDL_free(input);
gabomdq@8062
   473
    d->input = NULL;
gabomdq@8062
   474
}
gabomdq@8062
   475
icculus@8116
   476
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
icculus@8116
   477
gabomdq@8062
   478
/* vi: set ts=4 sw=4 expandtab: */