SDL_x11window.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_X11
#include "SDL_assert.h"
#include "SDL_hints.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h"
#include "SDL_x11video.h"
#include "SDL_x11mouse.h"
#include "SDL_x11shape.h"
#include "SDL_x11xinput2.h"
#if SDL_VIDEO_OPENGL_EGL
#include "SDL_x11opengles.h"
#endif
#include "SDL_timer.h"
#include "SDL_syswm.h"
#include "SDL_assert.h"
#define _NET_WM_STATE_REMOVE 0l
#define _NET_WM_STATE_ADD 1l
#define _NET_WM_STATE_TOGGLE 2l
static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
{
return ev->type == MapNotify && ev->xmap.window == *((Window*)win);
}
static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win)
{
return ev->type == UnmapNotify && ev->xunmap.window == *((Window*)win);
}
/*
static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
{
return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
}
static Bool
X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg, int timeoutMS)
{
Uint32 start = SDL_GetTicks();
while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), start + timeoutMS)) {
return False;
}
}
return True;
}
*/
static SDL_bool
X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
return (data->fswindow != 0);
}
static SDL_bool
X11_IsWindowMapped(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
XWindowAttributes attr;
X11_XGetWindowAttributes(videodata->display, data->xwindow, &attr);
if (attr.map_state != IsUnmapped) {
return SDL_TRUE;
} else {
return SDL_FALSE;
}
}
#if 0
static SDL_bool
X11_IsActionAllowed(SDL_Window *window, Atom action)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Atom _NET_WM_ALLOWED_ACTIONS = data->videodata->_NET_WM_ALLOWED_ACTIONS;
Atom type;
Display *display = data->videodata->display;
int form;
unsigned long remain;
unsigned long len, i;
Atom *list;
SDL_bool ret = SDL_FALSE;
if (X11_XGetWindowProperty(display, data->xwindow, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, XA_ATOM, &type, &form, &len, &remain, (unsigned char **)&list) == Success)
{
for (i=0; i<len; ++i)
{
if (list[i] == action) {
ret = SDL_TRUE;
break;
}
}
X11_XFree(list);
}
return ret;
}
#endif /* 0 */
void
X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
Display *display = videodata->display;
Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
/* Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN; */
Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
Atom atoms[5];
int count = 0;
/* The window manager sets this property, we shouldn't set it.
If we did, this would indicate to the window manager that we don't
actually want to be mapped during X11_XMapRaised(), which would be bad.
*
if (flags & SDL_WINDOW_HIDDEN) {
atoms[count++] = _NET_WM_STATE_HIDDEN;
}
*/
if (flags & SDL_WINDOW_INPUT_FOCUS) {
atoms[count++] = _NET_WM_STATE_FOCUSED;
}
if (flags & SDL_WINDOW_MAXIMIZED) {
atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
}
if (flags & SDL_WINDOW_FULLSCREEN) {
atoms[count++] = _NET_WM_STATE_FULLSCREEN;
}
if (count > 0) {
X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char *)atoms, count);
} else {
X11_XDeleteProperty(display, xwindow, _NET_WM_STATE);
}
}
Uint32
X11_GetNetWMState(_THIS, Window xwindow)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
Display *display = videodata->display;
Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
Atom actualType;
int actualFormat;
unsigned long i, numItems, bytesAfter;
unsigned char *propertyValue = NULL;
long maxLength = 1024;
Uint32 flags = 0;
if (X11_XGetWindowProperty(display, xwindow, _NET_WM_STATE,
0l, maxLength, False, XA_ATOM, &actualType,
&actualFormat, &numItems, &bytesAfter,
&propertyValue) == Success) {
Atom *atoms = (Atom *) propertyValue;
int maximized = 0;
int fullscreen = 0;
for (i = 0; i < numItems; ++i) {
if (atoms[i] == _NET_WM_STATE_HIDDEN) {
flags |= SDL_WINDOW_HIDDEN;
} else if (atoms[i] == _NET_WM_STATE_FOCUSED) {
flags |= SDL_WINDOW_INPUT_FOCUS;
} else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
maximized |= 1;
} else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
maximized |= 2;
} else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
fullscreen = 1;
}
}
if (maximized == 3) {
flags |= SDL_WINDOW_MAXIMIZED;
} else if (fullscreen == 1) {
flags |= SDL_WINDOW_FULLSCREEN;
}
X11_XFree(propertyValue);
}
/* FIXME, check the size hints for resizable */
/* flags |= SDL_WINDOW_RESIZABLE; */
return flags;
}
static int
SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
SDL_WindowData *data;
int numwindows = videodata->numwindows;
int windowlistlength = videodata->windowlistlength;
SDL_WindowData **windowlist = videodata->windowlist;
/* Allocate the window data */
data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
if (!data) {
return SDL_OutOfMemory();
}
data->window = window;
data->xwindow = w;
#ifdef X_HAVE_UTF8_STRING
if (SDL_X11_HAVE_UTF8 && videodata->im) {
data->ic =
X11_XCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
NULL);
}
#endif
data->created = created;
data->videodata = videodata;
/* Associate the data with the window */
if (numwindows < windowlistlength) {
windowlist[numwindows] = data;
videodata->numwindows++;
} else {
windowlist =
(SDL_WindowData **) SDL_realloc(windowlist,
(numwindows +
1) * sizeof(*windowlist));
if (!windowlist) {
SDL_free(data);
return SDL_OutOfMemory();
}
windowlist[numwindows] = data;
videodata->numwindows++;
videodata->windowlistlength++;
videodata->windowlist = windowlist;
}
/* Fill in the SDL window with the window data */
{
XWindowAttributes attrib;
X11_XGetWindowAttributes(data->videodata->display, w, &attrib);
window->x = attrib.x;
window->y = attrib.y;
window->w = attrib.width;
window->h = attrib.height;
if (attrib.map_state != IsUnmapped) {
window->flags |= SDL_WINDOW_SHOWN;
} else {
window->flags &= ~SDL_WINDOW_SHOWN;
}
data->visual = attrib.visual;
data->colormap = attrib.colormap;
}
window->flags |= X11_GetNetWMState(_this, w);
{
Window FocalWindow;
int RevertTo=0;
X11_XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
if (FocalWindow==w)
{
window->flags |= SDL_WINDOW_INPUT_FOCUS;
}
if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
SDL_SetKeyboardFocus(data->window);
}
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
/* Tell x11 to clip mouse */
}
}
/* All done! */
window->driverdata = data;
return 0;
}
static void
SetWindowBordered(Display *display, int screen, Window window, SDL_bool border)
{
/*
* this code used to check for KWM_WIN_DECORATION, but KDE hasn't
* supported it for years and years. It now respects _MOTIF_WM_HINTS.
* Gnome is similar: just use the Motif atom.
*/
Atom WM_HINTS = X11_XInternAtom(display, "_MOTIF_WM_HINTS", True);
if (WM_HINTS != None) {
/* Hints used by Motif compliant window managers */
struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} MWMHints = {
(1L << 1), 0, border ? 1 : 0, 0, 0
};
X11_XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
PropModeReplace, (unsigned char *) &MWMHints,
sizeof(MWMHints) / sizeof(long));
} else { /* set the transient hints instead, if necessary */
X11_XSetTransientForHint(display, window, RootWindow(display, screen));
}
}
int
X11_CreateWindow(_THIS, SDL_Window * window)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
SDL_DisplayData *displaydata =
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
SDL_WindowData *windowdata;
Display *display = data->display;
int screen = displaydata->screen;
Visual *visual;
int depth;
XSetWindowAttributes xattr;
Window w;
XSizeHints *sizehints;
XWMHints *wmhints;
XClassHint *classhints;
const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1;
Atom _NET_WM_BYPASS_COMPOSITOR;
Atom _NET_WM_WINDOW_TYPE;
Atom _NET_WM_WINDOW_TYPE_NORMAL;
Atom _NET_WM_PID;
Atom XdndAware, xdnd_version = 5;
long fevent = 0;
#if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_EGL
if ((window->flags & SDL_WINDOW_OPENGL) &&
!SDL_getenv("SDL_VIDEO_X11_VISUALID")) {
XVisualInfo *vinfo = NULL;
#if SDL_VIDEO_OPENGL_EGL
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
#if SDL_VIDEO_OPENGL_GLX
&& ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile )
#endif
) {
vinfo = X11_GLES_GetVisual(_this, display, screen);
} else
#endif
{
#if SDL_VIDEO_OPENGL_GLX
vinfo = X11_GL_GetVisual(_this, display, screen);
#endif
}
if (!vinfo) {
return -1;
}
visual = vinfo->visual;
depth = vinfo->depth;
X11_XFree(vinfo);
} else
#endif
{
visual = displaydata->visual;
depth = displaydata->depth;
}
xattr.override_redirect = False;
xattr.background_pixmap = None;
xattr.border_pixel = 0;
if (visual->class == DirectColor) {
XColor *colorcells;
int i;
int ncolors;
int rmax, gmax, bmax;
int rmask, gmask, bmask;
int rshift, gshift, bshift;
xattr.colormap =
X11_XCreateColormap(display, RootWindow(display, screen),
visual, AllocAll);
/* If we can't create a colormap, then we must die */
if (!xattr.colormap) {
return SDL_SetError("Could not create writable colormap");
}
/* OK, we got a colormap, now fill it in as best as we can */
colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
if (!colorcells) {
return SDL_OutOfMemory();
}
ncolors = visual->map_entries;
rmax = 0xffff;
gmax = 0xffff;
bmax = 0xffff;
rshift = 0;
rmask = visual->red_mask;
while (0 == (rmask & 1)) {
rshift++;
rmask >>= 1;
}
gshift = 0;
gmask = visual->green_mask;
while (0 == (gmask & 1)) {
gshift++;
gmask >>= 1;
}
bshift = 0;
bmask = visual->blue_mask;
while (0 == (bmask & 1)) {
bshift++;
bmask >>= 1;
}
/* build the color table pixel values */
for (i = 0; i < ncolors; i++) {
Uint32 red = (rmax * i) / (ncolors - 1);
Uint32 green = (gmax * i) / (ncolors - 1);
Uint32 blue = (bmax * i) / (ncolors - 1);
Uint32 rbits = (rmask * i) / (ncolors - 1);
Uint32 gbits = (gmask * i) / (ncolors - 1);
Uint32 bbits = (bmask * i) / (ncolors - 1);
Uint32 pix =
(rbits << rshift) | (gbits << gshift) | (bbits << bshift);
colorcells[i].pixel = pix;
colorcells[i].red = red;
colorcells[i].green = green;
colorcells[i].blue = blue;
colorcells[i].flags = DoRed | DoGreen | DoBlue;
}
X11_XStoreColors(display, xattr.colormap, colorcells, ncolors);
SDL_free(colorcells);
} else {
xattr.colormap =
X11_XCreateColormap(display, RootWindow(display, screen),
visual, AllocNone);
}
w = X11_XCreateWindow(display, RootWindow(display, screen),
window->x, window->y, window->w, window->h,
0, depth, InputOutput, visual,
(CWOverrideRedirect | CWBackPixmap | CWBorderPixel |
CWColormap), &xattr);
if (!w) {
return SDL_SetError("Couldn't create window");
}
SetWindowBordered(display, screen, w,
(window->flags & SDL_WINDOW_BORDERLESS) == 0);
sizehints = X11_XAllocSizeHints();
/* Setup the normal size hints */
sizehints->flags = 0;
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
sizehints->min_width = sizehints->max_width = window->w;
sizehints->min_height = sizehints->max_height = window->h;
sizehints->flags |= (PMaxSize | PMinSize);
}
sizehints->x = window->x;
sizehints->y = window->y;
sizehints->flags |= USPosition;
/* Setup the input hints so we get keyboard input */
wmhints = X11_XAllocWMHints();
wmhints->input = True;
wmhints->flags = InputHint;
/* Setup the class hints so we can get an icon (AfterStep) */
classhints = X11_XAllocClassHint();
classhints->res_name = data->classname;
classhints->res_class = data->classname;
/* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
X11_XSetWMProperties(display, w, NULL, NULL, NULL, 0, sizehints, wmhints, classhints);
X11_XFree(sizehints);
X11_XFree(wmhints);
X11_XFree(classhints);
/* Set the PID related to the window for the given hostname, if possible */
if (data->pid > 0) {
_NET_WM_PID = X11_XInternAtom(display, "_NET_WM_PID", False);
X11_XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&data->pid, 1);
}
/* Set the window manager state */
X11_SetNetWMState(_this, w, window->flags);
/* Let the window manager know we're a "normal" window */
_NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
_NET_WM_WINDOW_TYPE_NORMAL = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
PropModeReplace,
(unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
_NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
PropModeReplace,
(unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
{
Atom protocols[2];
int proto_count = 0;
const char *ping_hint;
protocols[proto_count] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
proto_count++;
ping_hint = SDL_GetHint(SDL_HINT_VIDEO_X11_NET_WM_PING);
/* Default to using ping if there is no hint */
if (!ping_hint || SDL_atoi(ping_hint)) {
protocols[proto_count] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
proto_count++;
}
SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));
X11_XSetWMProtocols(display, w, protocols, proto_count);
}
if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
X11_XDestroyWindow(display, w);
return -1;
}
windowdata = (SDL_WindowData *) window->driverdata;
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
if ((window->flags & SDL_WINDOW_OPENGL) &&
_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
#if SDL_VIDEO_OPENGL_GLX
&& ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile )
#endif
) {
#if SDL_VIDEO_OPENGL_EGL
if (!_this->egl_data) {
X11_XDestroyWindow(display, w);
return -1;
}
/* Create the GLES window surface */
windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) w);
if (windowdata->egl_surface == EGL_NO_SURFACE) {
X11_XDestroyWindow(display, w);
return SDL_SetError("Could not create GLES window surface");
}
#else
return SDL_SetError("Could not create GLES window surface (no EGL support available)");
#endif /* SDL_VIDEO_OPENGL_EGL */
}
#endif
#ifdef X_HAVE_UTF8_STRING
if (SDL_X11_HAVE_UTF8 && windowdata->ic) {
X11_XGetICValues(windowdata->ic, XNFilterEvents, &fevent, NULL);
}
#endif
X11_Xinput2SelectTouch(_this, window);
X11_XSelectInput(display, w,
(FocusChangeMask | EnterWindowMask | LeaveWindowMask |
ExposureMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | KeyPressMask | KeyReleaseMask |
PropertyChangeMask | StructureNotifyMask |
KeymapStateMask | fevent));
XdndAware = X11_XInternAtom(display, "XdndAware", False);
X11_XChangeProperty(display, w, XdndAware, XA_ATOM, 32,
PropModeReplace,
(unsigned char*)&xdnd_version, 1);
X11_XFlush(display);
return 0;
}
int
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
{
Window w = (Window) data;
window->title = X11_GetWindowTitle(_this, w);
if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
return -1;
}
return 0;
}
char *
X11_GetWindowTitle(_THIS, Window xwindow)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
Display *display = data->display;
int status, real_format;
Atom real_type;
unsigned long items_read, items_left;
unsigned char *propdata;
char *title = NULL;
status = X11_XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
&items_read, &items_left, &propdata);
if (status == Success && propdata) {
title = SDL_strdup(SDL_static_cast(char*, propdata));
X11_XFree(propdata);
} else {
status = X11_XGetWindowProperty(display, xwindow, XA_WM_NAME,
0L, 8192L, False, XA_STRING, &real_type, &real_format,
&items_read, &items_left, &propdata);
if (status == Success && propdata) {
title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
X11_XFree(propdata);
} else {
title = SDL_strdup("");
}
}
return title;
}
void
X11_SetWindowTitle(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
XTextProperty titleprop;
Status status;
const char *title = window->title ? window->title : "";
char *title_locale = NULL;
#ifdef X_HAVE_UTF8_STRING
Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
#endif
title_locale = SDL_iconv_utf8_locale(title);
if (!title_locale) {
SDL_OutOfMemory();
return;
}
status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
SDL_free(title_locale);
if (status) {
X11_XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
X11_XFree(titleprop.value);
}
#ifdef X_HAVE_UTF8_STRING
if (SDL_X11_HAVE_UTF8) {
status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1,
XUTF8StringStyle, &titleprop);
if (status == Success) {
X11_XSetTextProperty(display, data->xwindow, &titleprop,
_NET_WM_NAME);
X11_XFree(titleprop.value);
}
}
#endif
X11_XFlush(display);
}
void
X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
if (icon) {
int propsize;
long *propdata;
/* Set the _NET_WM_ICON property */
SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
propsize = 2 + (icon->w * icon->h);
propdata = SDL_malloc(propsize * sizeof(long));
if (propdata) {
int x, y;
Uint32 *src;
long *dst;
propdata[0] = icon->w;
propdata[1] = icon->h;
dst = &propdata[2];
for (y = 0; y < icon->h; ++y) {
src = (Uint32*)((Uint8*)icon->pixels + y * icon->pitch);
for (x = 0; x < icon->w; ++x) {
*dst++ = *src++;
}
}
X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
32, PropModeReplace, (unsigned char *) propdata,
propsize);
}
SDL_free(propdata);
} else {
X11_XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
}
X11_XFlush(display);
}
void
X11_SetWindowPosition(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
X11_XMoveWindow(display, data->xwindow, window->x, window->y);
X11_XFlush(display);
}
void
X11_SetWindowMinimumSize(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
if (window->flags & SDL_WINDOW_RESIZABLE) {
XSizeHints *sizehints = X11_XAllocSizeHints();
long userhints;
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
sizehints->min_width = window->min_w;
sizehints->min_height = window->min_h;
sizehints->flags |= PMinSize;
X11_XSetWMNormalHints(display, data->xwindow, sizehints);
X11_XFree(sizehints);
/* See comment in X11_SetWindowSize. */
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
X11_XMoveWindow(display, data->xwindow, window->x, window->y);
X11_XRaiseWindow(display, data->xwindow);
}
X11_XFlush(display);
}
void
X11_SetWindowMaximumSize(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
if (window->flags & SDL_WINDOW_RESIZABLE) {
XSizeHints *sizehints = X11_XAllocSizeHints();
long userhints;
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
sizehints->max_width = window->max_w;
sizehints->max_height = window->max_h;
sizehints->flags |= PMaxSize;
X11_XSetWMNormalHints(display, data->xwindow, sizehints);
X11_XFree(sizehints);
/* See comment in X11_SetWindowSize. */
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
X11_XMoveWindow(display, data->xwindow, window->x, window->y);
X11_XRaiseWindow(display, data->xwindow);
}
X11_XFlush(display);
}
void
X11_SetWindowSize(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
if (SDL_IsShapedWindow(window)) {
X11_ResizeWindowShape(window);
}
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
/* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the X11_XResizeWindow, thus
we must set the size hints to adjust the window size. */
XSizeHints *sizehints = X11_XAllocSizeHints();
long userhints;
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
sizehints->min_width = sizehints->max_width = window->w;
sizehints->min_height = sizehints->max_height = window->h;
sizehints->flags |= PMinSize | PMaxSize;
X11_XSetWMNormalHints(display, data->xwindow, sizehints);
X11_XFree(sizehints);
/* From Pierre-Loup:
WMs each have their little quirks with that. When you change the
size hints, they get a ConfigureNotify event with the
WM_NORMAL_SIZE_HINTS Atom. They all save the hints then, but they
don't all resize the window right away to enforce the new hints.
Some of them resize only after:
- A user-initiated move or resize
- A code-initiated move or resize
- Hiding & showing window (Unmap & map)
The following move & resize seems to help a lot of WMs that didn't
properly update after the hints were changed. We don't do a
hide/show, because there are supposedly subtle problems with doing so
and transitioning from windowed to fullscreen in Unity.
*/
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
X11_XMoveWindow(display, data->xwindow, window->x, window->y);
X11_XRaiseWindow(display, data->xwindow);
} else {
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
}
X11_XFlush(display);
}
void
X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
{
const SDL_bool focused = ((window->flags & SDL_WINDOW_INPUT_FOCUS) != 0);
const SDL_bool visible = ((window->flags & SDL_WINDOW_HIDDEN) == 0);
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata =
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
Display *display = data->videodata->display;
XEvent event;
SetWindowBordered(display, displaydata->screen, data->xwindow, bordered);
X11_XFlush(display);
if (visible) {
XWindowAttributes attr;
do {
X11_XSync(display, False);
X11_XGetWindowAttributes(display, data->xwindow, &attr);
} while (attr.map_state != IsViewable);
if (focused) {
X11_XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
}
}
/* make sure these don't make it to the real event queue if they fired here. */
X11_XSync(display, False);
X11_XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
}
void
X11_ShowWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
XEvent event;
if (!X11_IsWindowMapped(_this, window)) {
X11_XMapRaised(display, data->xwindow);
/* Blocking wait for "MapNotify" event.
* We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type,
* and XCheckTypedWindowEvent doesn't block */
X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
X11_XFlush(display);
}
if (!data->videodata->net_wm) {
/* no WM means no FocusIn event, which confuses us. Force it. */
X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
X11_XFlush(display);
}
}
void
X11_HideWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
Display *display = data->videodata->display;
XEvent event;
if (X11_IsWindowMapped(_this, window)) {
X11_XWithdrawWindow(display, data->xwindow, displaydata->screen);
/* Blocking wait for "UnmapNotify" event */
X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
X11_XFlush(display);
}
}
static void
SetWindowActive(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata =
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
Display *display = data->videodata->display;
Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_WINDOW;
if (X11_IsWindowMapped(_this, window)) {
XEvent e;
SDL_zero(e);
e.xany.type = ClientMessage;
e.xclient.message_type = _NET_ACTIVE_WINDOW;
e.xclient.format = 32;
e.xclient.window = data->xwindow;
e.xclient.data.l[0] = 1; /* source indication. 1 = application */
e.xclient.data.l[1] = CurrentTime;
e.xclient.data.l[2] = 0;
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
X11_XFlush(display);
}
}
void
X11_RaiseWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
X11_XRaiseWindow(display, data->xwindow);
SetWindowActive(_this, window);
X11_XFlush(display);
}
static void
SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata =
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
Display *display = data->videodata->display;
Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
if (maximized) {
window->flags |= SDL_WINDOW_MAXIMIZED;
} else {
window->flags &= ~SDL_WINDOW_MAXIMIZED;
}
if (X11_IsWindowMapped(_this, window)) {
XEvent e;
SDL_zero(e);
e.xany.type = ClientMessage;
e.xclient.message_type = _NET_WM_STATE;
e.xclient.format = 32;
e.xclient.window = data->xwindow;
e.xclient.data.l[0] =
maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
e.xclient.data.l[3] = 0l;
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
} else {
X11_SetNetWMState(_this, data->xwindow, window->flags);
}
X11_XFlush(display);
}
void
X11_MaximizeWindow(_THIS, SDL_Window * window)
{
SetWindowMaximized(_this, window, SDL_TRUE);
}
void
X11_MinimizeWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata =
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
Display *display = data->videodata->display;
X11_XIconifyWindow(display, data->xwindow, displaydata->screen);
X11_XFlush(display);
}
void
X11_RestoreWindow(_THIS, SDL_Window * window)
{
SetWindowMaximized(_this, window, SDL_FALSE);
X11_ShowWindow(_this, window);
SetWindowActive(_this, window);
}
/* This asks the Window Manager to handle fullscreen for us. Most don't do it right, though. */
static void
X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
Display *display = data->videodata->display;
Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
if (X11_IsWindowMapped(_this, window)) {
XEvent e;
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
/* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
can be resized to the fullscreen resolution (or reset so we're not resizable again) */
XSizeHints *sizehints = X11_XAllocSizeHints();
long flags = 0;
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &flags);
/* set the resize flags on */
if (fullscreen) {
/* we are going fullscreen so turn the flags off */
sizehints->flags &= ~(PMinSize | PMaxSize);
} else {
/* Reset the min/max width height to make the window non-resizable again */
sizehints->flags |= PMinSize | PMaxSize;
sizehints->min_width = sizehints->max_width = window->windowed.w;
sizehints->min_height = sizehints->max_height = window->windowed.h;
}
X11_XSetWMNormalHints(display, data->xwindow, sizehints);
X11_XFree(sizehints);
}
SDL_zero(e);
e.xany.type = ClientMessage;
e.xclient.message_type = _NET_WM_STATE;
e.xclient.format = 32;
e.xclient.window = data->xwindow;
e.xclient.data.l[0] =
fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
e.xclient.data.l[3] = 0l;
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
} else {
Uint32 flags;
flags = window->flags;
if (fullscreen) {
flags |= SDL_WINDOW_FULLSCREEN;
} else {
flags &= ~SDL_WINDOW_FULLSCREEN;
}
X11_SetNetWMState(_this, data->xwindow, flags);
}
if (data->visual->class == DirectColor) {
if ( fullscreen ) {
X11_XInstallColormap(display, data->colormap);
} else {
X11_XUninstallColormap(display, data->colormap);
}
}
X11_XFlush(display);
}
/* This handles fullscreen itself, outside the Window Manager. */
static void
X11_BeginWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
Visual *visual = data->visual;
Display *display = data->videodata->display;
const int screen = displaydata->screen;
Window root = RootWindow(display, screen);
const int def_vis = (visual == DefaultVisual(display, screen));
unsigned long xattrmask = 0;
XSetWindowAttributes xattr;
XEvent ev;
SDL_Rect rect;
if ( data->fswindow ) {
return; /* already fullscreen, I hope. */
}
X11_GetDisplayBounds(_this, _display, &rect);
SDL_zero(xattr);
xattr.override_redirect = True;
xattrmask |= CWOverrideRedirect;
xattr.background_pixel = def_vis ? BlackPixel(display, screen) : 0;
xattrmask |= CWBackPixel;
xattr.border_pixel = 0;
xattrmask |= CWBorderPixel;
xattr.colormap = data->colormap;
xattrmask |= CWColormap;
data->fswindow = X11_XCreateWindow(display, root,
rect.x, rect.y, rect.w, rect.h, 0,
displaydata->depth, InputOutput,
visual, xattrmask, &xattr);
X11_XSelectInput(display, data->fswindow, StructureNotifyMask);
X11_XSetWindowBackground(display, data->fswindow, 0);
X11_XInstallColormap(display, data->colormap);
X11_XClearWindow(display, data->fswindow);
X11_XMapRaised(display, data->fswindow);
/* Make sure the fswindow is in view by warping mouse to the corner */
X11_XUngrabPointer(display, CurrentTime);
X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
/* Wait to be mapped, filter Unmap event out if it arrives. */
X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->fswindow);
X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->fswindow);
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
if ( displaydata->use_vidmode ) {
X11_XF86VidModeLockModeSwitch(display, screen, True);
}
#endif
SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
/* Center actual window within our cover-the-screen window. */
X11_XReparentWindow(display, data->xwindow, data->fswindow,
(rect.w - window->w) / 2, (rect.h - window->h) / 2);
/* Move the mouse to the upper left to make sure it's on-screen */
X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
/* Center mouse in the fullscreen window. */
rect.x += (rect.w / 2);
rect.y += (rect.h / 2);
X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
/* Wait to be mapped, filter Unmap event out if it arrives. */
X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
SDL_UpdateWindowGrab(window);
}
static void
X11_EndWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
Display *display = data->videodata->display;
const int screen = displaydata->screen;
Window root = RootWindow(display, screen);
Window fswindow = data->fswindow;
XEvent ev;
if (!data->fswindow) {
return; /* already not fullscreen, I hope. */
}
data->fswindow = None;
#if SDL_VIDEO_DRIVER_X11_VIDMODE
if ( displaydata->use_vidmode ) {
X11_XF86VidModeLockModeSwitch(display, screen, False);
}
#endif
SDL_UpdateWindowGrab(window);
X11_XReparentWindow(display, data->xwindow, root, window->x, window->y);
/* flush these events so they don't confuse normal event handling */
X11_XSync(display, False);
X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
SetWindowBordered(display, screen, data->xwindow,
(window->flags & SDL_WINDOW_BORDERLESS) == 0);
X11_XWithdrawWindow(display, fswindow, screen);
/* Wait to be unmapped. */
X11_XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);
X11_XDestroyWindow(display, fswindow);
}
void
X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
{
/* !!! FIXME: SDL_Hint? */
SDL_bool legacy = SDL_FALSE;
const char *env = SDL_getenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN");
if (env) {
legacy = SDL_atoi(env);
} else {
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
if ( displaydata->use_vidmode ) {
legacy = SDL_TRUE; /* the new stuff only works with XRandR. */
} else if ( !videodata->net_wm ) {
legacy = SDL_TRUE; /* The window manager doesn't support it */
} else {
/* !!! FIXME: look at the window manager name, and blacklist certain ones? */
/* http://stackoverflow.com/questions/758648/find-the-name-of-the-x-window-manager */
legacy = SDL_FALSE; /* try the new way. */
}
}
if (legacy) {
if (fullscreen) {
X11_BeginWindowFullscreenLegacy(_this, window, _display);
} else {
X11_EndWindowFullscreenLegacy(_this, window, _display);
}
} else {
X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen);
}
}
int
X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
Visual *visual = data->visual;
Colormap colormap = data->colormap;
XColor *colorcells;
int ncolors;
int rmask, gmask, bmask;
int rshift, gshift, bshift;
int i;
if (visual->class != DirectColor) {
return SDL_SetError("Window doesn't have DirectColor visual");
}
ncolors = visual->map_entries;
colorcells = SDL_malloc(ncolors * sizeof(XColor));
if (!colorcells) {
return SDL_OutOfMemory();
}
rshift = 0;
rmask = visual->red_mask;
while (0 == (rmask & 1)) {
rshift++;
rmask >>= 1;
}
gshift = 0;
gmask = visual->green_mask;
while (0 == (gmask & 1)) {
gshift++;
gmask >>= 1;
}
bshift = 0;
bmask = visual->blue_mask;
while (0 == (bmask & 1)) {
bshift++;
bmask >>= 1;
}
/* build the color table pixel values */
for (i = 0; i < ncolors; i++) {
Uint32 rbits = (rmask * i) / (ncolors - 1);
Uint32 gbits = (gmask * i) / (ncolors - 1);
Uint32 bbits = (bmask * i) / (ncolors - 1);
Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
colorcells[i].pixel = pix;
colorcells[i].red = ramp[(0 * 256) + i];
colorcells[i].green = ramp[(1 * 256) + i];
colorcells[i].blue = ramp[(2 * 256) + i];
colorcells[i].flags = DoRed | DoGreen | DoBlue;
}
X11_XStoreColors(display, colormap, colorcells, ncolors);
X11_XFlush(display);
SDL_free(colorcells);
return 0;
}
void
X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
SDL_bool oldstyle_fullscreen;
SDL_bool grab_keyboard;
const char *hint;
/* ICCCM2.0-compliant window managers can handle fullscreen windows
If we're using XVidMode to change resolution we need to confine
the cursor so we don't pan around the virtual desktop.
*/
oldstyle_fullscreen = X11_IsWindowLegacyFullscreen(_this, window);
if (oldstyle_fullscreen || grabbed) {
/* Try to grab the mouse */
for (;;) {
int result =
X11_XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync,
GrabModeAsync, data->xwindow, None, CurrentTime);
if (result == GrabSuccess) {
break;
}
SDL_Delay(50);
}
/* Raise the window if we grab the mouse */
X11_XRaiseWindow(display, data->xwindow);
/* Now grab the keyboard */
hint = SDL_GetHint(SDL_HINT_GRAB_KEYBOARD);
if (hint && SDL_atoi(hint)) {
grab_keyboard = SDL_TRUE;
} else {
/* We need to do this with the old style override_redirect
fullscreen window otherwise we won't get keyboard focus.
*/
grab_keyboard = oldstyle_fullscreen;
}
if (grab_keyboard) {
X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
}
} else {
X11_XUngrabPointer(display, CurrentTime);
X11_XUngrabKeyboard(display, CurrentTime);
}
X11_XSync(display, False);
}
void
X11_DestroyWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data) {
SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
Display *display = videodata->display;
int numwindows = videodata->numwindows;
SDL_WindowData **windowlist = videodata->windowlist;
int i;
if (windowlist) {
for (i = 0; i < numwindows; ++i) {
if (windowlist[i] && (windowlist[i]->window == window)) {
windowlist[i] = windowlist[numwindows - 1];
windowlist[numwindows - 1] = NULL;
videodata->numwindows--;
break;
}
}
}
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
X11_XDestroyIC(data->ic);
}
#endif
if (data->created) {
X11_XDestroyWindow(display, data->xwindow);
X11_XFlush(display);
}
SDL_free(data);
}
window->driverdata = NULL;
}
SDL_bool
X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
if (info->version.major == SDL_MAJOR_VERSION &&
info->version.minor == SDL_MINOR_VERSION) {
info->subsystem = SDL_SYSWM_X11;
info->info.x11.display = display;
info->info.x11.window = data->xwindow;
return SDL_TRUE;
} else {
SDL_SetError("Application not compiled with SDL %d.%d\n",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
return SDL_FALSE;
}
}
int
X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
{
return 0; /* just succeed, the real work is done elsewhere. */
}
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */
SDL_UpdateWindowGrab
void SDL_UpdateWindowGrab(SDL_Window *window)
Definition: SDL_video.c:2227
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:247
SDL_MINOR_VERSION
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
X11_SetWindowHitTest
int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
SDL_VideoData::_NET_WM_STATE_FULLSCREEN
Atom _NET_WM_STATE_FULLSCREEN
Definition: SDL_x11video.h:96
X11_ResizeWindowShape
int X11_ResizeWindowShape(SDL_Window *window)
SDL_VideoData::pid
pid_t pid
Definition: SDL_x11video.h:78
SDL_VideoData::_NET_WM_ALLOWED_ACTIONS
Atom _NET_WM_ALLOWED_ACTIONS
Definition: SDL_x11video.h:97
X11_SetWindowTitle
void X11_SetWindowTitle(_THIS, SDL_Window *window)
SDL_IsShapedWindow
#define SDL_IsShapedWindow
Definition: SDL_dynapi_overrides.h:377
SDL_WindowData::visual
Visual * visual
Definition: SDL_x11window.h:48
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9432
SDL_SetKeyboardFocus
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
X11_GetNetWMState
Uint32 X11_GetNetWMState(_THIS, Window xwindow)
SDL_VIDEO_OPENGL_ES
#define SDL_VIDEO_OPENGL_ES
Definition: SDL_config_android.h:133
Uint32
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:157
e
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 Uint32 * e
Definition: SDL_dynapi_procs.h:121
SDL_Window::w
int w
Definition: SDL_sysvideo.h:78
SDL_Surface::h
int h
Definition: SDL_surface.h:73
SDL_VideoData::_NET_WM_STATE_MAXIMIZED_VERT
Atom _NET_WM_STATE_MAXIMIZED_VERT
Definition: SDL_x11video.h:94
SDL_WindowData::colormap
Colormap colormap
Definition: SDL_x11window.h:49
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
SDL_x11mouse.h
SDL_MAJOR_VERSION
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
SDL_Window::x
int x
Definition: SDL_sysvideo.h:77
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1564
dpy
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display dpy)
Definition: SDL_x11sym.h:36
rect
SDL_Rect rect
Definition: testrelative.c:27
SDL_VideoData::display
struct wl_display * display
Definition: SDL_waylandvideo.h:40
window
SDL_Window * window
Definition: testautomation_render.c:26
SDL_VideoData::windowlistlength
int windowlistlength
Definition: SDL_x11video.h:83
SDL_WindowData::xwindow
Window xwindow
Definition: SDL_x11window.h:46
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:332
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
SDL_GetHint
#define SDL_GetHint
Definition: SDL_dynapi_overrides.h:197
SDL_SysWMinfo::version
SDL_version version
Definition: SDL_syswm.h:183
SDL_version::major
Uint8 major
Definition: SDL_version.h:53
SDL_VideoData::windowlist
SDL_WindowData ** windowlist
Definition: SDL_x11video.h:82
SDL_VideoDevice::profile_mask
int profile_mask
Definition: SDL_sysvideo.h:310
SDL_x11opengles.h
SDL_SysWMinfo::subsystem
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:184
X11_SetWindowFullscreen
void X11_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
X11_MinimizeWindow
void X11_MinimizeWindow(_THIS, SDL_Window *window)
SDL_WindowData::window
SDL_Window * window
Definition: SDL_cocoawindow.h:110
SDL_SYSWM_X11
Definition: SDL_syswm.h:116
X11_SetNetWMState
void X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:382
SDL_Surface::w
int w
Definition: SDL_surface.h:73
SDL_WINDOW_HIDDEN
Definition: SDL_video.h:101
SDL_Window::windowed
SDL_Rect windowed
Definition: SDL_sysvideo.h:85
SDL_VideoData::_NET_WM_ICON
Atom _NET_WM_ICON
Definition: SDL_x11video.h:101
SDL_VideoData::im
XIM im
Definition: SDL_x11video.h:79
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
SDL_VIDEO_OPENGL_ES2
#define SDL_VIDEO_OPENGL_ES2
Definition: SDL_config.h:328
SDL_DisplayData
Definition: SDL_cocoamodes.h:26
SDL_WINDOW_SHOWN
Definition: SDL_video.h:100
X11_MaximizeWindow
void X11_MaximizeWindow(_THIS, SDL_Window *window)
SDL_VideoDevice::gl_data
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:333
SDL_WindowData
Definition: SDL_androidwindow.h:34
SDL_HINT_GRAB_KEYBOARD
#define SDL_HINT_GRAB_KEYBOARD
A variable controlling whether grabbing input grabs the keyboard.
Definition: SDL_hints.h:233
red
const GLubyte GLuint red
Definition: SDL_glfuncs.h:78
X11_GetDisplayBounds
int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay *sdl_display, SDL_Rect *rect)
SDL_VideoData::_NET_WM_STATE
Atom _NET_WM_STATE
Definition: SDL_x11video.h:91
maxLength
GLsizei maxLength
Definition: SDL_opengl_glext.h:3644
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:114
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:126
SDL_VideoDevice::gl_config
struct SDL_VideoDevice::@29 gl_config
SDL_x11shape.h
SDL_iconv_utf8_locale
#define SDL_iconv_utf8_locale(S)
Definition: SDL_stdinc.h:484
SDL_VideoData::classname
char * classname
Definition: SDL_x11video.h:77
SDL_VideoData::_NET_WM_STATE_HIDDEN
Atom _NET_WM_STATE_HIDDEN
Definition: SDL_x11video.h:92
SDL_HINT_VIDEO_X11_NET_WM_PING
#define SDL_HINT_VIDEO_X11_NET_WM_PING
A variable controlling whether the X11 _NET_WM_PING protocol should be supported. ...
Definition: SDL_hints.h:200
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1564
SDL_VideoData::_NET_ACTIVE_WINDOW
Atom _NET_ACTIVE_WINDOW
Definition: SDL_x11video.h:103
SDL_VideoData::WM_DELETE_WINDOW
Atom WM_DELETE_WINDOW
Definition: SDL_x11video.h:90
SDL_calloc
void * SDL_calloc(size_t nmemb, size_t size)
X11_CreateWindow
int X11_CreateWindow(_THIS, SDL_Window *window)
SDL_SysWMinfo
Definition: SDL_syswm.h:181
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:75
X11_SetWindowGammaRamp
int X11_SetWindowGammaRamp(_THIS, SDL_Window *window, const Uint16 *ramp)
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_WindowData::videodata
struct SDL_VideoData * videodata
Definition: SDL_cocoawindow.h:116
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_free
void SDL_free(void *mem)
X11_CreateWindowFrom
int X11_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
SDL_Window::min_w
int min_w
Definition: SDL_sysvideo.h:79
SDL_static_cast
#define SDL_static_cast(type, expression)
Definition: SDL_stdinc.h:109
X11_RestoreWindow
void X11_RestoreWindow(_THIS, SDL_Window *window)
SDL_hints.h
SDL_version::minor
Uint8 minor
Definition: SDL_version.h:54
blue
GLbyte GLbyte blue
Definition: SDL_opengl_glext.h:379
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:357
SDL_Window::title
char * title
Definition: SDL_sysvideo.h:75
SDL_Window::y
int y
Definition: SDL_sysvideo.h:77
SDL_WindowData::fswindow
Window fswindow
Definition: SDL_x11window.h:47
SDL_Rect::x
int x
Definition: SDL_rect.h:66
X11_ShowWindow
void X11_ShowWindow(_THIS, SDL_Window *window)
SDL_TRUE
Definition: SDL_stdinc.h:129
X11_DestroyWindow
void X11_DestroyWindow(_THIS, SDL_Window *window)
SDL_VIDEO_OPENGL_GLX
#define SDL_VIDEO_OPENGL_GLX
Definition: SDL_config.h:332
SDL_Rect::w
int w
Definition: SDL_rect.h:67
SDL_SysWMinfo::x11
struct SDL_SysWMinfo::@18::@19 x11
SDL_atoi
#define SDL_atoi
Definition: SDL_dynapi_overrides.h:416
SDL_Delay
#define SDL_Delay
Definition: SDL_dynapi_overrides.h:490
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: SDL_opengl_glext.h:2479
SDL_VideoDisplay
Definition: SDL_sysvideo.h:120
SDL_getenv
#define SDL_getenv
Definition: SDL_dynapi_overrides.h:384
SDL_Window::h
int h
Definition: SDL_sysvideo.h:78
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_x11xinput2.h
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:167
X11_SetWindowMinimumSize
void X11_SetWindowMinimumSize(_THIS, SDL_Window *window)
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_WINDOW_INPUT_FOCUS
Definition: SDL_video.h:107
SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:103
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:72
depth
GLint GLint GLsizei GLsizei GLsizei depth
Definition: SDL_opengl.h:1565
SDL_VideoData::_NET_WM_STATE_MAXIMIZED_HORZ
Atom _NET_WM_STATE_MAXIMIZED_HORZ
Definition: SDL_x11video.h:95
SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:102
SDL_Window::min_h
int min_h
Definition: SDL_sysvideo.h:79
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:36
SDL_WindowData::ic
XIC ic
Definition: SDL_x11window.h:57
SDL_Window::max_w
int max_w
Definition: SDL_sysvideo.h:80
SDL_GetDisplayForWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1039
SDL_Rect::h
int h
Definition: SDL_rect.h:67
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:403
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:71
SDL_WINDOW_MAXIMIZED
Definition: SDL_video.h:105
SDL_VideoData::_NET_WM_STATE_FOCUSED
Atom _NET_WM_STATE_FOCUSED
Definition: SDL_x11video.h:93
X11_RaiseWindow
void X11_RaiseWindow(_THIS, SDL_Window *window)
SDL_iconv_string
#define SDL_iconv_string
Definition: SDL_dynapi_overrides.h:447
SDL_FALSE
Definition: SDL_stdinc.h:128
SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:98
SDL_VideoData::net_wm
SDL_bool net_wm
Definition: SDL_x11video.h:86
X11_SetWindowIcon
void X11_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:74
X11_GetWindowTitle
char * X11_GetWindowTitle(_THIS, Window xwindow)
SDL_x11video.h
border
GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: SDL_opengl.h:1565
SDL_VideoData
Definition: SDL_androidvideo.h:35
green
GLbyte green
Definition: SDL_opengl_glext.h:379
Uint16
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:147
SDL_Window::max_h
int max_h
Definition: SDL_sysvideo.h:80
SDL_SysWMinfo::info
union SDL_SysWMinfo::@18 info
SDL_WindowData::created
SDL_bool created
Definition: SDL_cocoawindow.h:113
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
SDL_WINDOW_OPENGL
Definition: SDL_video.h:99
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
SDL_VideoData::UTF8_STRING
Atom UTF8_STRING
Definition: SDL_x11video.h:104
SDL_Window::driverdata
void * driverdata
Definition: SDL_sysvideo.h:106
X11_SetWindowSize
void X11_SetWindowSize(_THIS, SDL_Window *window)
SDL_PixelFormat::format
Uint32 format
Definition: SDL_pixels.h:301
SDL_VideoData::_NET_WM_NAME
Atom _NET_WM_NAME
Definition: SDL_x11video.h:99
SDL_timer.h
SDL_Window::flags
Uint32 flags
Definition: SDL_sysvideo.h:81
SDL_GL_CONTEXT_PROFILE_ES
Definition: SDL_video.h:202
SDL_VideoData::_NET_WM_PING
Atom _NET_WM_PING
Definition: SDL_x11video.h:102
src
GLenum src
Definition: SDL_opengl_glext.h:1737
X11_SetWindowBordered
void X11_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
X11_HideWindow
void X11_HideWindow(_THIS, SDL_Window *window)
screen
SDL_Renderer * screen
Definition: testgamecontroller.c:64
SDL_VideoData::numwindows
int numwindows
Definition: SDL_x11video.h:81
SDL_syswm.h
X11_SetWindowGrab
void X11_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
SDL_Rect::y
int y
Definition: SDL_rect.h:66
SDL_WINDOW_INPUT_GRABBED
Definition: SDL_video.h:106
SDL_WindowData::egl_surface
EGLSurface egl_surface
Definition: SDL_androidwindow.h:36
SDL_Rect
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
X11_GetWindowWMInfo
SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
X11_SetWindowMaximumSize
void X11_SetWindowMaximumSize(_THIS, SDL_Window *window)
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:133
SDL_assert.h
X11_Xinput2SelectTouch
void X11_Xinput2SelectTouch(_THIS, SDL_Window *window)
X11_SetWindowPosition
void X11_SetWindowPosition(_THIS, SDL_Window *window)