SDL_x11events.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 <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <limits.h> /* For INT_MAX */
#include "SDL_x11video.h"
#include "SDL_x11touch.h"
#include "SDL_x11xinput2.h"
#include "../../events/SDL_events_c.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_touch_c.h"
#include "SDL_timer.h"
#include "SDL_syswm.h"
#include <stdio.h>
/*#define DEBUG_XEVENTS*/
#ifndef _NET_WM_MOVERESIZE_SIZE_TOPLEFT
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
#endif
#ifndef _NET_WM_MOVERESIZE_SIZE_TOP
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
#endif
#ifndef _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
#endif
#ifndef _NET_WM_MOVERESIZE_SIZE_RIGHT
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
#endif
#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
#endif
#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOM
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
#endif
#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
#endif
#ifndef _NET_WM_MOVERESIZE_SIZE_LEFT
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
#endif
#ifndef _NET_WM_MOVERESIZE_MOVE
#define _NET_WM_MOVERESIZE_MOVE 8
#endif
typedef struct {
unsigned char *data;
int format, count;
Atom type;
} SDL_x11Prop;
/* Reads property
Must call X11_XFree on results
*/
static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop)
{
unsigned char *ret=NULL;
Atom type;
int fmt;
unsigned long count;
unsigned long bytes_left;
int bytes_fetch = 0;
do {
if (ret != 0) X11_XFree(ret);
X11_XGetWindowProperty(disp, w, prop, 0, bytes_fetch, False, AnyPropertyType, &type, &fmt, &count, &bytes_left, &ret);
bytes_fetch += bytes_left;
} while (bytes_left != 0);
p->data=ret;
p->format=fmt;
p->count=count;
p->type=type;
}
/* Find text-uri-list in a list of targets and return it's atom
if available, else return None */
static Atom X11_PickTarget(Display *disp, Atom list[], int list_count)
{
Atom request = None;
char *name;
int i;
for (i=0; i < list_count && request == None; i++) {
name = X11_XGetAtomName(disp, list[i]);
if (strcmp("text/uri-list", name)==0) request = list[i];
X11_XFree(name);
}
return request;
}
/* Wrapper for X11_PickTarget for a maximum of three targets, a special
case in the Xdnd protocol */
static Atom X11_PickTargetFromAtoms(Display *disp, Atom a0, Atom a1, Atom a2)
{
int count=0;
Atom atom[3];
if (a0 != None) atom[count++] = a0;
if (a1 != None) atom[count++] = a1;
if (a2 != None) atom[count++] = a2;
return X11_PickTarget(disp, atom, count);
}
struct KeyRepeatCheckData
{
XEvent *event;
SDL_bool found;
};
static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
XPointer arg)
{
struct KeyRepeatCheckData *d = (struct KeyRepeatCheckData *) arg;
if (chkev->type == KeyPress &&
chkev->xkey.keycode == d->event->xkey.keycode &&
chkev->xkey.time - d->event->xkey.time < 2)
d->found = SDL_TRUE;
return False;
}
/* Check to see if this is a repeated key.
(idea shamelessly lifted from GII -- thanks guys! :)
*/
static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
{
XEvent dummyev;
struct KeyRepeatCheckData d;
d.event = event;
d.found = SDL_FALSE;
if (X11_XPending(display))
X11_XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent,
(XPointer) &d);
return d.found;
}
static SDL_bool
X11_IsWheelEvent(Display * display,XEvent * event,int * xticks,int * yticks)
{
/* according to the xlib docs, no specific mouse wheel events exist.
However, the defacto standard is that the vertical wheel is X buttons
4 (up) and 5 (down) and a horizontal wheel is 6 (left) and 7 (right). */
/* Xlib defines "Button1" through 5, so we just use literals here. */
switch (event->xbutton.button) {
case 4: *yticks = 1; return SDL_TRUE;
case 5: *yticks = -1; return SDL_TRUE;
case 6: *xticks = 1; return SDL_TRUE;
case 7: *xticks = -1; return SDL_TRUE;
default: break;
}
return SDL_FALSE;
}
/* Decodes URI escape sequences in string buf of len bytes
(excluding the terminating NULL byte) in-place. Since
URI-encoded characters take three times the space of
normal characters, this should not be an issue.
Returns the number of decoded bytes that wound up in
the buffer, excluding the terminating NULL byte.
The buffer is guaranteed to be NULL-terminated but
may contain embedded NULL bytes.
On error, -1 is returned.
*/
int X11_URIDecode(char *buf, int len) {
int ri, wi, di;
char decode = '\0';
if (buf == NULL || len < 0) {
errno = EINVAL;
return -1;
}
if (len == 0) {
len = SDL_strlen(buf);
}
for (ri = 0, wi = 0, di = 0; ri < len && wi < len; ri += 1) {
if (di == 0) {
/* start decoding */
if (buf[ri] == '%') {
decode = '\0';
di += 1;
continue;
}
/* normal write */
buf[wi] = buf[ri];
wi += 1;
continue;
} else if (di == 1 || di == 2) {
char off = '\0';
char isa = buf[ri] >= 'a' && buf[ri] <= 'f';
char isA = buf[ri] >= 'A' && buf[ri] <= 'F';
char isn = buf[ri] >= '0' && buf[ri] <= '9';
if (!(isa || isA || isn)) {
/* not a hexadecimal */
int sri;
for (sri = ri - di; sri <= ri; sri += 1) {
buf[wi] = buf[sri];
wi += 1;
}
di = 0;
continue;
}
/* itsy bitsy magicsy */
if (isn) {
off = 0 - '0';
} else if (isa) {
off = 10 - 'a';
} else if (isA) {
off = 10 - 'A';
}
decode |= (buf[ri] + off) << (2 - di) * 4;
if (di == 2) {
buf[wi] = decode;
wi += 1;
di = 0;
} else {
di += 1;
}
continue;
}
}
buf[wi] = '\0';
return wi;
}
/* Convert URI to local filename
return filename if possible, else NULL
*/
static char* X11_URIToLocal(char* uri) {
char *file = NULL;
SDL_bool local;
if (memcmp(uri,"file:/",6) == 0) uri += 6; /* local file? */
else if (strstr(uri,":/") != NULL) return file; /* wrong scheme */
local = uri[0] != '/' || (uri[0] != '\0' && uri[1] == '/');
/* got a hostname? */
if (!local && uri[0] == '/' && uri[2] != '/') {
char* hostname_end = strchr(uri+1, '/');
if (hostname_end != NULL) {
char hostname[ 257 ];
if (gethostname(hostname, 255) == 0) {
hostname[ 256 ] = '\0';
if (memcmp(uri+1, hostname, hostname_end - (uri+1)) == 0) {
uri = hostname_end + 1;
local = SDL_TRUE;
}
}
}
}
if (local) {
file = uri;
/* Convert URI escape sequences to real characters */
X11_URIDecode(file, 0);
if (uri[1] == '/') {
file++;
} else {
file--;
}
}
return file;
}
#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event)
{
/* event is a union, so cookie == &event, but this is type safe. */
XGenericEventCookie *cookie = &event.xcookie;
if (X11_XGetEventData(videodata->display, cookie)) {
X11_HandleXinput2Event(videodata, cookie);
X11_XFreeEventData(videodata->display, cookie);
}
}
#endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
static unsigned
X11_GetNumLockModifierMask(_THIS)
{
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
Display *display = viddata->display;
unsigned num_mask = 0;
int i, j;
XModifierKeymap *xmods;
unsigned n;
xmods = X11_XGetModifierMapping(display);
n = xmods->max_keypermod;
for(i = 3; i < 8; i++) {
for(j = 0; j < n; j++) {
KeyCode kc = xmods->modifiermap[i * n + j];
if (viddata->key_layout[kc] == SDL_SCANCODE_NUMLOCKCLEAR) {
num_mask = 1 << i;
break;
}
}
}
X11_XFreeModifiermap(xmods);
return num_mask;
}
static void
X11_ReconcileKeyboardState(_THIS)
{
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
Display *display = viddata->display;
char keys[32];
int keycode;
Window junk_window;
int x, y;
unsigned int mask;
X11_XQueryKeymap(display, keys);
/* Sync up the keyboard modifier state */
if (X11_XQueryPointer(display, DefaultRootWindow(display), &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
SDL_ToggleModState(KMOD_CAPS, (mask & LockMask) != 0);
SDL_ToggleModState(KMOD_NUM, (mask & X11_GetNumLockModifierMask(_this)) != 0);
}
for (keycode = 0; keycode < 256; ++keycode) {
if (keys[keycode / 8] & (1 << (keycode % 8))) {
SDL_SendKeyboardKey(SDL_PRESSED, viddata->key_layout[keycode]);
} else {
SDL_SendKeyboardKey(SDL_RELEASED, viddata->key_layout[keycode]);
}
}
}
static void
X11_DispatchFocusIn(_THIS, SDL_WindowData *data)
{
#ifdef DEBUG_XEVENTS
printf("window %p: Dispatching FocusIn\n", data);
#endif
SDL_SetKeyboardFocus(data->window);
X11_ReconcileKeyboardState(_this);
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
X11_XSetICFocus(data->ic);
}
#endif
#ifdef SDL_USE_IBUS
SDL_IBus_SetFocus(SDL_TRUE);
#endif
}
static void
X11_DispatchFocusOut(_THIS, SDL_WindowData *data)
{
#ifdef DEBUG_XEVENTS
printf("window %p: Dispatching FocusOut\n", data);
#endif
/* If another window has already processed a focus in, then don't try to
* remove focus here. Doing so will incorrectly remove focus from that
* window, and the focus lost event for this window will have already
* been dispatched anyway. */
if (data->window == SDL_GetKeyboardFocus()) {
SDL_SetKeyboardFocus(NULL);
}
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
X11_XUnsetICFocus(data->ic);
}
#endif
#ifdef SDL_USE_IBUS
SDL_IBus_SetFocus(SDL_FALSE);
#endif
}
static void
X11_DispatchMapNotify(SDL_WindowData *data)
{
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
static void
X11_DispatchUnmapNotify(SDL_WindowData *data)
{
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
}
static void
InitiateWindowMove(_THIS, const SDL_WindowData *data, const SDL_Point *point)
{
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
SDL_Window* window = data->window;
Display *display = viddata->display;
XEvent evt;
/* !!! FIXME: we need to regrab this if necessary when the drag is done. */
X11_XUngrabPointer(display, 0L);
X11_XFlush(display);
evt.xclient.type = ClientMessage;
evt.xclient.window = data->xwindow;
evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
evt.xclient.format = 32;
evt.xclient.data.l[0] = window->x + point->x;
evt.xclient.data.l[1] = window->y + point->y;
evt.xclient.data.l[2] = _NET_WM_MOVERESIZE_MOVE;
evt.xclient.data.l[3] = Button1;
evt.xclient.data.l[4] = 0;
X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
X11_XSync(display, 0);
}
static void
InitiateWindowResize(_THIS, const SDL_WindowData *data, const SDL_Point *point, int direction)
{
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
SDL_Window* window = data->window;
Display *display = viddata->display;
XEvent evt;
if (direction < _NET_WM_MOVERESIZE_SIZE_TOPLEFT || direction > _NET_WM_MOVERESIZE_SIZE_LEFT)
return;
/* !!! FIXME: we need to regrab this if necessary when the drag is done. */
X11_XUngrabPointer(display, 0L);
X11_XFlush(display);
evt.xclient.type = ClientMessage;
evt.xclient.window = data->xwindow;
evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
evt.xclient.format = 32;
evt.xclient.data.l[0] = window->x + point->x;
evt.xclient.data.l[1] = window->y + point->y;
evt.xclient.data.l[2] = direction;
evt.xclient.data.l[3] = Button1;
evt.xclient.data.l[4] = 0;
X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
X11_XSync(display, 0);
}
static SDL_bool
ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
{
SDL_Window *window = data->window;
if (window->hit_test) {
const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
static const int directions[] = {
_NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP,
_NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT,
_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT, _NET_WM_MOVERESIZE_SIZE_BOTTOM,
_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT
};
switch (rc) {
case SDL_HITTEST_DRAGGABLE:
InitiateWindowMove(_this, data, &point);
return SDL_TRUE;
case SDL_HITTEST_RESIZE_TOPLEFT:
case SDL_HITTEST_RESIZE_TOP:
case SDL_HITTEST_RESIZE_TOPRIGHT:
case SDL_HITTEST_RESIZE_RIGHT:
case SDL_HITTEST_RESIZE_BOTTOMRIGHT:
case SDL_HITTEST_RESIZE_BOTTOM:
case SDL_HITTEST_RESIZE_BOTTOMLEFT:
case SDL_HITTEST_RESIZE_LEFT:
InitiateWindowResize(_this, data, &point, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
return SDL_TRUE;
default: return SDL_FALSE;
}
}
return SDL_FALSE;
}
static void
X11_DispatchEvent(_THIS)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
Display *display = videodata->display;
SDL_WindowData *data;
XEvent xevent;
int orig_event_type;
KeyCode orig_keycode;
XClientMessageEvent m;
int i;
SDL_zero(xevent); /* valgrind fix. --ryan. */
X11_XNextEvent(display, &xevent);
/* Save the original keycode for dead keys, which are filtered out by
the XFilterEvent() call below.
*/
orig_event_type = xevent.type;
if (orig_event_type == KeyPress || orig_event_type == KeyRelease) {
orig_keycode = xevent.xkey.keycode;
} else {
orig_keycode = 0;
}
/* filter events catchs XIM events and sends them to the correct handler */
if (X11_XFilterEvent(&xevent, None) == True) {
#if 0
printf("Filtered event type = %d display = %d window = %d\n",
xevent.type, xevent.xany.display, xevent.xany.window);
#endif
if (orig_keycode) {
/* Make sure dead key press/release events are sent */
/* Actually, don't do this because it causes double-delivery
of some keys on Ubuntu 14.04 (bug 2526)
SDL_Scancode scancode = videodata->key_layout[orig_keycode];
if (orig_event_type == KeyPress) {
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
} else {
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
*/
}
return;
}
/* Send a SDL_SYSWMEVENT if the application wants them */
if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
SDL_SysWMmsg wmmsg;
SDL_VERSION(&wmmsg.version);
wmmsg.subsystem = SDL_SYSWM_X11;
wmmsg.msg.x11.event = xevent;
SDL_SendSysWMEvent(&wmmsg);
}
#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
if(xevent.type == GenericEvent) {
X11_HandleGenericEvent(videodata,xevent);
return;
}
#endif
#if 0
printf("type = %d display = %d window = %d\n",
xevent.type, xevent.xany.display, xevent.xany.window);
#endif
data = NULL;
if (videodata && videodata->windowlist) {
for (i = 0; i < videodata->numwindows; ++i) {
if ((videodata->windowlist[i] != NULL) &&
(videodata->windowlist[i]->xwindow == xevent.xany.window)) {
data = videodata->windowlist[i];
break;
}
}
}
if (!data) {
/* The window for KeymapNotify, etc events is 0 */
if (xevent.type == KeymapNotify) {
if (SDL_GetKeyboardFocus() != NULL) {
X11_ReconcileKeyboardState(_this);
}
} else if (xevent.type == MappingNotify) {
/* Has the keyboard layout changed? */
const int request = xevent.xmapping.request;
#ifdef DEBUG_XEVENTS
printf("window %p: MappingNotify!\n", data);
#endif
if ((request == MappingKeyboard) || (request == MappingModifier)) {
X11_XRefreshKeyboardMapping(&xevent.xmapping);
}
X11_UpdateKeymap(_this);
SDL_SendKeymapChangedEvent();
}
return;
}
switch (xevent.type) {
/* Gaining mouse coverage? */
case EnterNotify:{
#ifdef DEBUG_XEVENTS
printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
xevent.xcrossing.x,
xevent.xcrossing.y,
xevent.xcrossing.mode);
if (xevent.xcrossing.mode == NotifyGrab)
printf("Mode: NotifyGrab\n");
if (xevent.xcrossing.mode == NotifyUngrab)
printf("Mode: NotifyUngrab\n");
#endif
SDL_SetMouseFocus(data->window);
if (!SDL_GetMouse()->relative_mode) {
SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
}
}
break;
/* Losing mouse coverage? */
case LeaveNotify:{
#ifdef DEBUG_XEVENTS
printf("window %p: LeaveNotify! (%d,%d,%d)\n", data,
xevent.xcrossing.x,
xevent.xcrossing.y,
xevent.xcrossing.mode);
if (xevent.xcrossing.mode == NotifyGrab)
printf("Mode: NotifyGrab\n");
if (xevent.xcrossing.mode == NotifyUngrab)
printf("Mode: NotifyUngrab\n");
#endif
if (!SDL_GetMouse()->relative_mode) {
SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
}
if (xevent.xcrossing.mode != NotifyGrab &&
xevent.xcrossing.mode != NotifyUngrab &&
xevent.xcrossing.detail != NotifyInferior) {
SDL_SetMouseFocus(NULL);
}
}
break;
/* Gaining input focus? */
case FocusIn:{
if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
/* Someone is handling a global hotkey, ignore it */
#ifdef DEBUG_XEVENTS
printf("window %p: FocusIn (NotifyGrab/NotifyUngrab, ignoring)\n", data);
#endif
break;
}
if (xevent.xfocus.detail == NotifyInferior) {
#ifdef DEBUG_XEVENTS
printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data);
#endif
break;
}
#ifdef DEBUG_XEVENTS
printf("window %p: FocusIn!\n", data);
#endif
if (!videodata->last_mode_change_deadline) /* no recent mode changes */
{
data->pending_focus = PENDING_FOCUS_NONE;
data->pending_focus_time = 0;
X11_DispatchFocusIn(_this, data);
}
else
{
data->pending_focus = PENDING_FOCUS_IN;
data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
}
}
break;
/* Losing input focus? */
case FocusOut:{
if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
/* Someone is handling a global hotkey, ignore it */
#ifdef DEBUG_XEVENTS
printf("window %p: FocusOut (NotifyGrab/NotifyUngrab, ignoring)\n", data);
#endif
break;
}
if (xevent.xfocus.detail == NotifyInferior) {
/* We still have focus if a child gets focus */
#ifdef DEBUG_XEVENTS
printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data);
#endif
break;
}
#ifdef DEBUG_XEVENTS
printf("window %p: FocusOut!\n", data);
#endif
if (!videodata->last_mode_change_deadline) /* no recent mode changes */
{
data->pending_focus = PENDING_FOCUS_NONE;
data->pending_focus_time = 0;
X11_DispatchFocusOut(_this, data);
}
else
{
data->pending_focus = PENDING_FOCUS_OUT;
data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
}
}
break;
/* Key press? */
case KeyPress:{
KeyCode keycode = xevent.xkey.keycode;
KeySym keysym = NoSymbol;
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
Status status = 0;
SDL_bool handled_by_ime = SDL_FALSE;
#ifdef DEBUG_XEVENTS
printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
#endif
#if 1
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
int min_keycode, max_keycode;
X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
#else
keysym = X11_XKeycodeToKeysym(display, keycode, 0);
#endif
fprintf(stderr,
"The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
keycode, keycode - min_keycode, keysym,
X11_XKeysymToString(keysym));
}
#endif
/* */
SDL_zero(text);
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
X11_Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
&keysym, &status);
}
#else
X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
#endif
#ifdef SDL_USE_IBUS
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
handled_by_ime = SDL_IBus_ProcessKeyEvent(keysym, keycode);
}
#endif
if (!handled_by_ime) {
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
if(*text) {
SDL_SendKeyboardText(text);
}
}
}
break;
/* Key release? */
case KeyRelease:{
KeyCode keycode = xevent.xkey.keycode;
#ifdef DEBUG_XEVENTS
printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
#endif
if (X11_KeyRepeat(display, &xevent)) {
/* We're about to get a repeated key down, ignore the key up */
break;
}
SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
}
break;
/* Have we been iconified? */
case UnmapNotify:{
#ifdef DEBUG_XEVENTS
printf("window %p: UnmapNotify!\n", data);
#endif
X11_DispatchUnmapNotify(data);
}
break;
/* Have we been restored? */
case MapNotify:{
#ifdef DEBUG_XEVENTS
printf("window %p: MapNotify!\n", data);
#endif
X11_DispatchMapNotify(data);
}
break;
/* Have we been resized or moved? */
case ConfigureNotify:{
#ifdef DEBUG_XEVENTS
printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data,
xevent.xconfigure.x, xevent.xconfigure.y,
xevent.xconfigure.width, xevent.xconfigure.height);
#endif
long border_left = 0;
long border_top = 0;
if (data->xwindow) {
Atom _net_frame_extents = X11_XInternAtom(display, "_NET_FRAME_EXTENTS", 0);
Atom type;
int format;
unsigned long nitems, bytes_after;
unsigned char *property;
if (X11_XGetWindowProperty(display, data->xwindow,
_net_frame_extents, 0, 16, 0,
XA_CARDINAL, &type, &format,
&nitems, &bytes_after, &property) == Success) {
if (type != None && nitems == 4)
{
border_left = ((long*)property)[0];
border_top = ((long*)property)[2];
}
X11_XFree(property);
}
}
if (xevent.xconfigure.x != data->last_xconfigure.x ||
xevent.xconfigure.y != data->last_xconfigure.y) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
xevent.xconfigure.x - border_left,
xevent.xconfigure.y - border_top);
#ifdef SDL_USE_IBUS
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
/* Update IBus candidate list position */
SDL_IBus_UpdateTextRect(NULL);
}
#endif
}
if (xevent.xconfigure.width != data->last_xconfigure.width ||
xevent.xconfigure.height != data->last_xconfigure.height) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED,
xevent.xconfigure.width,
xevent.xconfigure.height);
}
data->last_xconfigure = xevent.xconfigure;
}
break;
/* Have we been requested to quit (or another client message?) */
case ClientMessage:{
static int xdnd_version=0;
if (xevent.xclient.message_type == videodata->XdndEnter) {
SDL_bool use_list = xevent.xclient.data.l[1] & 1;
data->xdnd_source = xevent.xclient.data.l[0];
xdnd_version = (xevent.xclient.data.l[1] >> 24);
#ifdef DEBUG_XEVENTS
printf("XID of source window : %ld\n", data->xdnd_source);
printf("Protocol version to use : %d\n", xdnd_version);
printf("More then 3 data types : %d\n", (int) use_list);
#endif
if (use_list) {
/* fetch conversion targets */
SDL_x11Prop p;
X11_ReadProperty(&p, display, data->xdnd_source, videodata->XdndTypeList);
/* pick one */
data->xdnd_req = X11_PickTarget(display, (Atom*)p.data, p.count);
X11_XFree(p.data);
} else {
/* pick from list of three */
data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]);
}
}
else if (xevent.xclient.message_type == videodata->XdndPosition) {
#ifdef DEBUG_XEVENTS
Atom act= videodata->XdndActionCopy;
if(xdnd_version >= 2) {
act = xevent.xclient.data.l[4];
}
printf("Action requested by user is : %s\n", X11_XGetAtomName(display , act));
#endif
/* reply with status */
memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = xevent.xclient.display;
m.window = xevent.xclient.data.l[0];
m.message_type = videodata->XdndStatus;
m.format=32;
m.data.l[0] = data->xwindow;
m.data.l[1] = (data->xdnd_req != None);
m.data.l[2] = 0; /* specify an empty rectangle */
m.data.l[3] = 0;
m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */
X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
X11_XFlush(display);
}
else if(xevent.xclient.message_type == videodata->XdndDrop) {
if (data->xdnd_req == None) {
/* say again - not interested! */
memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = xevent.xclient.display;
m.window = xevent.xclient.data.l[0];
m.message_type = videodata->XdndFinished;
m.format=32;
m.data.l[0] = data->xwindow;
m.data.l[1] = 0;
m.data.l[2] = None; /* fail! */
X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
} else {
/* convert */
if(xdnd_version >= 1) {
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
} else {
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
}
}
}
else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
(xevent.xclient.format == 32) &&
(xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) {
Window root = DefaultRootWindow(display);
#ifdef DEBUG_XEVENTS
printf("window %p: _NET_WM_PING\n", data);
#endif
xevent.xclient.window = root;
X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
break;
}
else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
(xevent.xclient.format == 32) &&
(xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
#ifdef DEBUG_XEVENTS
printf("window %p: WM_DELETE_WINDOW\n", data);
#endif
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
break;
}
}
break;
/* Do we need to refresh ourselves? */
case Expose:{
#ifdef DEBUG_XEVENTS
printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
#endif
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
}
break;
case MotionNotify:{
SDL_Mouse *mouse = SDL_GetMouse();
if(!mouse->relative_mode || mouse->relative_mode_warp) {
#ifdef DEBUG_MOTION
printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
#endif
SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
}
}
break;
case ButtonPress:{
int xticks = 0, yticks = 0;
if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
SDL_SendMouseWheel(data->window, 0, xticks, yticks, SDL_MOUSEWHEEL_NORMAL);
} else {
int button = xevent.xbutton.button;
if(button == Button1) {
if (ProcessHitTest(_this, data, &xevent)) {
break; /* don't pass this event on to app. */
}
}
else if(button > 7) {
/* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
=> subtract (8-SDL_BUTTON_X1) to get value SDL expects */
button -= (8-SDL_BUTTON_X1);
}
SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
}
}
break;
case ButtonRelease:{
int button = xevent.xbutton.button;
/* The X server sends a Release event for each Press for wheels. Ignore them. */
int xticks = 0, yticks = 0;
if (!X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
if (button > 7) {
/* see explanation at case ButtonPress */
button -= (8-SDL_BUTTON_X1);
}
SDL_SendMouseButton(data->window, 0, SDL_RELEASED, button);
}
}
break;
case PropertyNotify:{
#ifdef DEBUG_XEVENTS
unsigned char *propdata;
int status, real_format;
Atom real_type;
unsigned long items_read, items_left;
char *name = X11_XGetAtomName(display, xevent.xproperty.atom);
if (name) {
printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
X11_XFree(name);
}
status = X11_XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
if (status == Success && items_read > 0) {
if (real_type == XA_INTEGER) {
int *values = (int *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
printf(" %d", values[i]);
}
printf(" }\n");
} else if (real_type == XA_CARDINAL) {
if (real_format == 32) {
Uint32 *values = (Uint32 *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
printf(" %d", values[i]);
}
printf(" }\n");
} else if (real_format == 16) {
Uint16 *values = (Uint16 *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
printf(" %d", values[i]);
}
printf(" }\n");
} else if (real_format == 8) {
Uint8 *values = (Uint8 *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
printf(" %d", values[i]);
}
printf(" }\n");
}
} else if (real_type == XA_STRING ||
real_type == videodata->UTF8_STRING) {
printf("{ \"%s\" }\n", propdata);
} else if (real_type == XA_ATOM) {
Atom *atoms = (Atom *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
char *atomname = X11_XGetAtomName(display, atoms[i]);
if (atomname) {
printf(" %s", atomname);
X11_XFree(atomname);
}
}
printf(" }\n");
} else {
char *atomname = X11_XGetAtomName(display, real_type);
printf("Unknown type: %ld (%s)\n", real_type, atomname ? atomname : "UNKNOWN");
if (atomname) {
X11_XFree(atomname);
}
}
}
if (status == Success) {
X11_XFree(propdata);
}
#endif /* DEBUG_XEVENTS */
if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
/* Get the new state from the window manager.
Compositing window managers can alter visibility of windows
without ever mapping / unmapping them, so we handle that here,
because they use the NETWM protocol to notify us of changes.
*/
const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
const Uint32 changed = flags ^ data->window->flags;
if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) {
if (flags & SDL_WINDOW_HIDDEN) {
X11_DispatchUnmapNotify(data);
} else {
X11_DispatchMapNotify(data);
}
}
if (changed & SDL_WINDOW_MAXIMIZED) {
if (flags & SDL_WINDOW_MAXIMIZED) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
} else {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
}
} else if (xevent.xproperty.atom == videodata->XKLAVIER_STATE) {
/* Hack for Ubuntu 12.04 (etc) that doesn't send MappingNotify
events when the keyboard layout changes (for example,
changing from English to French on the menubar's keyboard
icon). Since it changes the XKLAVIER_STATE property, we
notice and reinit our keymap here. This might not be the
right approach, but it seems to work. */
X11_UpdateKeymap(_this);
SDL_SendKeymapChangedEvent();
}
}
break;
/* Copy the selection from our own CUTBUFFER to the requested property */
case SelectionRequest: {
XSelectionRequestEvent *req;
XEvent sevent;
int seln_format;
unsigned long nbytes;
unsigned long overflow;
unsigned char *seln_data;
req = &xevent.xselectionrequest;
#ifdef DEBUG_XEVENTS
printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data,
req->requestor, req->target);
#endif
SDL_zero(sevent);
sevent.xany.type = SelectionNotify;
sevent.xselection.selection = req->selection;
sevent.xselection.target = None;
sevent.xselection.property = None;
sevent.xselection.requestor = req->requestor;
sevent.xselection.time = req->time;
if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
X11_GetSDLCutBufferClipboardType(display), 0, INT_MAX/4, False, req->target,
&sevent.xselection.target, &seln_format, &nbytes,
&overflow, &seln_data) == Success) {
Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
if (sevent.xselection.target == req->target) {
X11_XChangeProperty(display, req->requestor, req->property,
sevent.xselection.target, seln_format, PropModeReplace,
seln_data, nbytes);
sevent.xselection.property = req->property;
} else if (XA_TARGETS == req->target) {
Atom SupportedFormats[] = { XA_TARGETS, sevent.xselection.target };
X11_XChangeProperty(display, req->requestor, req->property,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)SupportedFormats,
SDL_arraysize(SupportedFormats));
sevent.xselection.property = req->property;
sevent.xselection.target = XA_TARGETS;
}
X11_XFree(seln_data);
}
X11_XSendEvent(display, req->requestor, False, 0, &sevent);
X11_XSync(display, False);
}
break;
case SelectionNotify: {
#ifdef DEBUG_XEVENTS
printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
xevent.xselection.requestor, xevent.xselection.target);
#endif
Atom target = xevent.xselection.target;
if (target == data->xdnd_req) {
/* read data */
SDL_x11Prop p;
X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
if (p.format == 8) {
SDL_bool expect_lf = SDL_FALSE;
char *start = NULL;
char *scan = (char*)p.data;
char *fn;
char *uri;
int length = 0;
while (p.count--) {
if (!expect_lf) {
if (*scan == 0x0D) {
expect_lf = SDL_TRUE;
}
if (start == NULL) {
start = scan;
length = 0;
}
length++;
} else {
if (*scan == 0x0A && length > 0) {
uri = SDL_malloc(length--);
SDL_memcpy(uri, start, length);
uri[length] = '\0';
fn = X11_URIToLocal(uri);
if (fn) {
SDL_SendDropFile(fn);
}
SDL_free(uri);
}
expect_lf = SDL_FALSE;
start = NULL;
}
scan++;
}
}
X11_XFree(p.data);
/* send reply */
SDL_memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = display;
m.window = data->xdnd_source;
m.message_type = videodata->XdndFinished;
m.format = 32;
m.data.l[0] = data->xwindow;
m.data.l[1] = 1;
m.data.l[2] = videodata->XdndActionCopy;
X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent*)&m);
X11_XSync(display, False);
} else {
videodata->selection_waiting = SDL_FALSE;
}
}
break;
case SelectionClear: {
Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
if (xevent.xselectionclear.selection == XA_PRIMARY ||
(XA_CLIPBOARD != None && xevent.xselectionclear.selection == XA_CLIPBOARD)) {
SDL_SendClipboardUpdate();
}
}
break;
default:{
#ifdef DEBUG_XEVENTS
printf("window %p: Unhandled event %d\n", data, xevent.type);
#endif
}
break;
}
}
static void
X11_HandleFocusChanges(_THIS)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
int i;
if (videodata && videodata->windowlist) {
for (i = 0; i < videodata->numwindows; ++i) {
SDL_WindowData *data = videodata->windowlist[i];
if (data && data->pending_focus != PENDING_FOCUS_NONE) {
Uint32 now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, data->pending_focus_time)) {
if (data->pending_focus == PENDING_FOCUS_IN) {
X11_DispatchFocusIn(_this, data);
} else {
X11_DispatchFocusOut(_this, data);
}
data->pending_focus = PENDING_FOCUS_NONE;
}
}
}
}
}
/* Ack! X11_XPending() actually performs a blocking read if no events available */
static int
X11_Pending(Display * display)
{
/* Flush the display connection and look to see if events are queued */
X11_XFlush(display);
if (X11_XEventsQueued(display, QueuedAlready)) {
return (1);
}
/* More drastic measures are required -- see if X is ready to talk */
{
static struct timeval zero_time; /* static == 0 */
int x11_fd;
fd_set fdset;
x11_fd = ConnectionNumber(display);
FD_ZERO(&fdset);
FD_SET(x11_fd, &fdset);
if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
return (X11_XPending(display));
}
}
/* Oh well, nothing is ready .. */
return (0);
}
void
X11_PumpEvents(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
if (data->last_mode_change_deadline) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) {
data->last_mode_change_deadline = 0; /* assume we're done. */
}
}
/* Update activity every 30 seconds to prevent screensaver */
if (_this->suspend_screensaver) {
const Uint32 now = SDL_GetTicks();
if (!data->screensaver_activity ||
SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
X11_XResetScreenSaver(data->display);
#if SDL_USE_LIBDBUS
SDL_DBus_ScreensaverTickle();
#endif
data->screensaver_activity = now;
}
}
/* Keep processing pending events */
while (X11_Pending(data->display)) {
X11_DispatchEvent(_this);
}
#ifdef SDL_USE_IBUS
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
SDL_IBus_PumpEvents();
}
#endif
/* FIXME: Only need to do this when there are pending focus changes */
X11_HandleFocusChanges(_this);
}
void
X11_SuspendScreenSaver(_THIS)
{
#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
int dummy;
int major_version, minor_version;
#endif /* SDL_VIDEO_DRIVER_X11_XSCRNSAVER */
#if SDL_USE_LIBDBUS
if (SDL_DBus_ScreensaverInhibit(_this->suspend_screensaver)) {
return;
}
if (_this->suspend_screensaver) {
SDL_DBus_ScreensaverTickle();
}
#endif
#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
if (SDL_X11_HAVE_XSS) {
/* X11_XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
if (!X11_XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
!X11_XScreenSaverQueryVersion(data->display,
&major_version, &minor_version) ||
major_version < 1 || (major_version == 1 && minor_version < 1)) {
return;
}
X11_XScreenSaverSuspend(data->display, _this->suspend_screensaver);
X11_XResetScreenSaver(data->display);
}
#endif
}
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */
X11_PumpEvents
void X11_PumpEvents(_THIS)
SDL_SysWMmsg::version
SDL_version version
Definition: SDL_syswm.h:131
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1565
SDL_HITTEST_RESIZE_TOPRIGHT
Definition: SDL_video.h:858
SDL_VideoData::XdndEnter
Atom XdndEnter
Definition: SDL_x11video.h:106
SDL_GetMouse
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:66
button
SDL_Texture * button
Definition: testgamecontroller.c:67
SDL_SetKeyboardFocus
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
X11_GetNetWMState
Uint32 X11_GetNetWMState(_THIS, Window xwindow)
n
GLdouble n
Definition: SDL_opengl_glext.h:1952
Uint32
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:157
SDL_HITTEST_RESIZE_LEFT
Definition: SDL_video.h:863
SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:149
SDL_Window::hit_test_data
void * hit_test_data
Definition: SDL_sysvideo.h:102
SDL_HITTEST_RESIZE_BOTTOMRIGHT
Definition: SDL_video.h:860
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
SDL_Mouse::relative_mode_warp
SDL_bool relative_mode_warp
Definition: SDL_mouse_c.h:85
SDL_Window::x
int x
Definition: SDL_sysvideo.h:77
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1564
m
const GLfloat * m
Definition: SDL_opengl_glext.h:6092
SDL_VideoData::display
struct wl_display * display
Definition: SDL_waylandvideo.h:40
window
SDL_Window * window
Definition: testautomation_render.c:26
SDL_SYSWMEVENT
Definition: SDL_events.h:90
SDL_WindowData::xwindow
Window xwindow
Definition: SDL_x11window.h:46
SDL_MOUSEWHEEL_NORMAL
Definition: SDL_mouse.h:68
p
GLfloat GLfloat p
Definition: SDL_opengl_glext.h:11090
SDL_Point
The structure that defines a point.
Definition: SDL_rect.h:48
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:332
SDL_HITTEST_RESIZE_TOP
Definition: SDL_video.h:857
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
SDL_HITTEST_RESIZE_BOTTOM
Definition: SDL_video.h:861
SDL_VideoData::WM_PROTOCOLS
Atom WM_PROTOCOLS
Definition: SDL_x11video.h:89
SDL_VideoData::windowlist
SDL_WindowData ** windowlist
Definition: SDL_x11video.h:82
memset
#define memset
Definition: SDL_malloc.c:639
SDL_ENABLE
#define SDL_ENABLE
Definition: SDL_events.h:718
SDL_WINDOWEVENT_MAXIMIZED
Definition: SDL_video.h:150
start
GLuint start
Definition: SDL_opengl.h:1564
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_SendWindowEvent
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
Definition: SDL_windowevents.c:74
SDL_WindowData::window
SDL_Window * window
Definition: SDL_cocoawindow.h:110
SDL_BUTTON_X1
#define SDL_BUTTON_X1
Definition: SDL_mouse.h:283
SDL_SYSWM_X11
Definition: SDL_syswm.h:116
SDL_SetMouseFocus
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:103
SDL_GetKeyboardFocus
#define SDL_GetKeyboardFocus
Definition: SDL_dynapi_overrides.h:222
SDL_HITTEST_RESIZE_RIGHT
Definition: SDL_video.h:859
SDL_WINDOW_HIDDEN
Definition: SDL_video.h:101
SDL_SysWMmsg::msg
union SDL_SysWMmsg::@16 msg
SDL_VideoData::XdndPosition
Atom XdndPosition
Definition: SDL_x11video.h:107
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
SDL_VideoData::selection_waiting
SDL_bool selection_waiting
Definition: SDL_x11video.h:117
SDL_SendSysWMEvent
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:636
SDL_WINDOWEVENT_HIDDEN
Definition: SDL_video.h:140
SDL_SendKeyboardKey
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:661
PENDING_FOCUS_OUT
Definition: SDL_x11window.h:40
SDL_WindowData
Definition: SDL_androidwindow.h:34
SDL_VideoData::_NET_WM_STATE
Atom _NET_WM_STATE
Definition: SDL_x11video.h:91
SDL_VERSION
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:114
SDL_HitTestResult
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:852
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:126
SDL_Point::x
int x
Definition: SDL_rect.h:50
SDL_x11touch.h
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1564
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:393
SDL_VideoData::screensaver_activity
Uint32 screensaver_activity
Definition: SDL_cocoavideo.h:54
SDL_WindowData::pending_focus_time
Uint32 pending_focus_time
Definition: SDL_x11window.h:60
SDL_VideoData::WM_DELETE_WINDOW
Atom WM_DELETE_WINDOW
Definition: SDL_x11video.h:90
SDL_VideoData::XdndActionCopy
Atom XdndActionCopy
Definition: SDL_x11video.h:110
SDL_VideoData::PRIMARY
Atom PRIMARY
Definition: SDL_x11video.h:105
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:731
X11_SuspendScreenSaver
void X11_SuspendScreenSaver(_THIS)
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
SDL_SendMouseMotion
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:188
SDL_GetTicks
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_Point::y
int y
Definition: SDL_rect.h:51
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
SDL_WINDOWEVENT_RESTORED
Definition: SDL_video.h:151
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_WindowData::videodata
struct SDL_VideoData * videodata
Definition: SDL_cocoawindow.h:116
SDL_SendClipboardUpdate
int SDL_SendClipboardUpdate(void)
Definition: SDL_clipboardevents.c:31
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
SDL_SendKeyboardText
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:774
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_free
void SDL_free(void *mem)
KMOD_CAPS
Definition: SDL_keycode.h:329
target
GLenum target
Definition: SDL_opengl_glext.h:1551
SDL_VideoData::XKLAVIER_STATE
Atom XKLAVIER_STATE
Definition: SDL_x11video.h:114
KMOD_NUM
Definition: SDL_keycode.h:328
SDL_Mouse::relative_mode
SDL_bool relative_mode
Definition: SDL_mouse_c.h:84
SDL_SysWMmsg
Definition: SDL_syswm.h:129
SDL_WindowData::xdnd_req
Atom xdnd_req
Definition: SDL_x11window.h:63
SDL_VideoData::key_layout
void * key_layout
Definition: SDL_cocoavideo.h:51
values
GLenum GLsizei GLsizei GLint * values
Definition: SDL_opengl_glext.h:1486
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:357
PENDING_FOCUS_NONE
Definition: SDL_x11window.h:38
SDL_Window::y
int y
Definition: SDL_sysvideo.h:77
SDL_HITTEST_DRAGGABLE
Definition: SDL_video.h:855
X11_UpdateKeymap
void X11_UpdateKeymap(_THIS)
SDL_TRUE
Definition: SDL_stdinc.h:129
buf
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: SDL_opengl_glext.h:2480
mask
GLenum GLint GLuint mask
Definition: SDL_opengl_glext.h:657
SDL_WINDOWEVENT_CLOSE
Definition: SDL_video.h:157
SDL_WindowData::xdnd_source
Window xdnd_source
Definition: SDL_x11window.h:64
SDL_ToggleModState
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
Definition: SDL_keyboard.c:850
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_SysWMmsg::subsystem
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:132
NULL
#define NULL
Definition: begin_code.h:143
SDL_HITTEST_RESIZE_BOTTOMLEFT
Definition: SDL_video.h:862
SDL_Window::hit_test
SDL_HitTest hit_test
Definition: SDL_sysvideo.h:101
SDL_SCANCODE_UNKNOWN
Definition: SDL_scancode.h:45
X11_GetSDLCutBufferClipboardType
Atom X11_GetSDLCutBufferClipboardType(Display *display)
text
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:34
SDL_SysWMmsg::x11
struct SDL_SysWMmsg::@16::@17 x11
SDL_SendKeymapChangedEvent
int SDL_SendKeymapChangedEvent(void)
Definition: SDL_events.c:653
SDL_SCANCODE_NUMLOCKCLEAR
Definition: SDL_scancode.h:181
SDL_WindowData::ic
XIC ic
Definition: SDL_x11window.h:57
SDL_VideoData::XdndTypeList
Atom XdndTypeList
Definition: SDL_x11video.h:109
SDL_WINDOWEVENT_SHOWN
Definition: SDL_video.h:139
SDL_TEXTINPUT
Definition: SDL_events.h:96
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:399
SDL_SendDropFile
int SDL_SendDropFile(const char *file)
Definition: SDL_dropevents.c:31
PENDING_FOCUS_TIME
#define PENDING_FOCUS_TIME
Definition: SDL_x11window.h:30
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:71
SDL_WINDOW_MAXIMIZED
Definition: SDL_video.h:105
SDL_VideoData::XdndStatus
Atom XdndStatus
Definition: SDL_x11video.h:108
SDL_VideoData::XdndFinished
Atom XdndFinished
Definition: SDL_x11video.h:112
SDL_FALSE
Definition: SDL_stdinc.h:128
SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:98
SDL_WINDOWEVENT_EXPOSED
Definition: SDL_video.h:141
SDL_VideoData::XdndDrop
Atom XdndDrop
Definition: SDL_x11video.h:111
SDL_x11video.h
SDL_VideoData
Definition: SDL_androidvideo.h:35
Uint16
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:147
SDL_WindowData::last_xconfigure
XConfigureEvent last_xconfigure
Definition: SDL_x11window.h:61
X11_HandleXinput2Event
int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie)
SDL_VideoDevice::suspend_screensaver
SDL_bool suspend_screensaver
Definition: SDL_sysvideo.h:278
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
SDL_SendMouseWheel
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:406
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
SDL_WINDOWEVENT_RESIZED
Definition: SDL_video.h:145
SDL_Mouse
Definition: SDL_mouse_c.h:43
SDL_TEXTINPUTEVENT_TEXT_SIZE
#define SDL_TEXTINPUTEVENT_TEXT_SIZE
Definition: SDL_events.h:214
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
SDL_VideoData::XdndSelection
Atom XdndSelection
Definition: SDL_x11video.h:113
PENDING_FOCUS_IN
Definition: SDL_x11window.h:39
SDL_VideoData::UTF8_STRING
Atom UTF8_STRING
Definition: SDL_x11video.h:104
SDL_VideoData::last_mode_change_deadline
Uint32 last_mode_change_deadline
Definition: SDL_x11video.h:119
SDL_PRESSED
#define SDL_PRESSED
Definition: SDL_events.h:50
length
GLuint GLsizei GLsizei * length
Definition: SDL_opengl_glext.h:669
SDL_timer.h
SDL_HITTEST_RESIZE_TOPLEFT
Definition: SDL_video.h:856
SDL_Window::flags
Uint32 flags
Definition: SDL_sysvideo.h:81
SDL_TICKS_PASSED
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_VideoData::_NET_WM_PING
Atom _NET_WM_PING
Definition: SDL_x11video.h:102
SDL_WINDOWEVENT_MOVED
Definition: SDL_video.h:143
SDL_WindowData::pending_focus
PendingFocusEnum pending_focus
Definition: SDL_x11window.h:59
SDL_VideoData::numwindows
int numwindows
Definition: SDL_x11video.h:81
SDL_syswm.h
XGenericEventCookie
struct XGenericEventCookie XGenericEventCookie
Definition: SDL_x11xinput2.h:30
SDL_SendMouseButton
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:326
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:392
j
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 int in j)
Definition: SDL_x11sym.h:42