SDL_waylandvideo.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2016 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: */
Wayland_SetWindowSize
void Wayland_SetWindowSize(_THIS, SDL_Window *window)
Wayland_SetWindowFullscreen
void Wayland_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen)
SDL_WAYLAND_UnloadSymbols
void SDL_WAYLAND_UnloadSymbols(void)
width
GLint GLint GLsizei width
Definition: SDL_opengl.h:1565
SDL_VideoDevice::SetWindowHitTest
int(* SetWindowHitTest)(SDL_Window *window, SDL_bool enabled)
Definition: SDL_sysvideo.h:274
int32_t
signed int int32_t
Definition: SDL_config_windows.h:61
SDL_DisplayMode::w
int w
Definition: SDL_video.h:56
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
Wayland_SetWindowHitTest
int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
SDL_VideoData::display
struct wl_display * display
Definition: SDL_waylandvideo.h:40
Wayland_GLES_DeleteContext
void Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context)
SDL_VideoDevice::free
void(* free)(_THIS)
Definition: SDL_sysvideo.h:345
SDL_VideoDisplay::name
char * name
Definition: SDL_sysvideo.h:122
SDL_waylandtouch.h
free
SDL_EventEntry * free
Definition: SDL_events.c:81
Wayland_GLES_UnloadLibrary
#define Wayland_GLES_UnloadLibrary
Definition: SDL_waylandopengles.h:36
SDL_waylandwindow.h
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:332
SDL_VideoDevice::GL_SetSwapInterval
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:240
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
SDL_VideoDevice::ShowWindow
void(* ShowWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:203
SDL_DisplayMode
The structure that defines a display mode.
Definition: SDL_video.h:53
memset
#define memset
Definition: SDL_malloc.c:639
Wayland_ShowWindow
void Wayland_ShowWindow(_THIS, SDL_Window *window)
SDL_VideoDevice::SetWindowSize
void(* SetWindowSize)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:200
SDL_DisplayMode::refresh_rate
int refresh_rate
Definition: SDL_video.h:58
SDL_waylandmouse.h
Wayland_GLES_GetSwapInterval
#define Wayland_GLES_GetSwapInterval
Definition: SDL_waylandopengles.h:38
SDL_VideoData::cursor_theme
struct wl_cursor_theme * cursor_theme
Definition: SDL_waylandvideo.h:44
SDL_VideoDevice::GL_SwapWindow
void(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:242
height
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1565
Wayland_CreateWindow
int Wayland_CreateWindow(_THIS, SDL_Window *window)
SDL_waylandopengles.h
SDL_AddVideoDisplay
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
Definition: SDL_video.c:593
SDL_VideoDevice::GL_LoadLibrary
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:234
SDL_VideoDevice::SetDisplayMode
int(* SetDisplayMode)(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
Definition: SDL_sysvideo.h:189
Wayland_GLES_CreateContext
SDL_GLContext Wayland_GLES_CreateContext(_THIS, SDL_Window *window)
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:114
SDL_video.h
SDL_calloc
void * SDL_calloc(size_t nmemb, size_t size)
Wayland_GLES_SetSwapInterval
#define Wayland_GLES_SetSwapInterval
Definition: SDL_waylandopengles.h:37
SDL_VideoDevice::GetWindowWMInfo
SDL_bool(* GetWindowWMInfo)(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
Definition: SDL_sysvideo.h:227
SDL_VideoDevice::GL_CreateContext
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:237
Wayland_DestroyWindow
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
d
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
Definition: SDL_dynapi_procs.h:121
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_VideoDevice::GL_MakeCurrent
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:238
SDL_free
void SDL_free(void *mem)
SDL_mouse.h
VideoBootStrap
Definition: SDL_sysvideo.h:348
sort_controllers.output
output
Definition: sort_controllers.py:10
SDL_VideoDevice::num_displays
int num_displays
Definition: SDL_sysvideo.h:279
SDL_VideoData::xkb_context
struct xkb_context * xkb_context
Definition: SDL_waylandvideo.h:53
SDL_WAYLAND_LoadSymbols
int SDL_WAYLAND_LoadSymbols(void)
Wayland_GetWindowWMInfo
SDL_bool Wayland_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
SDL_VideoData::shell
struct wl_shell * shell
Definition: SDL_waylandvideo.h:47
SDL_VideoDisplay::current_mode
SDL_DisplayMode current_mode
Definition: SDL_sysvideo.h:127
mode
GLenum mode
Definition: SDL_opengl_glext.h:1122
SDL_VideoDevice::displays
SDL_VideoDisplay * displays
Definition: SDL_sysvideo.h:280
SDL_VideoDevice::DestroyWindow
void(* DestroyWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:214
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:355
SDL_DisplayMode::h
int h
Definition: SDL_video.h:57
SDL_waylanddyn.h
Wayland_GLES_MakeCurrent
int Wayland_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context)
Wayland_display_add_input
void Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
SDL_VideoDisplay
Definition: SDL_sysvideo.h:120
SDL_VideoDevice::GL_UnloadLibrary
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:236
SDL_VideoData::default_cursor
struct wl_cursor * default_cursor
Definition: SDL_waylandvideo.h:45
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:42
SDL_VideoDevice::GetDisplayModes
void(* GetDisplayModes)(_THIS, SDL_VideoDisplay *display)
Definition: SDL_sysvideo.h:181
Wayland_GLES_GetProcAddress
#define Wayland_GLES_GetProcAddress
Definition: SDL_waylandopengles.h:35
SDL_waylandvideo.h
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_VideoDisplay::desktop_mode
SDL_DisplayMode desktop_mode
Definition: SDL_sysvideo.h:126
uint32_t
unsigned int uint32_t
Definition: SDL_config_windows.h:62
SDL_VideoDevice::VideoQuit
void(* VideoQuit)(_THIS)
Definition: SDL_sysvideo.h:161
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:36
SDL_VideoData::compositor
struct wl_compositor * compositor
Definition: SDL_waylandvideo.h:42
Wayland_display_destroy_input
void Wayland_display_destroy_input(SDL_VideoData *d)
Wayland_PumpEvents
void Wayland_PumpEvents(_THIS)
SDL_stdinc.h
SDL_VideoDevice::CreateWindow
int(* CreateWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:195
transform
GLuint GLenum GLenum transform
Definition: SDL_opengl_glext.h:9996
SDL_VideoData::registry
struct wl_registry * registry
Definition: SDL_waylandvideo.h:41
SDL_VideoDevice
Definition: SDL_sysvideo.h:142
SDL_VideoData
Definition: SDL_androidvideo.h:35
SDL_waylandevents_c.h
SDL_AddDisplayMode
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
Definition: SDL_video.c:709
SDL_VideoDevice::VideoInit
int(* VideoInit)(_THIS)
Definition: SDL_sysvideo.h:155
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
SDL_VideoDevice::SetWindowFullscreen
void(* SetWindowFullscreen)(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
Definition: SDL_sysvideo.h:210
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
SDL_VideoDevice::GL_DeleteContext
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:243
SDL_VideoDevice::GL_GetSwapInterval
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:241
Wayland_GLES_LoadLibrary
int Wayland_GLES_LoadLibrary(_THIS, const char *path)
Wayland_GLES_SwapWindow
void Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
SDL_VideoData::shm
struct wl_shm * shm
Definition: SDL_waylandvideo.h:43
SDL_Unsupported
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_VideoDevice::GL_GetProcAddress
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:235
SDL_SendQuit
int SDL_SendQuit(void)
Definition: SDL_quit.c:139
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:133
SDL_VideoDevice::PumpEvents
void(* PumpEvents)(_THIS)
Definition: SDL_sysvideo.h:249