Fixed crash if initialization of EGL failed but was tried again later.

The internal function SDL_EGL_LoadLibrary() did not delete and remove a mostly
uninitialized data structure if loading the library first failed. A later try to
use EGL then skipped initialization and assumed it was previously successful
because the data structure now already existed. This led to at least one crash
in the internal function SDL_EGL_ChooseConfig() because a NULL pointer was
dereferenced to make a call to eglBindAPI().
This commit is contained in:
Philipp Wiesemann
2015-06-21 17:33:46 +02:00
commit 0e45984fa0
1596 changed files with 468120 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND
#define DEBUG_DYNAMIC_WAYLAND 0
#include "SDL_waylanddyn.h"
#if DEBUG_DYNAMIC_WAYLAND
#include "SDL_log.h"
#endif
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
#include "SDL_name.h"
#include "SDL_loadso.h"
typedef struct
{
void *lib;
const char *libname;
} waylanddynlib;
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON NULL
#endif
static waylanddynlib waylandlibs[] = {
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON}
};
static void *
WAYLAND_GetSym(const char *fnname, int *pHasModule)
{
int i;
void *fn = NULL;
for (i = 0; i < SDL_TABLESIZE(waylandlibs); i++) {
if (waylandlibs[i].lib != NULL) {
fn = SDL_LoadFunction(waylandlibs[i].lib, fnname);
if (fn != NULL)
break;
}
}
#if DEBUG_DYNAMIC_WAYLAND
if (fn != NULL)
SDL_Log("WAYLAND: Found '%s' in %s (%p)\n", fnname, waylandlibs[i].libname, fn);
else
SDL_Log("WAYLAND: Symbol '%s' NOT FOUND!\n", fnname);
#endif
if (fn == NULL)
*pHasModule = 0; /* kill this module. */
return fn;
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */
/* Define all the function pointers and wrappers... */
#define SDL_WAYLAND_MODULE(modname) int SDL_WAYLAND_HAVE_##modname = 0;
#define SDL_WAYLAND_SYM(rc,fn,params) SDL_DYNWAYLANDFN_##fn WAYLAND_##fn = NULL;
#define SDL_WAYLAND_INTERFACE(iface) const struct wl_interface *WAYLAND_##iface = NULL;
#include "SDL_waylandsym.h"
#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE
static int wayland_load_refcount = 0;
void
SDL_WAYLAND_UnloadSymbols(void)
{
/* Don't actually unload if more than one module is using the libs... */
if (wayland_load_refcount > 0) {
if (--wayland_load_refcount == 0) {
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
int i;
#endif
/* set all the function pointers to NULL. */
#define SDL_WAYLAND_MODULE(modname) SDL_WAYLAND_HAVE_##modname = 0;
#define SDL_WAYLAND_SYM(rc,fn,params) WAYLAND_##fn = NULL;
#define SDL_WAYLAND_INTERFACE(iface) WAYLAND_##iface = NULL;
#include "SDL_waylandsym.h"
#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
for (i = 0; i < SDL_TABLESIZE(waylandlibs); i++) {
if (waylandlibs[i].lib != NULL) {
SDL_UnloadObject(waylandlibs[i].lib);
waylandlibs[i].lib = NULL;
}
}
#endif
}
}
}
/* returns non-zero if all needed symbols were loaded. */
int
SDL_WAYLAND_LoadSymbols(void)
{
int rc = 1; /* always succeed if not using Dynamic WAYLAND stuff. */
/* deal with multiple modules (dga, wayland, etc) needing these symbols... */
if (wayland_load_refcount++ == 0) {
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
int i;
int *thismod = NULL;
for (i = 0; i < SDL_TABLESIZE(waylandlibs); i++) {
if (waylandlibs[i].libname != NULL) {
waylandlibs[i].lib = SDL_LoadObject(waylandlibs[i].libname);
}
}
#define SDL_WAYLAND_MODULE(modname) SDL_WAYLAND_HAVE_##modname = 1; /* default yes */
#define SDL_WAYLAND_SYM(rc,fn,params)
#define SDL_WAYLAND_INTERFACE(iface)
#include "SDL_waylandsym.h"
#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE
#define SDL_WAYLAND_MODULE(modname) thismod = &SDL_WAYLAND_HAVE_##modname;
#define SDL_WAYLAND_SYM(rc,fn,params) WAYLAND_##fn = (SDL_DYNWAYLANDFN_##fn) WAYLAND_GetSym(#fn,thismod);
#define SDL_WAYLAND_INTERFACE(iface) WAYLAND_##iface = (struct wl_interface *) WAYLAND_GetSym(#iface,thismod);
#include "SDL_waylandsym.h"
#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE
if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT) {
/* all required symbols loaded. */
SDL_ClearError();
} else {
/* in case something got loaded... */
SDL_WAYLAND_UnloadSymbols();
rc = 0;
}
#else /* no dynamic WAYLAND */
#define SDL_WAYLAND_MODULE(modname) SDL_WAYLAND_HAVE_##modname = 1; /* default yes */
#define SDL_WAYLAND_SYM(rc,fn,params) WAYLAND_##fn = fn;
#define SDL_WAYLAND_INTERFACE(iface) WAYLAND_##iface = &iface;
#include "SDL_waylandsym.h"
#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE
#endif
}
return rc;
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,104 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _SDL_waylanddyn_h
#define _SDL_waylanddyn_h
#include "../../SDL_internal.h"
/* We can't include wayland-client.h here
* but we need some structs from it
*/
struct wl_interface;
struct wl_proxy;
struct wl_event_queue;
struct wl_display;
struct wl_surface;
struct wl_shm;
#include <stdint.h>
#include "wayland-cursor.h"
#include "wayland-util.h"
#include "xkbcommon/xkbcommon.h"
#ifdef __cplusplus
extern "C"
{
#endif
int SDL_WAYLAND_LoadSymbols(void);
void SDL_WAYLAND_UnloadSymbols(void);
#define SDL_WAYLAND_MODULE(modname) extern int SDL_WAYLAND_HAVE_##modname;
#define SDL_WAYLAND_SYM(rc,fn,params) \
typedef rc (*SDL_DYNWAYLANDFN_##fn) params; \
extern SDL_DYNWAYLANDFN_##fn WAYLAND_##fn;
#define SDL_WAYLAND_INTERFACE(iface) extern const struct wl_interface *WAYLAND_##iface;
#include "SDL_waylandsym.h"
#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE
#ifdef __cplusplus
}
#endif
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
#ifdef _WAYLAND_CLIENT_H
#error Do not include wayland-client ahead of SDL_waylanddyn.h in dynamic loading mode
#endif
/* wayland-client-protocol.h included from wayland-client.h
* has inline functions that require these to be defined in dynamic loading mode
*/
#define wl_proxy_create (*WAYLAND_wl_proxy_create)
#define wl_proxy_destroy (*WAYLAND_wl_proxy_destroy)
#define wl_proxy_marshal (*WAYLAND_wl_proxy_marshal)
#define wl_proxy_set_user_data (*WAYLAND_wl_proxy_set_user_data)
#define wl_proxy_get_user_data (*WAYLAND_wl_proxy_get_user_data)
#define wl_proxy_add_listener (*WAYLAND_wl_proxy_add_listener)
#define wl_proxy_marshal_constructor (*WAYLAND_wl_proxy_marshal_constructor)
#define wl_seat_interface (*WAYLAND_wl_seat_interface)
#define wl_surface_interface (*WAYLAND_wl_surface_interface)
#define wl_shm_pool_interface (*WAYLAND_wl_shm_pool_interface)
#define wl_buffer_interface (*WAYLAND_wl_buffer_interface)
#define wl_registry_interface (*WAYLAND_wl_registry_interface)
#define wl_shell_surface_interface (*WAYLAND_wl_shell_surface_interface)
#define wl_region_interface (*WAYLAND_wl_region_interface)
#define wl_pointer_interface (*WAYLAND_wl_pointer_interface)
#define wl_keyboard_interface (*WAYLAND_wl_keyboard_interface)
#define wl_compositor_interface (*WAYLAND_wl_compositor_interface)
#define wl_output_interface (*WAYLAND_wl_output_interface)
#define wl_shell_interface (*WAYLAND_wl_shell_interface)
#define wl_shm_interface (*WAYLAND_wl_shm_interface)
#endif /* SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */
#include "wayland-client.h"
#include "wayland-egl.h"
#endif /* !defined _SDL_waylanddyn_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,459 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND
#include "SDL_stdinc.h"
#include "SDL_assert.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
#include "../../events/scancodes_xfree86.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylanddyn.h"
#include <linux/input.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <poll.h>
#include <errno.h>
#include <unistd.h>
#include <xkbcommon/xkbcommon.h>
struct SDL_WaylandInput {
SDL_VideoData *display;
struct wl_seat *seat;
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
SDL_WindowData *pointer_focus;
SDL_WindowData *keyboard_focus;
/* Last motion location */
wl_fixed_t sx_w;
wl_fixed_t sy_w;
struct {
struct xkb_keymap *keymap;
struct xkb_state *state;
} xkb;
};
void
Wayland_PumpEvents(_THIS)
{
SDL_VideoData *d = _this->driverdata;
struct pollfd pfd[1];
pfd[0].fd = WAYLAND_wl_display_get_fd(d->display);
pfd[0].events = POLLIN;
poll(pfd, 1, 0);
if (pfd[0].revents & POLLIN)
WAYLAND_wl_display_dispatch(d->display);
else
WAYLAND_wl_display_dispatch_pending(d->display);
}
static void
pointer_handle_enter(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window;
if (!surface) {
/* enter event for a window we've just destroyed */
return;
}
/* This handler will be called twice in Wayland 1.4
* Once for the window surface which has valid user data
* and again for the mouse cursor surface which does not have valid user data
* We ignore the later
*/
window = (SDL_WindowData *)wl_surface_get_user_data(surface);
if (window) {
input->pointer_focus = window;
SDL_SetMouseFocus(window->sdlwindow);
}
}
static void
pointer_handle_leave(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface)
{
struct SDL_WaylandInput *input = data;
if (input->pointer_focus) {
SDL_SetMouseFocus(NULL);
input->pointer_focus = NULL;
}
}
static void
pointer_handle_motion(void *data, struct wl_pointer *pointer,
uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
input->sx_w = sx_w;
input->sy_w = sy_w;
if (input->pointer_focus) {
const int sx = wl_fixed_to_int(sx_w);
const int sy = wl_fixed_to_int(sy_w);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
}
static SDL_bool
ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
{
SDL_WindowData *window_data = input->pointer_focus;
SDL_Window *window = window_data->sdlwindow;
if (window->hit_test) {
const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
static const uint32_t directions[] = {
WL_SHELL_SURFACE_RESIZE_TOP_LEFT, WL_SHELL_SURFACE_RESIZE_TOP,
WL_SHELL_SURFACE_RESIZE_TOP_RIGHT, WL_SHELL_SURFACE_RESIZE_RIGHT,
WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, WL_SHELL_SURFACE_RESIZE_BOTTOM,
WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT, WL_SHELL_SURFACE_RESIZE_LEFT
};
switch (rc) {
case SDL_HITTEST_DRAGGABLE:
wl_shell_surface_move(window_data->shell_surface, input->seat, serial);
return SDL_TRUE;
case SDL_HITTEST_RESIZE_TOPLEFT:
case SDL_HITTEST_RESIZE_TOP:
case SDL_HITTEST_RESIZE_TOPRIGHT:
case SDL_HITTEST_RESIZE_RIGHT:
case SDL_HITTEST_RESIZE_BOTTOMRIGHT:
case SDL_HITTEST_RESIZE_BOTTOM:
case SDL_HITTEST_RESIZE_BOTTOMLEFT:
case SDL_HITTEST_RESIZE_LEFT:
wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
return SDL_TRUE;
default: return SDL_FALSE;
}
}
return SDL_FALSE;
}
static void
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_button_state state = state_w;
uint32_t sdl_button;
if (input->pointer_focus) {
switch (button) {
case BTN_LEFT:
sdl_button = SDL_BUTTON_LEFT;
if (ProcessHitTest(data, serial)) {
return; /* don't pass this event on to app. */
}
break;
case BTN_MIDDLE:
sdl_button = SDL_BUTTON_MIDDLE;
break;
case BTN_RIGHT:
sdl_button = SDL_BUTTON_RIGHT;
break;
case BTN_SIDE:
sdl_button = SDL_BUTTON_X1;
break;
case BTN_EXTRA:
sdl_button = SDL_BUTTON_X2;
break;
default:
return;
}
SDL_SendMouseButton(window->sdlwindow, 0,
state ? SDL_PRESSED : SDL_RELEASED, sdl_button);
}
}
static void
pointer_handle_axis(void *data, struct wl_pointer *pointer,
uint32_t time, uint32_t axis, wl_fixed_t value)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_axis a = axis;
int x, y;
if (input->pointer_focus) {
switch (a) {
case WL_POINTER_AXIS_VERTICAL_SCROLL:
x = 0;
y = wl_fixed_to_int(value);
break;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
x = wl_fixed_to_int(value);
y = 0;
break;
default:
return;
}
SDL_SendMouseWheel(window->sdlwindow, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
}
}
static const struct wl_pointer_listener pointer_listener = {
pointer_handle_enter,
pointer_handle_leave,
pointer_handle_motion,
pointer_handle_button,
pointer_handle_axis,
};
static void
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
uint32_t format, int fd, uint32_t size)
{
struct SDL_WaylandInput *input = data;
char *map_str;
if (!data) {
close(fd);
return;
}
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
close(fd);
return;
}
map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (map_str == MAP_FAILED) {
close(fd);
return;
}
input->xkb.keymap = WAYLAND_xkb_keymap_new_from_string(input->display->xkb_context,
map_str,
XKB_KEYMAP_FORMAT_TEXT_V1,
0);
munmap(map_str, size);
close(fd);
if (!input->xkb.keymap) {
fprintf(stderr, "failed to compile keymap\n");
return;
}
input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap);
if (!input->xkb.state) {
fprintf(stderr, "failed to create XKB state\n");
WAYLAND_xkb_keymap_unref(input->xkb.keymap);
input->xkb.keymap = NULL;
return;
}
}
static void
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface,
struct wl_array *keys)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window;
if (!surface) {
/* enter event for a window we've just destroyed */
return;
}
window = wl_surface_get_user_data(surface);
input->keyboard_focus = window;
window->keyboard_device = input;
if (window) {
SDL_SetKeyboardFocus(window->sdlwindow);
}
}
static void
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface)
{
SDL_SetKeyboardFocus(NULL);
}
static void
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t time, uint32_t key,
uint32_t state_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->keyboard_focus;
enum wl_keyboard_key_state state = state_w;
const xkb_keysym_t *syms;
uint32_t scancode;
char text[8];
int size;
if (key < SDL_arraysize(xfree86_scancode_table2)) {
scancode = xfree86_scancode_table2[key];
// TODO when do we get WL_KEYBOARD_KEY_STATE_REPEAT?
if (scancode != SDL_SCANCODE_UNKNOWN)
SDL_SendKeyboardKey(state == WL_KEYBOARD_KEY_STATE_PRESSED ?
SDL_PRESSED : SDL_RELEASED, scancode);
}
if (!window || window->keyboard_device != input || !input->xkb.state)
return;
// TODO can this happen?
if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
return;
if (state) {
size = WAYLAND_xkb_keysym_to_utf8(syms[0], text, sizeof text);
if (size > 0) {
text[size] = 0;
SDL_SendKeyboardText(text);
}
}
}
static void
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t mods_depressed,
uint32_t mods_latched, uint32_t mods_locked,
uint32_t group)
{
struct SDL_WaylandInput *input = data;
WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
mods_locked, 0, 0, group);
}
static const struct wl_keyboard_listener keyboard_listener = {
keyboard_handle_keymap,
keyboard_handle_enter,
keyboard_handle_leave,
keyboard_handle_key,
keyboard_handle_modifiers,
};
static void
seat_handle_capabilities(void *data, struct wl_seat *seat,
enum wl_seat_capability caps)
{
struct SDL_WaylandInput *input = data;
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
input->pointer = wl_seat_get_pointer(seat);
input->display->pointer = input->pointer;
wl_pointer_set_user_data(input->pointer, input);
wl_pointer_add_listener(input->pointer, &pointer_listener,
input);
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
wl_pointer_destroy(input->pointer);
input->pointer = NULL;
}
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
input->keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_set_user_data(input->keyboard, input);
wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
input);
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
wl_keyboard_destroy(input->keyboard);
input->keyboard = NULL;
}
}
static const struct wl_seat_listener seat_listener = {
seat_handle_capabilities,
};
void
Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
{
struct SDL_WaylandInput *input;
input = SDL_calloc(1, sizeof *input);
if (input == NULL)
return;
input->display = d;
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
input->sx_w = wl_fixed_from_int(0);
input->sy_w = wl_fixed_from_int(0);
d->input = input;
wl_seat_add_listener(input->seat, &seat_listener, input);
wl_seat_set_user_data(input->seat, input);
WAYLAND_wl_display_flush(d->display);
}
void Wayland_display_destroy_input(SDL_VideoData *d)
{
struct SDL_WaylandInput *input = d->input;
if (!input)
return;
if (input->keyboard)
wl_keyboard_destroy(input->keyboard);
if (input->pointer)
wl_pointer_destroy(input->pointer);
if (input->seat)
wl_seat_destroy(input->seat);
if (input->xkb.state)
WAYLAND_xkb_state_unref(input->xkb.state);
if (input->xkb.keymap)
WAYLAND_xkb_keymap_unref(input->xkb.keymap);
SDL_free(input);
d->input = NULL;
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,37 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifndef _SDL_waylandevents_h
#define _SDL_waylandevents_h
#include "SDL_waylandvideo.h"
#include "SDL_waylandwindow.h"
extern void Wayland_PumpEvents(_THIS);
extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id);
extern void Wayland_display_destroy_input(SDL_VideoData *d);
#endif /* _SDL_waylandevents_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,403 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include "../SDL_sysvideo.h"
#include "SDL_mouse.h"
#include "../../events/SDL_mouse_c.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylanddyn.h"
#include "wayland-cursor.h"
#include "SDL_assert.h"
typedef struct {
struct wl_buffer *buffer;
struct wl_surface *surface;
int hot_x, hot_y;
int w, h;
/* Either a preloaded cursor, or one we created ourselves */
struct wl_cursor *cursor;
void *shm_data;
} Wayland_CursorData;
static int
wayland_create_tmp_file(off_t size)
{
static const char template[] = "/sdl-shared-XXXXXX";
char *xdg_path;
char tmp_path[PATH_MAX];
int fd;
xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
if (!xdg_path) {
errno = ENOENT;
return -1;
}
SDL_strlcpy(tmp_path, xdg_path, PATH_MAX);
SDL_strlcat(tmp_path, template, PATH_MAX);
fd = mkostemp(tmp_path, O_CLOEXEC);
if (fd < 0)
return -1;
if (ftruncate(fd, size) < 0) {
close(fd);
return -1;
}
return fd;
}
static void
mouse_buffer_release(void *data, struct wl_buffer *buffer)
{
}
static const struct wl_buffer_listener mouse_buffer_listener = {
mouse_buffer_release
};
static int
create_buffer_from_shm(Wayland_CursorData *d,
int width,
int height,
uint32_t format)
{
SDL_VideoDevice *vd = SDL_GetVideoDevice();
SDL_VideoData *data = (SDL_VideoData *) vd->driverdata;
struct wl_shm_pool *shm_pool;
int stride = width * 4;
int size = stride * height;
int shm_fd;
shm_fd = wayland_create_tmp_file(size);
if (shm_fd < 0)
{
fprintf(stderr, "creating mouse cursor buffer failed!\n");
return -1;
}
d->shm_data = mmap(NULL,
size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
shm_fd,
0);
if (d->shm_data == MAP_FAILED) {
d->shm_data = NULL;
fprintf (stderr, "mmap () failed\n");
close (shm_fd);
}
shm_pool = wl_shm_create_pool(data->shm, shm_fd, size);
d->buffer = wl_shm_pool_create_buffer(shm_pool,
0,
width,
height,
stride,
format);
wl_buffer_add_listener(d->buffer,
&mouse_buffer_listener,
d);
wl_shm_pool_destroy (shm_pool);
close (shm_fd);
return 0;
}
static SDL_Cursor *
Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
{
SDL_Cursor *cursor;
cursor = calloc(1, sizeof (*cursor));
if (cursor) {
SDL_VideoDevice *vd = SDL_GetVideoDevice ();
SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata;
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
cursor->driverdata = (void *) data;
/* Assume ARGB8888 */
SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
SDL_assert(surface->pitch == surface->w * 4);
/* Allocate shared memory buffer for this cursor */
if (create_buffer_from_shm (data,
surface->w,
surface->h,
WL_SHM_FORMAT_XRGB8888) < 0)
{
free (cursor->driverdata);
free (cursor);
return NULL;
}
SDL_memcpy(data->shm_data,
surface->pixels,
surface->h * surface->pitch);
data->surface = wl_compositor_create_surface(wd->compositor);
wl_surface_set_user_data(data->surface, NULL);
data->hot_x = hot_x;
data->hot_y = hot_y;
data->w = surface->w;
data->h = surface->h;
}
return cursor;
}
static SDL_Cursor *
CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
{
SDL_Cursor *cursor;
cursor = calloc(1, sizeof (*cursor));
if (cursor) {
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
cursor->driverdata = (void *) data;
data->buffer = WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]);
data->surface = wl_compositor_create_surface(d->compositor);
wl_surface_set_user_data(data->surface, NULL);
data->hot_x = wlcursor->images[0]->hotspot_x;
data->hot_y = wlcursor->images[0]->hotspot_y;
data->w = wlcursor->images[0]->width;
data->h = wlcursor->images[0]->height;
data->cursor= wlcursor;
} else {
SDL_OutOfMemory ();
}
return cursor;
}
static SDL_Cursor *
Wayland_CreateDefaultCursor()
{
SDL_VideoDevice *device = SDL_GetVideoDevice();
SDL_VideoData *data = device->driverdata;
return CreateCursorFromWlCursor (data,
WAYLAND_wl_cursor_theme_get_cursor(data->cursor_theme,
"left_ptr"));
}
static SDL_Cursor *
Wayland_CreateSystemCursor(SDL_SystemCursor id)
{
SDL_VideoDevice *vd = SDL_GetVideoDevice();
SDL_VideoData *d = vd->driverdata;
struct wl_cursor *cursor = NULL;
switch(id)
{
default:
SDL_assert(0);
return NULL;
case SDL_SYSTEM_CURSOR_ARROW:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
break;
case SDL_SYSTEM_CURSOR_IBEAM:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
break;
case SDL_SYSTEM_CURSOR_WAIT:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
break;
case SDL_SYSTEM_CURSOR_CROSSHAIR:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_WAITARROW:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "watch");
break;
case SDL_SYSTEM_CURSOR_SIZENWSE:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZENESW:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZEWE:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZENS:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZEALL:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_NO:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
break;
case SDL_SYSTEM_CURSOR_HAND:
cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
}
return CreateCursorFromWlCursor(d, cursor);
}
static void
Wayland_FreeCursor(SDL_Cursor *cursor)
{
Wayland_CursorData *d;
if (!cursor)
return;
d = cursor->driverdata;
/* Probably not a cursor we own */
if (!d)
return;
if (d->buffer && !d->cursor)
wl_buffer_destroy(d->buffer);
if (d->surface)
wl_surface_destroy(d->surface);
/* Not sure what's meant to happen to shm_data */
free (cursor->driverdata);
SDL_free(cursor);
}
static int
Wayland_ShowCursor(SDL_Cursor *cursor)
{
SDL_VideoDevice *vd = SDL_GetVideoDevice();
SDL_VideoData *d = vd->driverdata;
struct wl_pointer *pointer = d->pointer;
if (!pointer)
return -1;
if (cursor)
{
Wayland_CursorData *data = cursor->driverdata;
wl_surface_attach(data->surface, data->buffer, 0, 0);
wl_surface_damage(data->surface, 0, 0, data->w, data->h);
wl_surface_commit(data->surface);
wl_pointer_set_cursor (pointer, 0,
data->surface,
data->hot_x,
data->hot_y);
}
else
{
wl_pointer_set_cursor (pointer, 0,
NULL,
0,
0);
}
return 0;
}
static void
Wayland_WarpMouse(SDL_Window *window, int x, int y)
{
SDL_Unsupported();
}
static void
Wayland_WarpMouseGlobal(int x, int y)
{
SDL_Unsupported();
}
static int
Wayland_SetRelativeMouseMode(SDL_bool enabled)
{
return SDL_Unsupported();
}
void
Wayland_InitMouse(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
mouse->CreateCursor = Wayland_CreateCursor;
mouse->CreateSystemCursor = Wayland_CreateSystemCursor;
mouse->ShowCursor = Wayland_ShowCursor;
mouse->FreeCursor = Wayland_FreeCursor;
mouse->WarpMouse = Wayland_WarpMouse;
mouse->WarpMouseGlobal = Wayland_WarpMouseGlobal;
mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode;
SDL_SetDefaultCursor(Wayland_CreateDefaultCursor());
}
void
Wayland_FiniMouse(void)
{
/* This effectively assumes that nobody else
* touches SDL_Mouse which is effectively
* a singleton */
SDL_Mouse *mouse = SDL_GetMouse();
/* Free the current cursor if not the same pointer as
* the default cursor */
if (mouse->def_cursor != mouse->cur_cursor)
Wayland_FreeCursor (mouse->cur_cursor);
Wayland_FreeCursor (mouse->def_cursor);
mouse->def_cursor = NULL;
mouse->cur_cursor = NULL;
mouse->CreateCursor = NULL;
mouse->CreateSystemCursor = NULL;
mouse->ShowCursor = NULL;
mouse->FreeCursor = NULL;
mouse->WarpMouse = NULL;
mouse->SetRelativeMouseMode = NULL;
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND */

View File

@@ -0,0 +1,31 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#include "SDL_mouse.h"
#include "SDL_waylandvideo.h"
#if SDL_VIDEO_DRIVER_WAYLAND
extern void Wayland_InitMouse(void);
extern void Wayland_FiniMouse(void);
#endif

View File

@@ -0,0 +1,91 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL
#include "SDL_waylandvideo.h"
#include "SDL_waylandopengles.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylanddyn.h"
/* EGL implementation of SDL OpenGL ES support */
int
Wayland_GLES_LoadLibrary(_THIS, const char *path) {
int ret;
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display);
Wayland_PumpEvents(_this);
WAYLAND_wl_display_flush(data->display);
return ret;
}
SDL_GLContext
Wayland_GLES_CreateContext(_THIS, SDL_Window * window)
{
SDL_GLContext context;
context = SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
return context;
}
void
Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
{
SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
}
int
Wayland_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
int ret;
if (window && context) {
ret = SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
}
else {
ret = SDL_EGL_MakeCurrent(_this, NULL, NULL);
}
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
return ret;
}
void
Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context)
{
SDL_EGL_DeleteContext(_this, context);
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,46 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifndef _SDL_waylandopengles_h
#define _SDL_waylandopengles_h
#include "../SDL_sysvideo.h"
#include "../SDL_egl_c.h"
typedef struct SDL_PrivateGLESData
{
} SDL_PrivateGLESData;
/* OpenGLES functions */
#define Wayland_GLES_GetAttribute SDL_EGL_GetAttribute
#define Wayland_GLES_GetProcAddress SDL_EGL_GetProcAddress
#define Wayland_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define Wayland_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
#define Wayland_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
extern int Wayland_GLES_LoadLibrary(_THIS, const char *path);
extern SDL_GLContext Wayland_GLES_CreateContext(_THIS, SDL_Window * window);
extern void Wayland_GLES_SwapWindow(_THIS, SDL_Window * window);
extern int Wayland_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
extern void Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context);
#endif /* _SDL_waylandopengles_h */

View File

@@ -0,0 +1,106 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* *INDENT-OFF* */
SDL_WAYLAND_MODULE(WAYLAND_CLIENT)
SDL_WAYLAND_SYM(void, wl_proxy_marshal, (struct wl_proxy *, uint32_t, ...))
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_create, (struct wl_proxy *, const struct wl_interface *))
SDL_WAYLAND_SYM(void, wl_proxy_destroy, (struct wl_proxy *))
SDL_WAYLAND_SYM(int, wl_proxy_add_listener, (struct wl_proxy *, void (**)(void), void *))
SDL_WAYLAND_SYM(void, wl_proxy_set_user_data, (struct wl_proxy *, void *))
SDL_WAYLAND_SYM(void *, wl_proxy_get_user_data, (struct wl_proxy *))
SDL_WAYLAND_SYM(uint32_t, wl_proxy_get_id, (struct wl_proxy *))
SDL_WAYLAND_SYM(const char *, wl_proxy_get_class, (struct wl_proxy *))
SDL_WAYLAND_SYM(void, wl_proxy_set_queue, (struct wl_proxy *, struct wl_event_queue *))
SDL_WAYLAND_SYM(struct wl_display *, wl_display_connect, (const char *))
SDL_WAYLAND_SYM(struct wl_display *, wl_display_connect_to_fd, (int))
SDL_WAYLAND_SYM(void, wl_display_disconnect, (struct wl_display *))
SDL_WAYLAND_SYM(int, wl_display_get_fd, (struct wl_display *))
SDL_WAYLAND_SYM(int, wl_display_dispatch, (struct wl_display *))
SDL_WAYLAND_SYM(int, wl_display_dispatch_queue, (struct wl_display *, struct wl_event_queue *))
SDL_WAYLAND_SYM(int, wl_display_dispatch_queue_pending, (struct wl_display *, struct wl_event_queue *))
SDL_WAYLAND_SYM(int, wl_display_dispatch_pending, (struct wl_display *))
SDL_WAYLAND_SYM(int, wl_display_get_error, (struct wl_display *))
SDL_WAYLAND_SYM(int, wl_display_flush, (struct wl_display *))
SDL_WAYLAND_SYM(int, wl_display_roundtrip, (struct wl_display *))
SDL_WAYLAND_SYM(struct wl_event_queue *, wl_display_create_queue, (struct wl_display *))
SDL_WAYLAND_SYM(void, wl_log_set_handler_client, (wl_log_func_t))
SDL_WAYLAND_SYM(void, wl_list_init, (struct wl_list *))
SDL_WAYLAND_SYM(void, wl_list_insert, (struct wl_list *, struct wl_list *) )
SDL_WAYLAND_SYM(void, wl_list_remove, (struct wl_list *))
SDL_WAYLAND_SYM(int, wl_list_length, (const struct wl_list *))
SDL_WAYLAND_SYM(int, wl_list_empty, (const struct wl_list *))
SDL_WAYLAND_SYM(void, wl_list_insert_list, (struct wl_list *, struct wl_list *))
/* These functions are available in Wayland >= 1.4 */
SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_4)
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor, (struct wl_proxy *, uint32_t opcode, const struct wl_interface *interface, ...))
SDL_WAYLAND_INTERFACE(wl_seat_interface)
SDL_WAYLAND_INTERFACE(wl_surface_interface)
SDL_WAYLAND_INTERFACE(wl_shm_pool_interface)
SDL_WAYLAND_INTERFACE(wl_buffer_interface)
SDL_WAYLAND_INTERFACE(wl_registry_interface)
SDL_WAYLAND_INTERFACE(wl_shell_surface_interface)
SDL_WAYLAND_INTERFACE(wl_region_interface)
SDL_WAYLAND_INTERFACE(wl_pointer_interface)
SDL_WAYLAND_INTERFACE(wl_keyboard_interface)
SDL_WAYLAND_INTERFACE(wl_compositor_interface)
SDL_WAYLAND_INTERFACE(wl_output_interface)
SDL_WAYLAND_INTERFACE(wl_shell_interface)
SDL_WAYLAND_INTERFACE(wl_shm_interface)
SDL_WAYLAND_MODULE(WAYLAND_EGL)
SDL_WAYLAND_SYM(struct wl_egl_window *, wl_egl_window_create, (struct wl_surface *, int, int))
SDL_WAYLAND_SYM(void, wl_egl_window_destroy, (struct wl_egl_window *))
SDL_WAYLAND_SYM(void, wl_egl_window_resize, (struct wl_egl_window *, int, int, int, int))
SDL_WAYLAND_SYM(void, wl_egl_window_get_attached_size, (struct wl_egl_window *, int *, int *))
SDL_WAYLAND_MODULE(WAYLAND_CURSOR)
SDL_WAYLAND_SYM(struct wl_cursor_theme *, wl_cursor_theme_load, (const char *, int , struct wl_shm *))
SDL_WAYLAND_SYM(void, wl_cursor_theme_destroy, (struct wl_cursor_theme *))
SDL_WAYLAND_SYM(struct wl_cursor *, wl_cursor_theme_get_cursor, (struct wl_cursor_theme *, const char *))
SDL_WAYLAND_SYM(struct wl_buffer *, wl_cursor_image_get_buffer, (struct wl_cursor_image *))
SDL_WAYLAND_SYM(int, wl_cursor_frame, (struct wl_cursor *, uint32_t))
SDL_WAYLAND_MODULE(WAYLAND_XKB)
SDL_WAYLAND_SYM(int, xkb_state_key_get_syms, (struct xkb_state *, xkb_keycode_t, const xkb_keysym_t **))
SDL_WAYLAND_SYM(int, xkb_keysym_to_utf8, (xkb_keysym_t, char *, size_t) )
SDL_WAYLAND_SYM(struct xkb_keymap *, xkb_keymap_new_from_string, (struct xkb_context *, const char *, enum xkb_keymap_format, enum xkb_keymap_compile_flags))
SDL_WAYLAND_SYM(struct xkb_state *, xkb_state_new, (struct xkb_keymap *) )
SDL_WAYLAND_SYM(void, xkb_keymap_unref, (struct xkb_keymap *) )
SDL_WAYLAND_SYM(void, xkb_state_unref, (struct xkb_state *) )
SDL_WAYLAND_SYM(void, xkb_context_unref, (struct xkb_context *) )
SDL_WAYLAND_SYM(struct xkb_context *, xkb_context_new, (enum xkb_context_flags flags) )
SDL_WAYLAND_SYM(enum xkb_state_component, xkb_state_update_mask, (struct xkb_state *state,\
xkb_mod_mask_t depressed_mods,\
xkb_mod_mask_t latched_mods,\
xkb_mod_mask_t locked_mods,\
xkb_layout_index_t depressed_layout,\
xkb_layout_index_t latched_layout,\
xkb_layout_index_t locked_layout) )
/* *INDENT-ON* */
/* vi: set ts=4 sw=4 expandtab: */
//SDL_WAYLAND_SYM(ret, fn, params)

View File

@@ -0,0 +1,265 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* Contributed by Thomas Perl <thomas.perl@jollamobile.com> */
#include "../../SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
#include "SDL_log.h"
#include "SDL_waylandtouch.h"
#include "../../events/SDL_touch_c.h"
struct SDL_WaylandTouch {
struct qt_touch_extension *touch_extension;
};
/**
* Qt TouchPointState
* adapted from qtbase/src/corelib/global/qnamespace.h
**/
enum QtWaylandTouchPointState {
QtWaylandTouchPointPressed = 0x01,
QtWaylandTouchPointMoved = 0x02,
/*
Never sent by the server:
QtWaylandTouchPointStationary = 0x04,
*/
QtWaylandTouchPointReleased = 0x08,
};
static void
touch_handle_touch(void *data,
struct qt_touch_extension *qt_touch_extension,
uint32_t time,
uint32_t id,
uint32_t state,
int32_t x,
int32_t y,
int32_t normalized_x,
int32_t normalized_y,
int32_t width,
int32_t height,
uint32_t pressure,
int32_t velocity_x,
int32_t velocity_y,
uint32_t flags,
struct wl_array *rawdata)
{
/**
* Event is assembled in QtWayland in TouchExtensionGlobal::postTouchEvent
* (src/compositor/wayland_wrapper/qwltouch.cpp)
**/
float FIXED_TO_FLOAT = 1. / 10000.;
float xf = FIXED_TO_FLOAT * x;
float yf = FIXED_TO_FLOAT * y;
float PRESSURE_TO_FLOAT = 1. / 255.;
float pressuref = PRESSURE_TO_FLOAT * pressure;
uint32_t touchState = state & 0xFFFF;
/*
Other fields that are sent by the server (qwltouch.cpp),
but not used at the moment can be decoded in this way:
uint32_t sentPointCount = state >> 16;
uint32_t touchFlags = flags & 0xFFFF;
uint32_t capabilities = flags >> 16;
*/
SDL_TouchID deviceId = 1;
if (SDL_AddTouch(deviceId, "qt_touch_extension") < 0) {
SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
}
switch (touchState) {
case QtWaylandTouchPointPressed:
case QtWaylandTouchPointReleased:
SDL_SendTouch(deviceId, (SDL_FingerID)id,
(touchState == QtWaylandTouchPointPressed) ? SDL_TRUE : SDL_FALSE,
xf, yf, pressuref);
break;
case QtWaylandTouchPointMoved:
SDL_SendTouchMotion(deviceId, (SDL_FingerID)id, xf, yf, pressuref);
break;
default:
/* Should not happen */
break;
}
}
static void
touch_handle_configure(void *data,
struct qt_touch_extension *qt_touch_extension,
uint32_t flags)
{
}
/* wayland-qt-touch-extension.c BEGINS */
static const struct qt_touch_extension_listener touch_listener = {
touch_handle_touch,
touch_handle_configure,
};
static const struct wl_interface *qt_touch_extension_types[] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
static const struct wl_message qt_touch_extension_requests[] = {
{ "dummy", "", qt_touch_extension_types + 0 },
};
static const struct wl_message qt_touch_extension_events[] = {
{ "touch", "uuuiiiiiiuiiua", qt_touch_extension_types + 0 },
{ "configure", "u", qt_touch_extension_types + 0 },
};
WL_EXPORT const struct wl_interface qt_touch_extension_interface = {
"qt_touch_extension", 1,
1, qt_touch_extension_requests,
2, qt_touch_extension_events,
};
/* wayland-qt-touch-extension.c ENDS */
/* wayland-qt-windowmanager.c BEGINS */
static const struct wl_interface *qt_windowmanager_types[] = {
NULL,
NULL,
};
static const struct wl_message qt_windowmanager_requests[] = {
{ "open_url", "us", qt_windowmanager_types + 0 },
};
static const struct wl_message qt_windowmanager_events[] = {
{ "hints", "i", qt_windowmanager_types + 0 },
{ "quit", "", qt_windowmanager_types + 0 },
};
WL_EXPORT const struct wl_interface qt_windowmanager_interface = {
"qt_windowmanager", 1,
1, qt_windowmanager_requests,
2, qt_windowmanager_events,
};
/* wayland-qt-windowmanager.c ENDS */
/* wayland-qt-surface-extension.c BEGINS */
extern const struct wl_interface qt_extended_surface_interface;
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
extern const struct wl_interface wl_surface_interface;
#endif
static const struct wl_interface *qt_surface_extension_types[] = {
NULL,
NULL,
&qt_extended_surface_interface,
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
/* FIXME: Set this dynamically to (*WAYLAND_wl_surface_interface) ?
* The value comes from auto generated code and does
* not appear to actually be used anywhere
*/
NULL,
#else
&wl_surface_interface,
#endif
};
static const struct wl_message qt_surface_extension_requests[] = {
{ "get_extended_surface", "no", qt_surface_extension_types + 2 },
};
WL_EXPORT const struct wl_interface qt_surface_extension_interface = {
"qt_surface_extension", 1,
1, qt_surface_extension_requests,
0, NULL,
};
static const struct wl_message qt_extended_surface_requests[] = {
{ "update_generic_property", "sa", qt_surface_extension_types + 0 },
{ "set_content_orientation", "i", qt_surface_extension_types + 0 },
{ "set_window_flags", "i", qt_surface_extension_types + 0 },
};
static const struct wl_message qt_extended_surface_events[] = {
{ "onscreen_visibility", "i", qt_surface_extension_types + 0 },
{ "set_generic_property", "sa", qt_surface_extension_types + 0 },
{ "close", "", qt_surface_extension_types + 0 },
};
WL_EXPORT const struct wl_interface qt_extended_surface_interface = {
"qt_extended_surface", 1,
3, qt_extended_surface_requests,
3, qt_extended_surface_events,
};
/* wayland-qt-surface-extension.c ENDS */
void
Wayland_touch_create(SDL_VideoData *data, uint32_t id)
{
struct SDL_WaylandTouch *touch;
if (data->touch) {
Wayland_touch_destroy(data);
}
/* !!! FIXME: check for failure, call SDL_OutOfMemory() */
data->touch = SDL_malloc(sizeof(struct SDL_WaylandTouch));
touch = data->touch;
touch->touch_extension = wl_registry_bind(data->registry, id, &qt_touch_extension_interface, 1);
qt_touch_extension_add_listener(touch->touch_extension, &touch_listener, data);
}
void
Wayland_touch_destroy(SDL_VideoData *data)
{
if (data->touch) {
struct SDL_WaylandTouch *touch = data->touch;
if (touch->touch_extension) {
qt_touch_extension_destroy(touch->touch_extension);
}
SDL_free(data->touch);
data->touch = NULL;
}
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */

View File

@@ -0,0 +1,352 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
#ifndef _SDL_waylandtouch_h
#define _SDL_waylandtouch_h
#include "SDL_waylandvideo.h"
#include <stdint.h>
#include <stddef.h>
#include "wayland-util.h"
#include "SDL_waylanddyn.h"
void Wayland_touch_create(SDL_VideoData *data, uint32_t id);
void Wayland_touch_destroy(SDL_VideoData *data);
struct qt_touch_extension;
/* Autogenerated QT headers */
/*
Support for Wayland with QmlCompositor as Server
================================================
The Wayland video driver has support for some additional features when
using QtWayland's "qmlcompositor" as Wayland server. This is needed for touch
input when running SDL applications under a qmlcompositor Wayland server.
The files following headers have been
generated from the Wayland XML Protocol Definition in QtWayland as follows:
Clone QtWayland from Git:
http://qt.gitorious.org/qt/qtwayland/
Generate headers and glue code:
for extension in touch-extension surface-extension windowmanager; do
wayland-scanner client-header < src/extensions/$extension.xml > wayland-qt-$extension.h
wayland-scanner code < src/extensions/$extension.xml > wayland-qt-$extension.c
done
*/
/* wayland-qt-surface-extension.h */
struct wl_client;
struct wl_resource;
struct qt_surface_extension;
struct qt_extended_surface;
extern const struct wl_interface qt_surface_extension_interface;
extern const struct wl_interface qt_extended_surface_interface;
#define QT_SURFACE_EXTENSION_GET_EXTENDED_SURFACE 0
static inline void
qt_surface_extension_set_user_data(struct qt_surface_extension *qt_surface_extension, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) qt_surface_extension, user_data);
}
static inline void *
qt_surface_extension_get_user_data(struct qt_surface_extension *qt_surface_extension)
{
return wl_proxy_get_user_data((struct wl_proxy *) qt_surface_extension);
}
static inline void
qt_surface_extension_destroy(struct qt_surface_extension *qt_surface_extension)
{
WAYLAND_wl_proxy_destroy((struct wl_proxy *) qt_surface_extension);
}
static inline struct qt_extended_surface *
qt_surface_extension_get_extended_surface(struct qt_surface_extension *qt_surface_extension, struct wl_surface *surface)
{
struct wl_proxy *id;
id = wl_proxy_create((struct wl_proxy *) qt_surface_extension,
&qt_extended_surface_interface);
if (!id)
return NULL;
WAYLAND_wl_proxy_marshal((struct wl_proxy *) qt_surface_extension,
QT_SURFACE_EXTENSION_GET_EXTENDED_SURFACE, id, surface);
return (struct qt_extended_surface *) id;
}
#ifndef QT_EXTENDED_SURFACE_ORIENTATION_ENUM
#define QT_EXTENDED_SURFACE_ORIENTATION_ENUM
enum qt_extended_surface_orientation {
QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION = 0,
QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION = 1,
QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION = 2,
QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION = 4,
QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION = 8,
};
#endif /* QT_EXTENDED_SURFACE_ORIENTATION_ENUM */
#ifndef QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM
#define QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM
enum qt_extended_surface_windowflag {
QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES = 1,
QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP = 2,
};
#endif /* QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM */
struct qt_extended_surface_listener {
/**
* onscreen_visibility - (none)
* @visible: (none)
*/
void (*onscreen_visibility)(void *data,
struct qt_extended_surface *qt_extended_surface,
int32_t visible);
/**
* set_generic_property - (none)
* @name: (none)
* @value: (none)
*/
void (*set_generic_property)(void *data,
struct qt_extended_surface *qt_extended_surface,
const char *name,
struct wl_array *value);
/**
* close - (none)
*/
void (*close)(void *data,
struct qt_extended_surface *qt_extended_surface);
};
static inline int
qt_extended_surface_add_listener(struct qt_extended_surface *qt_extended_surface,
const struct qt_extended_surface_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) qt_extended_surface,
(void (**)(void)) listener, data);
}
#define QT_EXTENDED_SURFACE_UPDATE_GENERIC_PROPERTY 0
#define QT_EXTENDED_SURFACE_SET_CONTENT_ORIENTATION 1
#define QT_EXTENDED_SURFACE_SET_WINDOW_FLAGS 2
static inline void
qt_extended_surface_set_user_data(struct qt_extended_surface *qt_extended_surface, void *user_data)
{
WAYLAND_wl_proxy_set_user_data((struct wl_proxy *) qt_extended_surface, user_data);
}
static inline void *
qt_extended_surface_get_user_data(struct qt_extended_surface *qt_extended_surface)
{
return WAYLAND_wl_proxy_get_user_data((struct wl_proxy *) qt_extended_surface);
}
static inline void
qt_extended_surface_destroy(struct qt_extended_surface *qt_extended_surface)
{
WAYLAND_wl_proxy_destroy((struct wl_proxy *) qt_extended_surface);
}
static inline void
qt_extended_surface_update_generic_property(struct qt_extended_surface *qt_extended_surface, const char *name, struct wl_array *value)
{
WAYLAND_wl_proxy_marshal((struct wl_proxy *) qt_extended_surface,
QT_EXTENDED_SURFACE_UPDATE_GENERIC_PROPERTY, name, value);
}
static inline void
qt_extended_surface_set_content_orientation(struct qt_extended_surface *qt_extended_surface, int32_t orientation)
{
WAYLAND_wl_proxy_marshal((struct wl_proxy *) qt_extended_surface,
QT_EXTENDED_SURFACE_SET_CONTENT_ORIENTATION, orientation);
}
static inline void
qt_extended_surface_set_window_flags(struct qt_extended_surface *qt_extended_surface, int32_t flags)
{
WAYLAND_wl_proxy_marshal((struct wl_proxy *) qt_extended_surface,
QT_EXTENDED_SURFACE_SET_WINDOW_FLAGS, flags);
}
/* wayland-qt-touch-extension.h */
extern const struct wl_interface qt_touch_extension_interface;
#ifndef QT_TOUCH_EXTENSION_FLAGS_ENUM
#define QT_TOUCH_EXTENSION_FLAGS_ENUM
enum qt_touch_extension_flags {
QT_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH = 0x1,
};
#endif /* QT_TOUCH_EXTENSION_FLAGS_ENUM */
struct qt_touch_extension_listener {
/**
* touch - (none)
* @time: (none)
* @id: (none)
* @state: (none)
* @x: (none)
* @y: (none)
* @normalized_x: (none)
* @normalized_y: (none)
* @width: (none)
* @height: (none)
* @pressure: (none)
* @velocity_x: (none)
* @velocity_y: (none)
* @flags: (none)
* @rawdata: (none)
*/
void (*touch)(void *data,
struct qt_touch_extension *qt_touch_extension,
uint32_t time,
uint32_t id,
uint32_t state,
int32_t x,
int32_t y,
int32_t normalized_x,
int32_t normalized_y,
int32_t width,
int32_t height,
uint32_t pressure,
int32_t velocity_x,
int32_t velocity_y,
uint32_t flags,
struct wl_array *rawdata);
/**
* configure - (none)
* @flags: (none)
*/
void (*configure)(void *data,
struct qt_touch_extension *qt_touch_extension,
uint32_t flags);
};
static inline int
qt_touch_extension_add_listener(struct qt_touch_extension *qt_touch_extension,
const struct qt_touch_extension_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) qt_touch_extension,
(void (**)(void)) listener, data);
}
#define QT_TOUCH_EXTENSION_DUMMY 0
static inline void
qt_touch_extension_set_user_data(struct qt_touch_extension *qt_touch_extension, void *user_data)
{
WAYLAND_wl_proxy_set_user_data((struct wl_proxy *) qt_touch_extension, user_data);
}
static inline void *
qt_touch_extension_get_user_data(struct qt_touch_extension *qt_touch_extension)
{
return WAYLAND_wl_proxy_get_user_data((struct wl_proxy *) qt_touch_extension);
}
static inline void
qt_touch_extension_destroy(struct qt_touch_extension *qt_touch_extension)
{
WAYLAND_wl_proxy_destroy((struct wl_proxy *) qt_touch_extension);
}
static inline void
qt_touch_extension_dummy(struct qt_touch_extension *qt_touch_extension)
{
WAYLAND_wl_proxy_marshal((struct wl_proxy *) qt_touch_extension,
QT_TOUCH_EXTENSION_DUMMY);
}
/* wayland-qt-windowmanager.h */
extern const struct wl_interface qt_windowmanager_interface;
struct qt_windowmanager_listener {
/**
* hints - (none)
* @show_is_fullscreen: (none)
*/
void (*hints)(void *data,
struct qt_windowmanager *qt_windowmanager,
int32_t show_is_fullscreen);
/**
* quit - (none)
*/
void (*quit)(void *data,
struct qt_windowmanager *qt_windowmanager);
};
static inline int
qt_windowmanager_add_listener(struct qt_windowmanager *qt_windowmanager,
const struct qt_windowmanager_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) qt_windowmanager,
(void (**)(void)) listener, data);
}
#define QT_WINDOWMANAGER_OPEN_URL 0
static inline void
qt_windowmanager_set_user_data(struct qt_windowmanager *qt_windowmanager, void *user_data)
{
WAYLAND_wl_proxy_set_user_data((struct wl_proxy *) qt_windowmanager, user_data);
}
static inline void *
qt_windowmanager_get_user_data(struct qt_windowmanager *qt_windowmanager)
{
return WAYLAND_wl_proxy_get_user_data((struct wl_proxy *) qt_windowmanager);
}
static inline void
qt_windowmanager_destroy(struct qt_windowmanager *qt_windowmanager)
{
WAYLAND_wl_proxy_destroy((struct wl_proxy *) qt_windowmanager);
}
static inline void
qt_windowmanager_open_url(struct qt_windowmanager *qt_windowmanager, uint32_t remaining, const char *url)
{
WAYLAND_wl_proxy_marshal((struct wl_proxy *) qt_windowmanager,
QT_WINDOWMANAGER_OPEN_URL, remaining, url);
}
#endif /* _SDL_waylandtouch_h */
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */

View File

@@ -0,0 +1,385 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "SDL_stdinc.h"
#include "../../events/SDL_events_c.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandopengles.h"
#include "SDL_waylandmouse.h"
#include "SDL_waylandtouch.h"
#include <fcntl.h>
#include <xkbcommon/xkbcommon.h>
#include "SDL_waylanddyn.h"
#include <wayland-util.h>
#define WAYLANDVID_DRIVER_NAME "wayland"
/* Initialization/Query functions */
static int
Wayland_VideoInit(_THIS);
static void
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display);
static int
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
static void
Wayland_VideoQuit(_THIS);
/* Wayland driver bootstrap functions */
static int
Wayland_Available(void)
{
struct wl_display *display = NULL;
if (SDL_WAYLAND_LoadSymbols()) {
display = WAYLAND_wl_display_connect(NULL);
if (display != NULL) {
WAYLAND_wl_display_disconnect(display);
}
SDL_WAYLAND_UnloadSymbols();
}
return (display != NULL);
}
static void
Wayland_DeleteDevice(SDL_VideoDevice *device)
{
SDL_free(device);
SDL_WAYLAND_UnloadSymbols();
}
static SDL_VideoDevice *
Wayland_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
if (!SDL_WAYLAND_LoadSymbols()) {
return NULL;
}
/* Initialize all variables that we clean on shutdown */
device = SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
SDL_WAYLAND_UnloadSymbols();
SDL_OutOfMemory();
return NULL;
}
/* Set the function pointers */
device->VideoInit = Wayland_VideoInit;
device->VideoQuit = Wayland_VideoQuit;
device->SetDisplayMode = Wayland_SetDisplayMode;
device->GetDisplayModes = Wayland_GetDisplayModes;
device->GetWindowWMInfo = Wayland_GetWindowWMInfo;
device->PumpEvents = Wayland_PumpEvents;
device->GL_SwapWindow = Wayland_GLES_SwapWindow;
device->GL_GetSwapInterval = Wayland_GLES_GetSwapInterval;
device->GL_SetSwapInterval = Wayland_GLES_SetSwapInterval;
device->GL_MakeCurrent = Wayland_GLES_MakeCurrent;
device->GL_CreateContext = Wayland_GLES_CreateContext;
device->GL_LoadLibrary = Wayland_GLES_LoadLibrary;
device->GL_UnloadLibrary = Wayland_GLES_UnloadLibrary;
device->GL_GetProcAddress = Wayland_GLES_GetProcAddress;
device->GL_DeleteContext = Wayland_GLES_DeleteContext;
device->CreateWindow = Wayland_CreateWindow;
device->ShowWindow = Wayland_ShowWindow;
device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
device->SetWindowSize = Wayland_SetWindowSize;
device->DestroyWindow = Wayland_DestroyWindow;
device->SetWindowHitTest = Wayland_SetWindowHitTest;
device->free = Wayland_DeleteDevice;
return device;
}
VideoBootStrap Wayland_bootstrap = {
WAYLANDVID_DRIVER_NAME, "SDL Wayland video driver",
Wayland_Available, Wayland_CreateDevice
};
static void
display_handle_geometry(void *data,
struct wl_output *output,
int x, int y,
int physical_width,
int physical_height,
int subpixel,
const char *make,
const char *model,
int transform)
{
SDL_VideoDisplay *display = data;
display->name = strdup(model);
display->driverdata = output;
}
static void
display_handle_mode(void *data,
struct wl_output *output,
uint32_t flags,
int width,
int height,
int refresh)
{
SDL_VideoDisplay *display = data;
SDL_DisplayMode mode;
SDL_zero(mode);
mode.w = width;
mode.h = height;
mode.refresh_rate = refresh / 1000; // mHz to Hz
SDL_AddDisplayMode(display, &mode);
if (flags & WL_OUTPUT_MODE_CURRENT) {
display->current_mode = mode;
display->desktop_mode = mode;
}
}
static void
display_handle_done(void *data,
struct wl_output *output)
{
SDL_VideoDisplay *display = data;
SDL_AddVideoDisplay(display);
SDL_free(display->name);
SDL_free(display);
}
static void
display_handle_scale(void *data,
struct wl_output *output,
int32_t factor)
{
// TODO: do HiDPI stuff.
}
static const struct wl_output_listener output_listener = {
display_handle_geometry,
display_handle_mode,
display_handle_done,
display_handle_scale
};
static void
Wayland_add_display(SDL_VideoData *d, uint32_t id)
{
struct wl_output *output;
SDL_VideoDisplay *display = SDL_malloc(sizeof *display);
if (!display) {
SDL_OutOfMemory();
return;
}
SDL_zero(*display);
output = wl_registry_bind(d->registry, id, &wl_output_interface, 2);
if (!output) {
SDL_SetError("Failed to retrieve output.");
return;
}
wl_output_add_listener(output, &output_listener, display);
}
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
static void
windowmanager_hints(void *data, struct qt_windowmanager *qt_windowmanager,
int32_t show_is_fullscreen)
{
}
static void
windowmanager_quit(void *data, struct qt_windowmanager *qt_windowmanager)
{
SDL_SendQuit();
}
static const struct qt_windowmanager_listener windowmanager_listener = {
windowmanager_hints,
windowmanager_quit,
};
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
static void
display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
{
SDL_VideoData *d = data;
if (strcmp(interface, "wl_compositor") == 0) {
d->compositor = wl_registry_bind(d->registry, id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "wl_output") == 0) {
Wayland_add_display(d, id);
} else if (strcmp(interface, "wl_seat") == 0) {
Wayland_display_add_input(d, id);
} else if (strcmp(interface, "wl_shell") == 0) {
d->shell = wl_registry_bind(d->registry, id, &wl_shell_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm);
d->default_cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (strcmp(interface, "qt_touch_extension") == 0) {
Wayland_touch_create(d, id);
} else if (strcmp(interface, "qt_surface_extension") == 0) {
d->surface_extension = wl_registry_bind(registry, id,
&qt_surface_extension_interface, 1);
} else if (strcmp(interface, "qt_windowmanager") == 0) {
d->windowmanager = wl_registry_bind(registry, id,
&qt_windowmanager_interface, 1);
qt_windowmanager_add_listener(d->windowmanager, &windowmanager_listener, d);
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
}
}
static const struct wl_registry_listener registry_listener = {
display_handle_global
};
int
Wayland_VideoInit(_THIS)
{
SDL_VideoData *data = SDL_malloc(sizeof *data);
if (data == NULL)
return SDL_OutOfMemory();
memset(data, 0, sizeof *data);
_this->driverdata = data;
data->display = WAYLAND_wl_display_connect(NULL);
if (data->display == NULL) {
return SDL_SetError("Failed to connect to a Wayland display");
}
data->registry = wl_display_get_registry(data->display);
if (data->registry == NULL) {
return SDL_SetError("Failed to get the Wayland registry");
}
wl_registry_add_listener(data->registry, &registry_listener, data);
// First roundtrip to receive all registry objects.
WAYLAND_wl_display_roundtrip(data->display);
// Second roundtrip to receive all output events.
WAYLAND_wl_display_roundtrip(data->display);
data->xkb_context = WAYLAND_xkb_context_new(0);
if (!data->xkb_context) {
return SDL_SetError("Failed to create XKB context");
}
Wayland_InitMouse();
WAYLAND_wl_display_flush(data->display);
return 0;
}
static void
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display)
{
// Nothing to do here, everything was already done in the wl_output
// callbacks.
}
static int
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
{
return SDL_Unsupported();
}
void
Wayland_VideoQuit(_THIS)
{
SDL_VideoData *data = _this->driverdata;
int i;
Wayland_FiniMouse ();
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *display = &_this->displays[i];
wl_output_destroy(display->driverdata);
display->driverdata = NULL;
}
Wayland_display_destroy_input(data);
if (data->xkb_context) {
WAYLAND_xkb_context_unref(data->xkb_context);
data->xkb_context = NULL;
}
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
if (data->windowmanager)
qt_windowmanager_destroy(data->windowmanager);
if (data->surface_extension)
qt_surface_extension_destroy(data->surface_extension);
Wayland_touch_destroy(data);
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
if (data->shm)
wl_shm_destroy(data->shm);
if (data->cursor_theme)
WAYLAND_wl_cursor_theme_destroy(data->cursor_theme);
if (data->shell)
wl_shell_destroy(data->shell);
if (data->compositor)
wl_compositor_destroy(data->compositor);
if (data->registry)
wl_registry_destroy(data->registry);
if (data->display) {
WAYLAND_wl_display_flush(data->display);
WAYLAND_wl_display_disconnect(data->display);
}
free(data);
_this->driverdata = NULL;
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,65 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifndef _SDL_waylandvideo_h
#define _SDL_waylandvideo_h
#include <EGL/egl.h>
#include "wayland-util.h"
struct xkb_context;
struct SDL_WaylandInput;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct SDL_WaylandTouch;
struct qt_surface_extension;
struct qt_windowmanager;
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
typedef struct {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_shm *shm;
struct wl_cursor_theme *cursor_theme;
struct wl_cursor *default_cursor;
struct wl_pointer *pointer;
struct wl_shell *shell;
EGLDisplay edpy;
EGLContext context;
EGLConfig econf;
struct xkb_context *xkb_context;
struct SDL_WaylandInput *input;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct SDL_WaylandTouch *touch;
struct qt_surface_extension *surface_extension;
struct qt_windowmanager *windowmanager;
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
} SDL_VideoData;
#endif /* _SDL_waylandvideo_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,262 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL
#include "../SDL_sysvideo.h"
#include "../../events/SDL_windowevents_c.h"
#include "../SDL_egl_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandtouch.h"
#include "SDL_waylanddyn.h"
static void
handle_ping(void *data, struct wl_shell_surface *shell_surface,
uint32_t serial)
{
wl_shell_surface_pong(shell_surface, serial);
}
static void
handle_configure(void *data, struct wl_shell_surface *shell_surface,
uint32_t edges, int32_t width, int32_t height)
{
SDL_WindowData *wind = (SDL_WindowData *)data;
SDL_Window *window = wind->sdlwindow;
struct wl_region *region;
window->w = width;
window->h = height;
WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
region = wl_compositor_create_region(wind->waylandData->compositor);
wl_region_add(region, 0, 0, window->w, window->h);
wl_surface_set_opaque_region(wind->surface, region);
wl_region_destroy(region);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
}
static void
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
{
}
static const struct wl_shell_surface_listener shell_surface_listener = {
handle_ping,
handle_configure,
handle_popup_done
};
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
static void
handle_onscreen_visibility(void *data,
struct qt_extended_surface *qt_extended_surface, int32_t visible)
{
}
static void
handle_set_generic_property(void *data,
struct qt_extended_surface *qt_extended_surface, const char *name,
struct wl_array *value)
{
}
static void
handle_close(void *data, struct qt_extended_surface *qt_extended_surface)
{
SDL_WindowData *window = (SDL_WindowData *)data;
SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
}
static const struct qt_extended_surface_listener extended_surface_listener = {
handle_onscreen_visibility,
handle_set_generic_property,
handle_close,
};
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
info->info.wl.display = data->waylandData->display;
info->info.wl.surface = data->surface;
info->info.wl.shell_surface = data->shell_surface;
info->subsystem = SDL_SYSWM_WAYLAND;
return SDL_TRUE;
}
int
Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
{
return 0; /* just succeed, the real work is done elsewhere. */
}
void Wayland_ShowWindow(_THIS, SDL_Window *window)
{
SDL_WindowData *wind = window->driverdata;
if (window->flags & SDL_WINDOW_FULLSCREEN)
wl_shell_surface_set_fullscreen(wind->shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0, (struct wl_output *)window->fullscreen_mode.driverdata);
else
wl_shell_surface_set_toplevel(wind->shell_surface);
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
}
void
Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_VideoDisplay * _display, SDL_bool fullscreen)
{
SDL_WindowData *wind = window->driverdata;
if (fullscreen)
wl_shell_surface_set_fullscreen(wind->shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE,
0, (struct wl_output *)_display->driverdata);
else
wl_shell_surface_set_toplevel(wind->shell_surface);
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
}
int Wayland_CreateWindow(_THIS, SDL_Window *window)
{
SDL_WindowData *data;
SDL_VideoData *c;
struct wl_region *region;
data = calloc(1, sizeof *data);
if (data == NULL)
return SDL_OutOfMemory();
c = _this->driverdata;
window->driverdata = data;
if (!(window->flags & SDL_WINDOW_OPENGL)) {
SDL_GL_LoadLibrary(NULL);
window->flags |= SDL_WINDOW_OPENGL;
}
if (window->x == SDL_WINDOWPOS_UNDEFINED) {
window->x = 0;
}
if (window->y == SDL_WINDOWPOS_UNDEFINED) {
window->y = 0;
}
data->waylandData = c;
data->sdlwindow = window;
data->surface =
wl_compositor_create_surface(c->compositor);
wl_surface_set_user_data(data->surface, data);
data->shell_surface = wl_shell_get_shell_surface(c->shell,
data->surface);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
if (c->surface_extension) {
data->extended_surface = qt_surface_extension_get_extended_surface(
c->surface_extension, data->surface);
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
window->w, window->h);
/* Create the GLES window surface */
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
if (data->egl_surface == EGL_NO_SURFACE) {
return SDL_SetError("failed to create a window surface");
}
if (data->shell_surface) {
wl_shell_surface_set_user_data(data->shell_surface, data);
wl_shell_surface_add_listener(data->shell_surface,
&shell_surface_listener, data);
}
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
if (data->extended_surface) {
qt_extended_surface_set_user_data(data->extended_surface, data);
qt_extended_surface_add_listener(data->extended_surface,
&extended_surface_listener, data);
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
region = wl_compositor_create_region(c->compositor);
wl_region_add(region, 0, 0, window->w, window->h);
wl_surface_set_opaque_region(data->surface, region);
wl_region_destroy(region);
WAYLAND_wl_display_flush(c->display);
return 0;
}
void Wayland_SetWindowSize(_THIS, SDL_Window * window)
{
SDL_VideoData *data = _this->driverdata;
SDL_WindowData *wind = window->driverdata;
struct wl_region *region;
WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
region =wl_compositor_create_region(data->compositor);
wl_region_add(region, 0, 0, window->w, window->h);
wl_surface_set_opaque_region(wind->surface, region);
wl_region_destroy(region);
}
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
{
SDL_VideoData *data = _this->driverdata;
SDL_WindowData *wind = window->driverdata;
if (data) {
SDL_EGL_DestroySurface(_this, wind->egl_surface);
WAYLAND_wl_egl_window_destroy(wind->egl_window);
if (wind->shell_surface)
wl_shell_surface_destroy(wind->shell_surface);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
if (wind->extended_surface)
qt_extended_surface_destroy(wind->extended_surface);
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
wl_surface_destroy(wind->surface);
SDL_free(wind);
WAYLAND_wl_display_flush(data->display);
}
window->driverdata = NULL;
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,62 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifndef _SDL_waylandwindow_h
#define _SDL_waylandwindow_h
#include "../SDL_sysvideo.h"
#include "SDL_syswm.h"
#include "SDL_waylandvideo.h"
struct SDL_WaylandInput;
typedef struct {
SDL_Window *sdlwindow;
SDL_VideoData *waylandData;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
struct wl_egl_window *egl_window;
struct SDL_WaylandInput *keyboard_device;
EGLSurface egl_surface;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct qt_extended_surface *extended_surface;
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
} SDL_WindowData;
extern void Wayland_ShowWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_VideoDisplay * _display,
SDL_bool fullscreen);
extern int Wayland_CreateWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowSize(_THIS, SDL_Window * window);
extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
extern SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
#endif /* _SDL_waylandwindow_h */
/* vi: set ts=4 sw=4 expandtab: */