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
This commit is contained in:
parent
b71add8edb
commit
3308d271b5
25 changed files with 2035 additions and 129 deletions
|
@ -30,7 +30,7 @@ SDL_PROC_UNUSED(void, glColor3bv, (const GLbyte *))
|
|||
SDL_PROC_UNUSED(void, glColor3d, (GLdouble, GLdouble, GLdouble))
|
||||
SDL_PROC_UNUSED(void, glColor3dv, (const GLdouble *))
|
||||
SDL_PROC_UNUSED(void, glColor3f, (GLfloat, GLfloat, GLfloat))
|
||||
SDL_PROC_UNUSED(void, glColor3fv, (const GLfloat *))
|
||||
SDL_PROC(void, glColor3fv, (const GLfloat *))
|
||||
SDL_PROC_UNUSED(void, glColor3i, (GLint, GLint, GLint))
|
||||
SDL_PROC_UNUSED(void, glColor3iv, (const GLint *))
|
||||
SDL_PROC_UNUSED(void, glColor3s, (GLshort, GLshort, GLshort))
|
||||
|
@ -85,7 +85,7 @@ SDL_PROC_UNUSED(void, glCopyTexSubImage2D,
|
|||
SDL_PROC_UNUSED(void, glCullFace, (GLenum mode))
|
||||
SDL_PROC_UNUSED(void, glDeleteLists, (GLuint list, GLsizei range))
|
||||
SDL_PROC(void, glDeleteTextures, (GLsizei n, const GLuint * textures))
|
||||
SDL_PROC_UNUSED(void, glDepthFunc, (GLenum func))
|
||||
SDL_PROC(void, glDepthFunc, (GLenum func))
|
||||
SDL_PROC_UNUSED(void, glDepthMask, (GLboolean flag))
|
||||
SDL_PROC_UNUSED(void, glDepthRange, (GLclampd zNear, GLclampd zFar))
|
||||
SDL_PROC(void, glDisable, (GLenum cap))
|
||||
|
@ -334,13 +334,13 @@ SDL_PROC_UNUSED(void, glRectsv, (const GLshort * v1, const GLshort * v2))
|
|||
SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode))
|
||||
SDL_PROC(void, glRotated,
|
||||
(GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
|
||||
SDL_PROC_UNUSED(void, glRotatef,
|
||||
SDL_PROC(void, glRotatef,
|
||||
(GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
|
||||
SDL_PROC_UNUSED(void, glScaled, (GLdouble x, GLdouble y, GLdouble z))
|
||||
SDL_PROC_UNUSED(void, glScalef, (GLfloat x, GLfloat y, GLfloat z))
|
||||
SDL_PROC(void, glScissor, (GLint x, GLint y, GLsizei width, GLsizei height))
|
||||
SDL_PROC_UNUSED(void, glSelectBuffer, (GLsizei size, GLuint * buffer))
|
||||
SDL_PROC_UNUSED(void, glShadeModel, (GLenum mode))
|
||||
SDL_PROC(void, glShadeModel, (GLenum mode))
|
||||
SDL_PROC_UNUSED(void, glStencilFunc, (GLenum func, GLint ref, GLuint mask))
|
||||
SDL_PROC_UNUSED(void, glStencilMask, (GLuint mask))
|
||||
SDL_PROC_UNUSED(void, glStencilOp, (GLenum fail, GLenum zfail, GLenum zpass))
|
||||
|
@ -432,7 +432,7 @@ SDL_PROC_UNUSED(void, glVertex2sv, (const GLshort * v))
|
|||
SDL_PROC_UNUSED(void, glVertex3d, (GLdouble x, GLdouble y, GLdouble z))
|
||||
SDL_PROC_UNUSED(void, glVertex3dv, (const GLdouble * v))
|
||||
SDL_PROC_UNUSED(void, glVertex3f, (GLfloat x, GLfloat y, GLfloat z))
|
||||
SDL_PROC_UNUSED(void, glVertex3fv, (const GLfloat * v))
|
||||
SDL_PROC(void, glVertex3fv, (const GLfloat * v))
|
||||
SDL_PROC_UNUSED(void, glVertex3i, (GLint x, GLint y, GLint z))
|
||||
SDL_PROC_UNUSED(void, glVertex3iv, (const GLint * v))
|
||||
SDL_PROC_UNUSED(void, glVertex3s, (GLshort x, GLshort y, GLshort z))
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
#else
|
||||
/* Desktop Linux */
|
||||
#define DEFAULT_OGL "libGL.so.1"
|
||||
#define DEFAULT_EGL "libEGL.so.1"
|
||||
#define DEFAULT_OGL_ES2 "libGLESv2.so.2"
|
||||
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
|
||||
|
@ -149,23 +150,31 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
|
|||
}
|
||||
|
||||
if (egl_dll_handle == NULL) {
|
||||
if (_this->gl_config.major_version > 1) {
|
||||
path = DEFAULT_OGL_ES2;
|
||||
egl_dll_handle = SDL_LoadObject(path);
|
||||
}
|
||||
else {
|
||||
path = DEFAULT_OGL_ES;
|
||||
egl_dll_handle = SDL_LoadObject(path);
|
||||
if (egl_dll_handle == NULL) {
|
||||
path = DEFAULT_OGL_ES_PVR;
|
||||
if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
if (_this->gl_config.major_version > 1) {
|
||||
path = DEFAULT_OGL_ES2;
|
||||
egl_dll_handle = SDL_LoadObject(path);
|
||||
}
|
||||
else {
|
||||
path = DEFAULT_OGL_ES;
|
||||
egl_dll_handle = SDL_LoadObject(path);
|
||||
if (egl_dll_handle == NULL) {
|
||||
path = DEFAULT_OGL_ES_PVR;
|
||||
egl_dll_handle = SDL_LoadObject(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEFAULT_OGL
|
||||
else {
|
||||
path = DEFAULT_OGL;
|
||||
egl_dll_handle = SDL_LoadObject(path);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
_this->egl_data->egl_dll_handle = egl_dll_handle;
|
||||
|
||||
if (egl_dll_handle == NULL) {
|
||||
return SDL_SetError("Could not initialize OpenGL ES library");
|
||||
return SDL_SetError("Could not initialize OpenGL / GLES library");
|
||||
}
|
||||
|
||||
/* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
|
||||
|
@ -205,6 +214,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
|
|||
LOAD_FUNC(eglSwapInterval);
|
||||
LOAD_FUNC(eglWaitNative);
|
||||
LOAD_FUNC(eglWaitGL);
|
||||
LOAD_FUNC(eglBindAPI);
|
||||
|
||||
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
|
||||
if (!_this->egl_data->egl_display) {
|
||||
|
@ -281,14 +291,21 @@ SDL_EGL_ChooseConfig(_THIS)
|
|||
}
|
||||
|
||||
attribs[i++] = EGL_RENDERABLE_TYPE;
|
||||
if (_this->gl_config.major_version == 2) {
|
||||
attribs[i++] = EGL_OPENGL_ES2_BIT;
|
||||
} else {
|
||||
attribs[i++] = EGL_OPENGL_ES_BIT;
|
||||
if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
if (_this->gl_config.major_version == 2) {
|
||||
attribs[i++] = EGL_OPENGL_ES2_BIT;
|
||||
} else {
|
||||
attribs[i++] = EGL_OPENGL_ES_BIT;
|
||||
}
|
||||
_this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
|
||||
}
|
||||
else {
|
||||
attribs[i++] = EGL_OPENGL_BIT;
|
||||
_this->egl_data->eglBindAPI(EGL_OPENGL_API);
|
||||
}
|
||||
|
||||
attribs[i++] = EGL_NONE;
|
||||
|
||||
|
||||
if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
|
||||
attribs,
|
||||
configs, SDL_arraysize(configs),
|
||||
|
@ -347,18 +364,27 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (_this->gl_config.major_version) {
|
||||
context_attrib_list[1] = _this->gl_config.major_version;
|
||||
}
|
||||
|
||||
if (_this->gl_config.share_with_current_context) {
|
||||
share_context = (EGLContext)SDL_GL_GetCurrentContext();
|
||||
}
|
||||
|
||||
/* Bind the API */
|
||||
if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
_this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
|
||||
if (_this->gl_config.major_version) {
|
||||
context_attrib_list[1] = _this->gl_config.major_version;
|
||||
}
|
||||
|
||||
egl_context =
|
||||
_this->egl_data->eglCreateContext(_this->egl_data->egl_display,
|
||||
_this->egl_data->egl_config,
|
||||
share_context, context_attrib_list);
|
||||
egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
|
||||
_this->egl_data->egl_config,
|
||||
share_context, context_attrib_list);
|
||||
}
|
||||
else {
|
||||
_this->egl_data->eglBindAPI(EGL_OPENGL_API);
|
||||
egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
|
||||
_this->egl_data->egl_config,
|
||||
share_context, NULL);
|
||||
}
|
||||
|
||||
if (egl_context == EGL_NO_CONTEXT) {
|
||||
SDL_SetError("Could not create EGL context");
|
||||
|
|
|
@ -76,6 +76,9 @@ typedef struct SDL_EGL_VideoData
|
|||
EGLBoolean(EGLAPIENTRY *eglWaitNative) (EGLint engine);
|
||||
|
||||
EGLBoolean(EGLAPIENTRY *eglWaitGL)(void);
|
||||
|
||||
EGLBoolean(EGLAPIENTRY *eglBindAPI)(EGLenum);
|
||||
|
||||
} SDL_EGL_VideoData;
|
||||
|
||||
/* OpenGLES functions */
|
||||
|
|
|
@ -369,6 +369,9 @@ extern VideoBootStrap RPI_bootstrap;
|
|||
#if SDL_VIDEO_DRIVER_DUMMY
|
||||
extern VideoBootStrap DUMMY_bootstrap;
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
extern VideoBootStrap Wayland_bootstrap;
|
||||
#endif
|
||||
|
||||
extern SDL_VideoDevice *SDL_GetVideoDevice(void);
|
||||
extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);
|
||||
|
|
|
@ -85,6 +85,9 @@ static VideoBootStrap *bootstrap[] = {
|
|||
#endif
|
||||
#if SDL_VIDEO_DRIVER_DUMMY
|
||||
&DUMMY_bootstrap,
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
&Wayland_bootstrap,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
|
381
src/video/wayland/SDL_waylandevents.c
Normal file
381
src/video/wayland/SDL_waylandevents.c
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.h"
|
||||
|
||||
#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 <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;
|
||||
|
||||
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 = wl_display_get_fd(d->display);
|
||||
pfd[0].events = POLLIN;
|
||||
poll(pfd, 1, 0);
|
||||
|
||||
if (pfd[0].revents & POLLIN)
|
||||
wl_display_dispatch(d->display);
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
input->pointer_focus = wl_surface_get_user_data(surface);
|
||||
window = input->pointer_focus;
|
||||
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;
|
||||
|
||||
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;
|
||||
int sx = wl_fixed_to_int(sx_w);
|
||||
int sy = wl_fixed_to_int(sy_w);
|
||||
|
||||
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
switch (button) {
|
||||
case BTN_LEFT:
|
||||
sdl_button = SDL_BUTTON_LEFT;
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 = xkb_map_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 = xkb_state_new(input->xkb.keymap);
|
||||
if (!input->xkb.state) {
|
||||
fprintf(stderr, "failed to create XKB state\n");
|
||||
xkb_map_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 = wl_surface_get_user_data(surface);
|
||||
|
||||
input->keyboard_focus = window;
|
||||
window->keyboard_device = input;
|
||||
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 (xkb_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
|
||||
return;
|
||||
|
||||
if (state) {
|
||||
size = 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;
|
||||
|
||||
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 = malloc(sizeof *input);
|
||||
if (input == NULL)
|
||||
return;
|
||||
|
||||
memset(input, 0, sizeof *input);
|
||||
input->display = d;
|
||||
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
|
||||
|
||||
d->input = input;
|
||||
|
||||
wl_seat_add_listener(input->seat, &seat_listener, input);
|
||||
wl_seat_set_user_data(input->seat, input);
|
||||
|
||||
wayland_schedule_write(d);
|
||||
}
|
||||
|
||||
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)
|
||||
xkb_state_unref(input->xkb.state);
|
||||
|
||||
if (input->xkb.keymap)
|
||||
xkb_map_unref(input->xkb.keymap);
|
||||
|
||||
free(input);
|
||||
d->input = NULL;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
37
src/video/wayland/SDL_waylandevents_c.h
Normal file
37
src/video/wayland/SDL_waylandevents_c.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.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: */
|
407
src/video/wayland/SDL_waylandmouse.c
Normal file
407
src/video/wayland/SDL_waylandmouse.c
Normal file
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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 _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_config.h"
|
||||
#include "SDL_mouse.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "SDL_waylandvideo.h"
|
||||
#include "SDL_waylandevents_c.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
|
||||
typedef struct {
|
||||
struct wl_buffer *buffer;
|
||||
struct wl_surface *surface;
|
||||
|
||||
int hot_x, hot_y;
|
||||
|
||||
/* 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;
|
||||
|
||||
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 (data == MAP_FAILED) {
|
||||
d->shm_data = NULL;
|
||||
fprintf (stderr, "mmap () failed\n");
|
||||
close (shm_fd);
|
||||
}
|
||||
|
||||
struct wl_shm_pool *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_attach(data->surface,
|
||||
data->buffer,
|
||||
0,
|
||||
0);
|
||||
wl_surface_damage(data->surface,
|
||||
0,
|
||||
0,
|
||||
surface->w,
|
||||
surface->h);
|
||||
wl_surface_commit(data->surface);
|
||||
|
||||
data->hot_x = hot_x;
|
||||
data->hot_y = hot_y;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* The wl_buffer here will be destroyed from wl_cursor_theme_destroy
|
||||
* if we are fetching this from a wl_cursor_theme, so don't store a
|
||||
* reference to it here */
|
||||
data->buffer = NULL;
|
||||
data->surface = wl_compositor_create_surface(d->compositor);
|
||||
wl_surface_attach(data->surface,
|
||||
wl_cursor_image_get_buffer(wlcursor->images[0]),
|
||||
0,
|
||||
0);
|
||||
wl_surface_damage(data->surface,
|
||||
0,
|
||||
0,
|
||||
wlcursor->images[0]->width,
|
||||
wlcursor->images[0]->height);
|
||||
wl_surface_commit(data->surface);
|
||||
data->hot_x = wlcursor->images[0]->hotspot_x;
|
||||
data->hot_y = wlcursor->images[0]->hotspot_y;
|
||||
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,
|
||||
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 = wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_IBEAM:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "wait");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAITARROW:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "wait");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENWSE:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENESW:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEWE:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENS:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEALL:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_NO:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_HAND:
|
||||
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_Cursor *sdl_cursor = CreateCursorFromWlCursor (d, cursor);
|
||||
|
||||
return sdl_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
Wayland_FreeCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
if (!cursor)
|
||||
return;
|
||||
|
||||
Wayland_CursorData *d = cursor->driverdata;
|
||||
|
||||
/* Probably not a cursor we own */
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
if (d->buffer)
|
||||
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_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();
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
Wayland_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return -1;
|
||||
}
|
||||
|
||||
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->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
|
31
src/video/wayland/SDL_waylandmouse.h
Normal file
31
src/video/wayland/SDL_waylandmouse.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.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
|
90
src/video/wayland/SDL_waylandopengles.c
Normal file
90
src/video/wayland/SDL_waylandopengles.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.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"
|
||||
|
||||
/* 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_schedule_write(data);
|
||||
|
||||
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_schedule_write(_this->driverdata);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void
|
||||
Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
|
||||
wayland_schedule_write(_this->driverdata);
|
||||
}
|
||||
|
||||
|
||||
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_schedule_write(_this->driverdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context)
|
||||
{
|
||||
SDL_EGL_DeleteContext(_this, context);
|
||||
wayland_schedule_write(_this->driverdata);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
46
src/video/wayland/SDL_waylandopengles.h
Normal file
46
src/video/wayland/SDL_waylandopengles.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.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 */
|
365
src/video/wayland/SDL_waylandvideo.c
Normal file
365
src/video/wayland/SDL_waylandvideo.c
Normal file
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.h"
|
||||
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_mouse.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 <fcntl.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#define WAYLANDVID_DRIVER_NAME "wayland"
|
||||
|
||||
struct wayland_mode {
|
||||
SDL_DisplayMode mode;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
/* 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;
|
||||
|
||||
display = wl_display_connect(NULL);
|
||||
if (display != NULL) {
|
||||
wl_display_disconnect(display);
|
||||
}
|
||||
|
||||
return (display != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
Wayland_DeleteDevice(SDL_VideoDevice *device)
|
||||
{
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *
|
||||
Wayland_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (!device) {
|
||||
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->free = Wayland_DeleteDevice;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
VideoBootStrap Wayland_bootstrap = {
|
||||
WAYLANDVID_DRIVER_NAME, "SDL Wayland video driver",
|
||||
Wayland_Available, Wayland_CreateDevice
|
||||
};
|
||||
|
||||
static void
|
||||
wayland_add_mode(SDL_VideoData *d, SDL_DisplayMode m)
|
||||
{
|
||||
struct wayland_mode *mode;
|
||||
|
||||
/* Check for duplicate mode */
|
||||
wl_list_for_each(mode, &d->modes_list, link)
|
||||
if (mode->mode.w == m.w && mode->mode.h == m.h &&
|
||||
mode->mode.refresh_rate == m.refresh_rate)
|
||||
return;
|
||||
|
||||
/* Add new mode to the list */
|
||||
mode = SDL_calloc(1, sizeof *mode);
|
||||
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
mode->mode = m;
|
||||
wl_list_insert(&d->modes_list, &mode->link);
|
||||
}
|
||||
|
||||
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_VideoData *d = data;
|
||||
|
||||
d->screen_allocation.x = x;
|
||||
d->screen_allocation.y = y;
|
||||
}
|
||||
|
||||
static void
|
||||
display_handle_mode(void *data,
|
||||
struct wl_output *wl_output,
|
||||
uint32_t flags,
|
||||
int width,
|
||||
int height,
|
||||
int refresh)
|
||||
{
|
||||
SDL_VideoData *d = data;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
SDL_zero(mode);
|
||||
mode.w = width;
|
||||
mode.h = height;
|
||||
mode.refresh_rate = refresh / 1000;
|
||||
|
||||
wayland_add_mode(d, mode);
|
||||
|
||||
if (flags & WL_OUTPUT_MODE_CURRENT) {
|
||||
d->screen_allocation.width = width;
|
||||
d->screen_allocation.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_output_listener output_listener = {
|
||||
display_handle_geometry,
|
||||
display_handle_mode
|
||||
};
|
||||
|
||||
static void
|
||||
shm_handle_format(void *data,
|
||||
struct wl_shm *shm,
|
||||
uint32_t format)
|
||||
{
|
||||
SDL_VideoData *d = data;
|
||||
|
||||
d->shm_formats |= (1 << format);
|
||||
}
|
||||
|
||||
static const struct wl_shm_listener shm_listener = {
|
||||
shm_handle_format
|
||||
};
|
||||
|
||||
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) {
|
||||
d->output = wl_registry_bind(d->registry, id, &wl_output_interface, 1);
|
||||
wl_output_add_listener(d->output, &output_listener, d);
|
||||
} 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 = wl_cursor_theme_load(NULL, 32, d->shm);
|
||||
d->default_cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
|
||||
wl_shm_add_listener(d->shm, &shm_listener, d);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
display_handle_global
|
||||
};
|
||||
|
||||
int
|
||||
Wayland_VideoInit(_THIS)
|
||||
{
|
||||
SDL_VideoData *data;
|
||||
|
||||
data = malloc(sizeof *data);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
memset(data, 0, sizeof *data);
|
||||
|
||||
_this->driverdata = data;
|
||||
|
||||
wl_list_init(&data->modes_list);
|
||||
|
||||
data->display = wl_display_connect(NULL);
|
||||
if (data->display == NULL) {
|
||||
SDL_SetError("Failed to connect to a Wayland display");
|
||||
return 0;
|
||||
}
|
||||
|
||||
data->registry = wl_display_get_registry(data->display);
|
||||
wl_registry_add_listener(data->registry, ®istry_listener, data);
|
||||
|
||||
while (data->screen_allocation.width == 0)
|
||||
wl_display_dispatch(data->display);
|
||||
|
||||
data->xkb_context = xkb_context_new(0);
|
||||
if (!data->xkb_context) {
|
||||
SDL_SetError("Failed to create XKB context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
/* Use a fake 32-bpp desktop mode */
|
||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
mode.w = data->screen_allocation.width;
|
||||
mode.h = data->screen_allocation.height;
|
||||
mode.refresh_rate = 0;
|
||||
mode.driverdata = NULL;
|
||||
wayland_add_mode(data, mode);
|
||||
SDL_zero(display);
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
display.driverdata = NULL;
|
||||
SDL_AddVideoDisplay(&display);
|
||||
|
||||
Wayland_InitMouse ();
|
||||
|
||||
wayland_schedule_write(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
SDL_DisplayMode mode;
|
||||
struct wayland_mode *m;
|
||||
|
||||
Wayland_PumpEvents(_this);
|
||||
|
||||
wl_list_for_each(m, &data->modes_list, link) {
|
||||
m->mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
SDL_AddDisplayMode(sdl_display, &m->mode);
|
||||
m->mode.format = SDL_PIXELFORMAT_RGBA8888;
|
||||
SDL_AddDisplayMode(sdl_display, &m->mode);
|
||||
}
|
||||
|
||||
mode.w = data->screen_allocation.width;
|
||||
mode.h = data->screen_allocation.height;
|
||||
mode.refresh_rate = 0;
|
||||
mode.driverdata = NULL;
|
||||
|
||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
SDL_AddDisplayMode(sdl_display, &mode);
|
||||
mode.format = SDL_PIXELFORMAT_RGBA8888;
|
||||
SDL_AddDisplayMode(sdl_display, &mode);
|
||||
}
|
||||
|
||||
static int
|
||||
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Wayland_VideoQuit(_THIS)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
struct wayland_mode *t, *m;
|
||||
|
||||
Wayland_FiniMouse ();
|
||||
|
||||
if (data->output)
|
||||
wl_output_destroy(data->output);
|
||||
|
||||
Wayland_display_destroy_input(data);
|
||||
|
||||
if (data->xkb_context) {
|
||||
xkb_context_unref(data->xkb_context);
|
||||
data->xkb_context = NULL;
|
||||
}
|
||||
|
||||
if (data->shm)
|
||||
wl_shm_destroy(data->shm);
|
||||
|
||||
if (data->cursor_theme)
|
||||
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->display) {
|
||||
wl_display_flush(data->display);
|
||||
wl_display_disconnect(data->display);
|
||||
}
|
||||
|
||||
wl_list_for_each_safe(m, t, &data->modes_list, link) {
|
||||
wl_list_remove(&m->link);
|
||||
free(m);
|
||||
}
|
||||
|
||||
|
||||
free(data);
|
||||
_this->driverdata = NULL;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
71
src/video/wayland/SDL_waylandvideo.h
Normal file
71
src/video/wayland/SDL_waylandvideo.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.h"
|
||||
|
||||
#ifndef _SDL_waylandvideo_h
|
||||
#define _SDL_waylandvideo_h
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-cursor.h>
|
||||
#include <wayland-egl.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
struct xkb_context;
|
||||
struct SDL_WaylandInput;
|
||||
|
||||
typedef struct {
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_output *output;
|
||||
struct wl_shm *shm;
|
||||
struct wl_cursor_theme *cursor_theme;
|
||||
struct wl_cursor *default_cursor;
|
||||
struct wl_pointer *pointer;
|
||||
struct wl_shell *shell;
|
||||
|
||||
struct {
|
||||
int32_t x, y, width, height;
|
||||
} screen_allocation;
|
||||
|
||||
struct wl_list modes_list;
|
||||
|
||||
EGLDisplay edpy;
|
||||
EGLContext context;
|
||||
EGLConfig econf;
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
struct SDL_WaylandInput *input;
|
||||
|
||||
uint32_t shm_formats;
|
||||
} SDL_VideoData;
|
||||
|
||||
static inline void
|
||||
wayland_schedule_write(SDL_VideoData *data)
|
||||
{
|
||||
wl_display_flush(data->display);
|
||||
}
|
||||
|
||||
#endif /* _SDL_nullvideo_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
192
src/video/wayland/SDL_waylandwindow.c
Normal file
192
src/video/wayland/SDL_waylandwindow.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.h"
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
#include "SDL_waylandwindow.h"
|
||||
#include "SDL_waylandvideo.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)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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, NULL);
|
||||
else
|
||||
wl_shell_surface_set_toplevel(wind->shell_surface);
|
||||
|
||||
wayland_schedule_write(_this->driverdata);
|
||||
}
|
||||
|
||||
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, NULL);
|
||||
else
|
||||
wl_shell_surface_set_toplevel(wind->shell_surface);
|
||||
|
||||
wayland_schedule_write(_this->driverdata);
|
||||
}
|
||||
|
||||
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 0;
|
||||
|
||||
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);
|
||||
data->egl_window = 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) {
|
||||
SDL_SetError("failed to create a window surface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_schedule_write(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Wayland_SetWindowSize(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
struct wl_region *region;
|
||||
|
||||
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;
|
||||
|
||||
window->driverdata = NULL;
|
||||
|
||||
if (data) {
|
||||
SDL_EGL_DestroySurface(_this, wind->egl_surface);
|
||||
wl_egl_window_destroy(wind->egl_window);
|
||||
|
||||
if (wind->shell_surface)
|
||||
wl_shell_surface_destroy(wind->shell_surface);
|
||||
|
||||
wl_surface_destroy(wind->surface);
|
||||
|
||||
SDL_free(wind);
|
||||
wayland_schedule_write(data);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
58
src/video/wayland/SDL_waylandwindow.h
Normal file
58
src/video/wayland/SDL_waylandwindow.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 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_config.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;
|
||||
} 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);
|
||||
|
||||
#endif /* _SDL_waylandwindow_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
Loading…
Add table
Add a link
Reference in a new issue