src/video/wayland/SDL_waylandevents.c
author Gabriel Jacobo
Sat, 14 Dec 2013 20:18:43 -0300
changeset 8062 4fc5f66d63cc
child 8104 2e4f1bd21196
permissions -rw-r--r--
Wayland support

Based on the original port to Wayland by: Joel Teichroeb, Benjamin Franzke, Scott Moreau, et al.

Additional changes in this commit, done by me:

* Wayland uses the common EGL framework
* EGL can now create a desktop OpenGL context
* testgl2 loads GL functions dynamically, no need to link to libGL anymore
* Assorted fixes to the Wayland backend

Tested on the Weston Compositor (v1.0.5) that ships with Ubuntu 13.10,
running Weston under X. Tests ran: testrendercopyex (all backends), testgl2, testgles2,testintersections
gabomdq@8062
     1
/*
gabomdq@8062
     2
  Simple DirectMedia Layer
gabomdq@8062
     3
  Copyright (C) 1997-2013 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@8062
    22
#include "SDL_config.h"
gabomdq@8062
    23
gabomdq@8062
    24
#include "SDL_stdinc.h"
gabomdq@8062
    25
#include "SDL_assert.h"
gabomdq@8062
    26
gabomdq@8062
    27
#include "../../events/SDL_sysevents.h"
gabomdq@8062
    28
#include "../../events/SDL_events_c.h"
gabomdq@8062
    29
#include "../../events/scancodes_xfree86.h"
gabomdq@8062
    30
gabomdq@8062
    31
#include "SDL_waylandvideo.h"
gabomdq@8062
    32
#include "SDL_waylandevents_c.h"
gabomdq@8062
    33
#include "SDL_waylandwindow.h"
gabomdq@8062
    34
gabomdq@8062
    35
#include <linux/input.h>
gabomdq@8062
    36
#include <sys/select.h>
gabomdq@8062
    37
#include <sys/mman.h>
gabomdq@8062
    38
#include <poll.h>
gabomdq@8062
    39
#include <errno.h>
gabomdq@8062
    40
#include <unistd.h>
gabomdq@8062
    41
#include <xkbcommon/xkbcommon.h>
gabomdq@8062
    42
gabomdq@8062
    43
struct SDL_WaylandInput {
gabomdq@8062
    44
    SDL_VideoData *display;
gabomdq@8062
    45
    struct wl_seat *seat;
gabomdq@8062
    46
    struct wl_pointer *pointer;
gabomdq@8062
    47
    struct wl_keyboard *keyboard;
gabomdq@8062
    48
    SDL_WindowData *pointer_focus;
gabomdq@8062
    49
    SDL_WindowData *keyboard_focus;
gabomdq@8062
    50
gabomdq@8062
    51
    struct {
gabomdq@8062
    52
        struct xkb_keymap *keymap;
gabomdq@8062
    53
        struct xkb_state *state;
gabomdq@8062
    54
    } xkb;
gabomdq@8062
    55
};
gabomdq@8062
    56
gabomdq@8062
    57
void
gabomdq@8062
    58
Wayland_PumpEvents(_THIS)
gabomdq@8062
    59
{
gabomdq@8062
    60
    SDL_VideoData *d = _this->driverdata;
gabomdq@8062
    61
    struct pollfd pfd[1];
gabomdq@8062
    62
gabomdq@8062
    63
    pfd[0].fd = wl_display_get_fd(d->display);
gabomdq@8062
    64
    pfd[0].events = POLLIN;
gabomdq@8062
    65
    poll(pfd, 1, 0);
gabomdq@8062
    66
gabomdq@8062
    67
    if (pfd[0].revents & POLLIN)
gabomdq@8062
    68
        wl_display_dispatch(d->display);
gabomdq@8062
    69
    else
gabomdq@8062
    70
        wl_display_dispatch_pending(d->display);
gabomdq@8062
    71
}
gabomdq@8062
    72
gabomdq@8062
    73
static void
gabomdq@8062
    74
pointer_handle_enter(void *data, struct wl_pointer *pointer,
gabomdq@8062
    75
                     uint32_t serial, struct wl_surface *surface,
gabomdq@8062
    76
                     wl_fixed_t sx_w, wl_fixed_t sy_w)
gabomdq@8062
    77
{
gabomdq@8062
    78
    struct SDL_WaylandInput *input = data;
gabomdq@8062
    79
    SDL_WindowData *window;
gabomdq@8062
    80
gabomdq@8062
    81
    if (!surface) {
gabomdq@8062
    82
        /* enter event for a window we've just destroyed */
gabomdq@8062
    83
        return;
gabomdq@8062
    84
    }
gabomdq@8062
    85
gabomdq@8062
    86
    input->pointer_focus = wl_surface_get_user_data(surface);
gabomdq@8062
    87
    window = input->pointer_focus;
gabomdq@8062
    88
    SDL_SetMouseFocus(window->sdlwindow);
gabomdq@8062
    89
}
gabomdq@8062
    90
gabomdq@8062
    91
static void
gabomdq@8062
    92
pointer_handle_leave(void *data, struct wl_pointer *pointer,
gabomdq@8062
    93
                     uint32_t serial, struct wl_surface *surface)
gabomdq@8062
    94
{
gabomdq@8062
    95
    struct SDL_WaylandInput *input = data;
gabomdq@8062
    96
gabomdq@8062
    97
    SDL_SetMouseFocus(NULL);
gabomdq@8062
    98
    input->pointer_focus = NULL;
gabomdq@8062
    99
}
gabomdq@8062
   100
gabomdq@8062
   101
static void
gabomdq@8062
   102
pointer_handle_motion(void *data, struct wl_pointer *pointer,
gabomdq@8062
   103
                      uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
gabomdq@8062
   104
{
gabomdq@8062
   105
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   106
    SDL_WindowData *window = input->pointer_focus;
gabomdq@8062
   107
    int sx = wl_fixed_to_int(sx_w);
gabomdq@8062
   108
    int sy = wl_fixed_to_int(sy_w);
gabomdq@8062
   109
gabomdq@8062
   110
    SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
gabomdq@8062
   111
}
gabomdq@8062
   112
gabomdq@8062
   113
static void
gabomdq@8062
   114
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
gabomdq@8062
   115
                      uint32_t time, uint32_t button, uint32_t state_w)
gabomdq@8062
   116
{
gabomdq@8062
   117
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   118
    SDL_WindowData *window = input->pointer_focus;
gabomdq@8062
   119
    enum wl_pointer_button_state state = state_w;
gabomdq@8062
   120
    uint32_t sdl_button;
gabomdq@8062
   121
gabomdq@8062
   122
    switch (button) {
gabomdq@8062
   123
    case BTN_LEFT:
gabomdq@8062
   124
        sdl_button = SDL_BUTTON_LEFT;
gabomdq@8062
   125
        break;
gabomdq@8062
   126
    case BTN_MIDDLE:
gabomdq@8062
   127
        sdl_button = SDL_BUTTON_MIDDLE;
gabomdq@8062
   128
        break;
gabomdq@8062
   129
    case BTN_RIGHT:
gabomdq@8062
   130
        sdl_button = SDL_BUTTON_RIGHT;
gabomdq@8062
   131
        break;
gabomdq@8062
   132
    case BTN_SIDE:
gabomdq@8062
   133
        sdl_button = SDL_BUTTON_X1;
gabomdq@8062
   134
        break;
gabomdq@8062
   135
    case BTN_EXTRA:
gabomdq@8062
   136
        sdl_button = SDL_BUTTON_X2;
gabomdq@8062
   137
        break;
gabomdq@8062
   138
    default:
gabomdq@8062
   139
        return;
gabomdq@8062
   140
    }
gabomdq@8062
   141
gabomdq@8062
   142
    SDL_SendMouseButton(window->sdlwindow, 0,
gabomdq@8062
   143
                        state ? SDL_PRESSED : SDL_RELEASED, sdl_button);
gabomdq@8062
   144
}
gabomdq@8062
   145
gabomdq@8062
   146
static void
gabomdq@8062
   147
pointer_handle_axis(void *data, struct wl_pointer *pointer,
gabomdq@8062
   148
                    uint32_t time, uint32_t axis, wl_fixed_t value)
gabomdq@8062
   149
{
gabomdq@8062
   150
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   151
    SDL_WindowData *window = input->pointer_focus;
gabomdq@8062
   152
    enum wl_pointer_axis a = axis;
gabomdq@8062
   153
    int x, y;
gabomdq@8062
   154
gabomdq@8062
   155
    switch (a) {
gabomdq@8062
   156
    case WL_POINTER_AXIS_VERTICAL_SCROLL:
gabomdq@8062
   157
        x = 0;
gabomdq@8062
   158
        y = wl_fixed_to_int(value);
gabomdq@8062
   159
        break;
gabomdq@8062
   160
    case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
gabomdq@8062
   161
        x = wl_fixed_to_int(value);
gabomdq@8062
   162
        y = 0;
gabomdq@8062
   163
        break;
gabomdq@8062
   164
    default:
gabomdq@8062
   165
        return;
gabomdq@8062
   166
    }
gabomdq@8062
   167
gabomdq@8062
   168
    SDL_SendMouseWheel(window->sdlwindow, 0, x, y);
gabomdq@8062
   169
}
gabomdq@8062
   170
gabomdq@8062
   171
static const struct wl_pointer_listener pointer_listener = {
gabomdq@8062
   172
    pointer_handle_enter,
gabomdq@8062
   173
    pointer_handle_leave,
gabomdq@8062
   174
    pointer_handle_motion,
gabomdq@8062
   175
    pointer_handle_button,
gabomdq@8062
   176
    pointer_handle_axis,
gabomdq@8062
   177
};
gabomdq@8062
   178
gabomdq@8062
   179
static void
gabomdq@8062
   180
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   181
                       uint32_t format, int fd, uint32_t size)
gabomdq@8062
   182
{
gabomdq@8062
   183
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   184
    char *map_str;
gabomdq@8062
   185
gabomdq@8062
   186
    if (!data) {
gabomdq@8062
   187
        close(fd);
gabomdq@8062
   188
        return;
gabomdq@8062
   189
    }
gabomdq@8062
   190
gabomdq@8062
   191
    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
gabomdq@8062
   192
        close(fd);
gabomdq@8062
   193
        return;
gabomdq@8062
   194
    }
gabomdq@8062
   195
gabomdq@8062
   196
    map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
gabomdq@8062
   197
    if (map_str == MAP_FAILED) {
gabomdq@8062
   198
        close(fd);
gabomdq@8062
   199
        return;
gabomdq@8062
   200
    }
gabomdq@8062
   201
gabomdq@8062
   202
    input->xkb.keymap = xkb_map_new_from_string(input->display->xkb_context,
gabomdq@8062
   203
                                                map_str,
gabomdq@8062
   204
                                                XKB_KEYMAP_FORMAT_TEXT_V1,
gabomdq@8062
   205
                                                0);
gabomdq@8062
   206
    munmap(map_str, size);
gabomdq@8062
   207
    close(fd);
gabomdq@8062
   208
gabomdq@8062
   209
    if (!input->xkb.keymap) {
gabomdq@8062
   210
        fprintf(stderr, "failed to compile keymap\n");
gabomdq@8062
   211
        return;
gabomdq@8062
   212
    }
gabomdq@8062
   213
gabomdq@8062
   214
    input->xkb.state = xkb_state_new(input->xkb.keymap);
gabomdq@8062
   215
    if (!input->xkb.state) {
gabomdq@8062
   216
        fprintf(stderr, "failed to create XKB state\n");
gabomdq@8062
   217
        xkb_map_unref(input->xkb.keymap);
gabomdq@8062
   218
        input->xkb.keymap = NULL;
gabomdq@8062
   219
        return;
gabomdq@8062
   220
    }
gabomdq@8062
   221
}
gabomdq@8062
   222
gabomdq@8062
   223
static void
gabomdq@8062
   224
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   225
                      uint32_t serial, struct wl_surface *surface,
gabomdq@8062
   226
                      struct wl_array *keys)
gabomdq@8062
   227
{
gabomdq@8062
   228
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   229
    SDL_WindowData *window = wl_surface_get_user_data(surface);
gabomdq@8062
   230
gabomdq@8062
   231
    input->keyboard_focus = window;
gabomdq@8062
   232
    window->keyboard_device = input;
gabomdq@8062
   233
    SDL_SetKeyboardFocus(window->sdlwindow);
gabomdq@8062
   234
}
gabomdq@8062
   235
gabomdq@8062
   236
static void
gabomdq@8062
   237
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   238
                      uint32_t serial, struct wl_surface *surface)
gabomdq@8062
   239
{
gabomdq@8062
   240
    SDL_SetKeyboardFocus(NULL);
gabomdq@8062
   241
}
gabomdq@8062
   242
gabomdq@8062
   243
static void
gabomdq@8062
   244
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   245
                    uint32_t serial, uint32_t time, uint32_t key,
gabomdq@8062
   246
                    uint32_t state_w)
gabomdq@8062
   247
{
gabomdq@8062
   248
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   249
    SDL_WindowData *window = input->keyboard_focus;
gabomdq@8062
   250
    enum wl_keyboard_key_state state = state_w;
gabomdq@8062
   251
    const xkb_keysym_t *syms;
gabomdq@8062
   252
    uint32_t scancode;
gabomdq@8062
   253
    char text[8];
gabomdq@8062
   254
    int size;
gabomdq@8062
   255
gabomdq@8062
   256
    if (key < SDL_arraysize(xfree86_scancode_table2)) {
gabomdq@8062
   257
        scancode = xfree86_scancode_table2[key];
gabomdq@8062
   258
gabomdq@8062
   259
        // TODO when do we get WL_KEYBOARD_KEY_STATE_REPEAT?
gabomdq@8062
   260
        if (scancode != SDL_SCANCODE_UNKNOWN)
gabomdq@8062
   261
            SDL_SendKeyboardKey(state == WL_KEYBOARD_KEY_STATE_PRESSED ?
gabomdq@8062
   262
                                SDL_PRESSED : SDL_RELEASED, scancode);
gabomdq@8062
   263
    }
gabomdq@8062
   264
gabomdq@8062
   265
    if (!window || window->keyboard_device != input || !input->xkb.state)
gabomdq@8062
   266
        return;
gabomdq@8062
   267
gabomdq@8062
   268
    // TODO can this happen?
gabomdq@8062
   269
    if (xkb_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
gabomdq@8062
   270
        return;
gabomdq@8062
   271
gabomdq@8062
   272
    if (state) {
gabomdq@8062
   273
        size = xkb_keysym_to_utf8(syms[0], text, sizeof text);
gabomdq@8062
   274
gabomdq@8062
   275
        if (size > 0) {
gabomdq@8062
   276
            text[size] = 0;
gabomdq@8062
   277
            SDL_SendKeyboardText(text);
gabomdq@8062
   278
        }
gabomdq@8062
   279
    }
gabomdq@8062
   280
}
gabomdq@8062
   281
gabomdq@8062
   282
static void
gabomdq@8062
   283
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
gabomdq@8062
   284
                          uint32_t serial, uint32_t mods_depressed,
gabomdq@8062
   285
                          uint32_t mods_latched, uint32_t mods_locked,
gabomdq@8062
   286
                          uint32_t group)
gabomdq@8062
   287
{
gabomdq@8062
   288
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   289
gabomdq@8062
   290
    xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
gabomdq@8062
   291
                          mods_locked, 0, 0, group);
gabomdq@8062
   292
}
gabomdq@8062
   293
gabomdq@8062
   294
static const struct wl_keyboard_listener keyboard_listener = {
gabomdq@8062
   295
    keyboard_handle_keymap,
gabomdq@8062
   296
    keyboard_handle_enter,
gabomdq@8062
   297
    keyboard_handle_leave,
gabomdq@8062
   298
    keyboard_handle_key,
gabomdq@8062
   299
    keyboard_handle_modifiers,
gabomdq@8062
   300
};
gabomdq@8062
   301
gabomdq@8062
   302
static void
gabomdq@8062
   303
seat_handle_capabilities(void *data, struct wl_seat *seat,
gabomdq@8062
   304
                         enum wl_seat_capability caps)
gabomdq@8062
   305
{
gabomdq@8062
   306
    struct SDL_WaylandInput *input = data;
gabomdq@8062
   307
gabomdq@8062
   308
    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
gabomdq@8062
   309
        input->pointer = wl_seat_get_pointer(seat);
gabomdq@8062
   310
        input->display->pointer = input->pointer;
gabomdq@8062
   311
        wl_pointer_set_user_data(input->pointer, input);
gabomdq@8062
   312
        wl_pointer_add_listener(input->pointer, &pointer_listener,
gabomdq@8062
   313
                                input);
gabomdq@8062
   314
    } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
gabomdq@8062
   315
        wl_pointer_destroy(input->pointer);
gabomdq@8062
   316
        input->pointer = NULL;
gabomdq@8062
   317
    }
gabomdq@8062
   318
gabomdq@8062
   319
    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
gabomdq@8062
   320
        input->keyboard = wl_seat_get_keyboard(seat);
gabomdq@8062
   321
        wl_keyboard_set_user_data(input->keyboard, input);
gabomdq@8062
   322
        wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
gabomdq@8062
   323
                                 input);
gabomdq@8062
   324
    } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
gabomdq@8062
   325
        wl_keyboard_destroy(input->keyboard);
gabomdq@8062
   326
        input->keyboard = NULL;
gabomdq@8062
   327
    }
gabomdq@8062
   328
}
gabomdq@8062
   329
gabomdq@8062
   330
static const struct wl_seat_listener seat_listener = {
gabomdq@8062
   331
    seat_handle_capabilities,
gabomdq@8062
   332
};
gabomdq@8062
   333
gabomdq@8062
   334
void
gabomdq@8062
   335
Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
gabomdq@8062
   336
{
gabomdq@8062
   337
    struct SDL_WaylandInput *input;
gabomdq@8062
   338
gabomdq@8062
   339
    input = malloc(sizeof *input);
gabomdq@8062
   340
    if (input == NULL)
gabomdq@8062
   341
        return;
gabomdq@8062
   342
gabomdq@8062
   343
    memset(input, 0, sizeof *input);
gabomdq@8062
   344
    input->display = d;
gabomdq@8062
   345
    input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
gabomdq@8062
   346
gabomdq@8062
   347
    d->input = input;
gabomdq@8062
   348
gabomdq@8062
   349
    wl_seat_add_listener(input->seat, &seat_listener, input);
gabomdq@8062
   350
    wl_seat_set_user_data(input->seat, input);
gabomdq@8062
   351
gabomdq@8062
   352
    wayland_schedule_write(d);
gabomdq@8062
   353
}
gabomdq@8062
   354
gabomdq@8062
   355
void Wayland_display_destroy_input(SDL_VideoData *d)
gabomdq@8062
   356
{
gabomdq@8062
   357
    struct SDL_WaylandInput *input = d->input;
gabomdq@8062
   358
gabomdq@8062
   359
    if (!input)
gabomdq@8062
   360
        return;
gabomdq@8062
   361
gabomdq@8062
   362
    if (input->keyboard)
gabomdq@8062
   363
        wl_keyboard_destroy(input->keyboard);
gabomdq@8062
   364
gabomdq@8062
   365
    if (input->pointer)
gabomdq@8062
   366
        wl_pointer_destroy(input->pointer);
gabomdq@8062
   367
gabomdq@8062
   368
    if (input->seat)
gabomdq@8062
   369
        wl_seat_destroy(input->seat);
gabomdq@8062
   370
gabomdq@8062
   371
    if (input->xkb.state)
gabomdq@8062
   372
        xkb_state_unref(input->xkb.state);
gabomdq@8062
   373
gabomdq@8062
   374
    if (input->xkb.keymap)
gabomdq@8062
   375
        xkb_map_unref(input->xkb.keymap);
gabomdq@8062
   376
gabomdq@8062
   377
    free(input);
gabomdq@8062
   378
    d->input = NULL;
gabomdq@8062
   379
}
gabomdq@8062
   380
gabomdq@8062
   381
/* vi: set ts=4 sw=4 expandtab: */