21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_X11
25 #include <sys/types.h>
34 #include "../../core/unix/SDL_poll.h"
35 #include "../../events/SDL_events_c.h"
36 #include "../../events/SDL_mouse_c.h"
37 #include "../../events/SDL_touch_c.h"
48 #ifndef _NET_WM_MOVERESIZE_SIZE_TOPLEFT
49 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
52 #ifndef _NET_WM_MOVERESIZE_SIZE_TOP
53 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
56 #ifndef _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
57 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
60 #ifndef _NET_WM_MOVERESIZE_SIZE_RIGHT
61 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
64 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
65 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
68 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOM
69 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
72 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
73 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
76 #ifndef _NET_WM_MOVERESIZE_SIZE_LEFT
77 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
80 #ifndef _NET_WM_MOVERESIZE_MOVE
81 #define _NET_WM_MOVERESIZE_MOVE 8
93 static void X11_ReadProperty(SDL_x11Prop *
p, Display *disp, Window
w, Atom prop)
95 unsigned char *ret=
NULL;
99 unsigned long bytes_left;
103 if (ret != 0) X11_XFree(ret);
104 X11_XGetWindowProperty(disp,
w, prop, 0, bytes_fetch, False, AnyPropertyType, &
type, &fmt, &
count, &bytes_left, &ret);
105 bytes_fetch += bytes_left;
106 }
while (bytes_left != 0);
116 static Atom X11_PickTarget(Display *disp, Atom list[],
int list_count)
121 for (
i=0;
i < list_count && request == None;
i++) {
122 name = X11_XGetAtomName(disp, list[
i]);
133 static Atom X11_PickTargetFromAtoms(Display *disp, Atom a0, Atom a1, Atom a2)
137 if (a0 != None) atom[
count++] = a0;
138 if (a1 != None) atom[
count++] = a1;
139 if (a2 != None) atom[
count++] = a2;
140 return X11_PickTarget(disp, atom,
count);
143 struct KeyRepeatCheckData
149 static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
152 struct KeyRepeatCheckData *
d = (
struct KeyRepeatCheckData *) arg;
153 if (chkev->type == KeyPress &&
154 chkev->xkey.keycode ==
d->event->xkey.keycode &&
155 chkev->xkey.time -
d->event->xkey.time < 2)
163 static SDL_bool X11_KeyRepeat(Display *display, XEvent *
event)
166 struct KeyRepeatCheckData
d;
169 if (X11_XPending(display))
170 X11_XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent,
176 X11_IsWheelEvent(Display * display,XEvent *
event,
int * xticks,
int * yticks)
183 switch (
event->xbutton.button) {
184 case 4: *yticks = 1;
return SDL_TRUE;
185 case 5: *yticks = -1;
return SDL_TRUE;
186 case 6: *xticks = 1;
return SDL_TRUE;
187 case 7: *xticks = -1;
return SDL_TRUE;
206 static int X11_URIDecode(
char *
buf,
int len) {
216 for (ri = 0, wi = 0, di = 0; ri <
len && wi <
len; ri += 1) {
219 if (
buf[ri] ==
'%') {
228 }
else if (di == 1 || di == 2) {
230 char isa =
buf[ri] >=
'a' &&
buf[ri] <=
'f';
231 char isA =
buf[ri] >=
'A' &&
buf[ri] <=
'F';
232 char isn =
buf[ri] >=
'0' &&
buf[ri] <=
'9';
233 if (!(isa || isA || isn)) {
236 for (sri = ri - di; sri <= ri; sri += 1) {
251 decode |= (
buf[ri] + off) << (2 - di) * 4;
269 static char* X11_URIToLocal(
char* uri) {
273 if (memcmp(uri,
"file:/",6) == 0) uri += 6;
274 else if (strstr(uri,
":/") !=
NULL)
return file;
276 local = uri[0] !=
'/' || (uri[0] !=
'\0' && uri[1] ==
'/');
279 if (!local && uri[0] ==
'/' && uri[2] !=
'/') {
280 char* hostname_end = strchr(uri+1,
'/');
281 if (hostname_end !=
NULL) {
282 char hostname[ 257 ];
283 if (gethostname(hostname, 255) == 0) {
284 hostname[ 256 ] =
'\0';
285 if (memcmp(uri+1, hostname, hostname_end - (uri+1)) == 0) {
286 uri = hostname_end + 1;
295 X11_URIDecode(file, 0);
305 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
306 static void X11_HandleGenericEvent(
SDL_VideoData *videodata, XEvent *xev)
310 if (X11_XGetEventData(videodata->
display, cookie)) {
322 wmmsg.
msg.
x11.event = *xev;
326 X11_XFreeEventData(videodata->
display, cookie);
332 X11_GetNumLockModifierMask(
_THIS)
335 Display *display = viddata->
display;
336 unsigned num_mask = 0;
338 XModifierKeymap *xmods;
341 xmods = X11_XGetModifierMapping(display);
342 n = xmods->max_keypermod;
343 for(
i = 3;
i < 8;
i++) {
344 for(
j = 0;
j <
n;
j++) {
345 KeyCode kc = xmods->modifiermap[
i *
n +
j];
352 X11_XFreeModifiermap(xmods);
358 X11_ReconcileKeyboardState(
_THIS)
361 Display *display = viddata->
display;
367 const Uint8 *keyboardState;
369 X11_XQueryKeymap(display, keys);
372 if (X11_XQueryPointer(display, DefaultRootWindow(display), &junk_window, &junk_window, &
x, &
y, &
x, &
y, &
mask)) {
378 for (keycode = 0; keycode < 256; ++keycode) {
380 SDL_bool x11KeyPressed = (keys[keycode / 8] & (1 << (keycode % 8))) != 0;
383 if (x11KeyPressed && !sdlKeyPressed) {
385 }
else if (!x11KeyPressed && sdlKeyPressed) {
396 printf(
"window %p: Dispatching FocusIn\n",
data);
399 X11_ReconcileKeyboardState(
_this);
400 #ifdef X_HAVE_UTF8_STRING
402 X11_XSetICFocus(
data->ic);
414 printf(
"window %p: Dispatching FocusOut\n",
data);
423 #ifdef X_HAVE_UTF8_STRING
425 X11_XUnsetICFocus(
data->ic);
452 Display *display = viddata->
display;
456 X11_XUngrabPointer(display, 0L);
459 evt.xclient.type = ClientMessage;
460 evt.xclient.window =
data->xwindow;
461 evt.xclient.message_type = X11_XInternAtom(display,
"_NET_WM_MOVERESIZE", True);
462 evt.xclient.format = 32;
463 evt.xclient.data.l[0] =
window->x + point->
x;
464 evt.xclient.data.l[1] =
window->y + point->
y;
465 evt.xclient.data.l[2] = _NET_WM_MOVERESIZE_MOVE;
466 evt.xclient.data.l[3] = Button1;
467 evt.xclient.data.l[4] = 0;
468 X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
470 X11_XSync(display, 0);
478 Display *display = viddata->
display;
481 if (direction < _NET_WM_MOVERESIZE_SIZE_TOPLEFT || direction > _NET_WM_MOVERESIZE_SIZE_LEFT)
485 X11_XUngrabPointer(display, 0L);
488 evt.xclient.type = ClientMessage;
489 evt.xclient.window =
data->xwindow;
490 evt.xclient.message_type = X11_XInternAtom(display,
"_NET_WM_MOVERESIZE", True);
491 evt.xclient.format = 32;
492 evt.xclient.data.l[0] =
window->x + point->
x;
493 evt.xclient.data.l[1] =
window->y + point->
y;
494 evt.xclient.data.l[2] = direction;
495 evt.xclient.data.l[3] = Button1;
496 evt.xclient.data.l[4] = 0;
497 X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
499 X11_XSync(display, 0);
508 const SDL_Point point = { xev->xbutton.
x, xev->xbutton.y };
510 static const int directions[] = {
511 _NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP,
512 _NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT,
513 _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT, _NET_WM_MOVERESIZE_SIZE_BOTTOM,
514 _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT
543 if (latest && (latest !=
data->user_time)) {
545 Display *display = videodata->
display;
547 XA_CARDINAL, 32, PropModeReplace,
548 (
const unsigned char *) &latest, 1);
550 printf(
"window %p: updating _NET_WM_USER_TIME to %lu\n",
data, latest);
552 data->user_time = latest;
557 X11_HandleClipboardEvent(
_THIS,
const XEvent *xevent)
560 Display *display = videodata->
display;
565 switch (xevent->type) {
567 case SelectionRequest: {
568 const XSelectionRequestEvent *req = &xevent->xselectionrequest;
571 unsigned long nbytes;
572 unsigned long overflow;
573 unsigned char *seln_data;
576 printf(
"window CLIPBOARD: SelectionRequest (requestor = %ld, target = %ld)\n",
577 req->requestor, req->target);
581 sevent.xany.type = SelectionNotify;
582 sevent.xselection.selection = req->selection;
583 sevent.xselection.target = None;
584 sevent.xselection.property = None;
585 sevent.xselection.requestor = req->requestor;
586 sevent.xselection.time = req->time;
591 if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
593 &sevent.xselection.target, &seln_format, &nbytes,
594 &overflow, &seln_data) == Success) {
596 Atom XA_TARGETS = X11_XInternAtom(display,
"TARGETS", 0);
597 if (sevent.xselection.target == req->target) {
598 X11_XChangeProperty(display, req->requestor, req->property,
599 sevent.xselection.target, seln_format, PropModeReplace,
601 sevent.xselection.property = req->property;
602 }
else if (XA_TARGETS == req->target) {
603 Atom SupportedFormats[] = { XA_TARGETS, sevent.xselection.target };
604 X11_XChangeProperty(display, req->requestor, req->property,
605 XA_ATOM, 32, PropModeReplace,
606 (
unsigned char*)SupportedFormats,
608 sevent.xselection.property = req->property;
609 sevent.xselection.target = XA_TARGETS;
611 X11_XFree(seln_data);
613 X11_XSendEvent(display, req->requestor, False, 0, &sevent);
614 X11_XSync(display, False);
618 case SelectionNotify: {
620 printf(
"window CLIPBOARD: SelectionNotify (requestor = %ld, target = %ld)\n",
621 xevent->xselection.requestor, xevent->xselection.target);
627 case SelectionClear: {
629 Atom XA_CLIPBOARD = X11_XInternAtom(display,
"CLIPBOARD", 0);
632 printf(
"window CLIPBOARD: SelectionClear (requestor = %ld, target = %ld)\n",
633 xevent->xselection.requestor, xevent->xselection.target);
636 if (xevent->xselectionclear.selection == XA_PRIMARY ||
637 (XA_CLIPBOARD != None && xevent->xselectionclear.selection == XA_CLIPBOARD)) {
647 X11_DispatchEvent(
_THIS)
654 KeyCode orig_keycode;
655 XClientMessageEvent
m;
664 X11_XNextEvent(display, &xevent);
669 orig_event_type = xevent.type;
670 if (orig_event_type == KeyPress || orig_event_type == KeyRelease) {
671 orig_keycode = xevent.xkey.keycode;
677 if (X11_XFilterEvent(&xevent, None) == True) {
679 printf(
"Filtered event type = %d display = %d window = %d\n",
680 xevent.type, xevent.xany.display, xevent.xany.window);
686 #if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX_FRONTEND_H)
691 if (orig_event_type == KeyPress) {
701 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
702 if(xevent.type == GenericEvent) {
703 X11_HandleGenericEvent(videodata, &xevent);
714 wmmsg.
msg.
x11.event = xevent;
719 printf(
"type = %d display = %d window = %d\n",
720 xevent.type, xevent.xany.display, xevent.xany.window);
725 X11_HandleClipboardEvent(
_this, &xevent);
741 if (xevent.type == KeymapNotify) {
743 X11_ReconcileKeyboardState(
_this);
745 }
else if (xevent.type == MappingNotify) {
747 const int request = xevent.xmapping.request;
750 printf(
"window %p: MappingNotify!\n",
data);
752 if ((request == MappingKeyboard) || (request == MappingModifier)) {
753 X11_XRefreshKeyboardMapping(&xevent.xmapping);
762 switch (xevent.type) {
768 printf(
"window %p: EnterNotify! (%d,%d,%d)\n",
data,
771 xevent.xcrossing.mode);
772 if (xevent.xcrossing.mode == NotifyGrab)
773 printf(
"Mode: NotifyGrab\n");
774 if (xevent.xcrossing.mode == NotifyUngrab)
775 printf(
"Mode: NotifyUngrab\n");
779 mouse->
last_x = xevent.xcrossing.x;
780 mouse->
last_y = xevent.xcrossing.y;
790 printf(
"window %p: LeaveNotify! (%d,%d,%d)\n",
data,
793 xevent.xcrossing.mode);
794 if (xevent.xcrossing.mode == NotifyGrab)
795 printf(
"Mode: NotifyGrab\n");
796 if (xevent.xcrossing.mode == NotifyUngrab)
797 printf(
"Mode: NotifyUngrab\n");
803 if (xevent.xcrossing.mode != NotifyGrab &&
804 xevent.xcrossing.mode != NotifyUngrab &&
805 xevent.xcrossing.detail != NotifyInferior) {
813 if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
816 printf(
"window %p: FocusIn (NotifyGrab/NotifyUngrab, ignoring)\n",
data);
821 if (xevent.xfocus.detail == NotifyInferior) {
823 printf(
"window %p: FocusIn (NotifierInferior, ignoring)\n",
data);
828 printf(
"window %p: FocusIn!\n",
data);
833 data->pending_focus_time = 0;
847 if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
850 printf(
"window %p: FocusOut (NotifyGrab/NotifyUngrab, ignoring)\n",
data);
854 if (xevent.xfocus.detail == NotifyInferior) {
857 printf(
"window %p: FocusOut (NotifierInferior, ignoring)\n",
data);
862 printf(
"window %p: FocusOut!\n",
data);
867 data->pending_focus_time = 0;
880 KeyCode keycode = xevent.xkey.keycode;
881 KeySym keysym = NoSymbol;
887 printf(
"window %p: KeyPress (X11 keycode = 0x%X)\n",
data, xevent.xkey.keycode);
891 int min_keycode, max_keycode;
892 X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
895 "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL forums/mailing list <https://discourse.libsdl.org/> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
896 keycode, keycode - min_keycode, keysym,
897 X11_XKeysymToString(keysym));
902 #ifdef X_HAVE_UTF8_STRING
904 X11_Xutf8LookupString(
data->ic, &xevent.xkey,
text,
sizeof(
text),
907 X11_XLookupString(&xevent.xkey,
text,
sizeof(
text), &keysym,
NULL);
910 X11_XLookupString(&xevent.xkey,
text,
sizeof(
text), &keysym,
NULL);
918 if (!handled_by_ime) {
928 X11_UpdateUserTime(
data, xevent.xkey.time);
934 KeyCode keycode = xevent.xkey.keycode;
937 printf(
"window %p: KeyRelease (X11 keycode = 0x%X)\n",
data, xevent.xkey.keycode);
939 if (X11_KeyRepeat(display, &xevent)) {
950 printf(
"window %p: UnmapNotify!\n",
data);
952 X11_DispatchUnmapNotify(
data);
959 printf(
"window %p: MapNotify!\n",
data);
961 X11_DispatchMapNotify(
data);
966 case ConfigureNotify:{
968 printf(
"window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n",
data,
969 xevent.xconfigure.x, xevent.xconfigure.y,
970 xevent.xconfigure.width, xevent.xconfigure.height);
973 if (!xevent.xconfigure.send_event) {
974 unsigned int NumChildren;
975 Window ChildReturn, Root, Parent;
978 X11_XQueryTree(
data->videodata->display, xevent.xconfigure.window, &Root, &Parent, &Children, &NumChildren);
979 X11_XTranslateCoordinates(xevent.xconfigure.display,
980 Parent, DefaultRootWindow(xevent.xconfigure.display),
981 xevent.xconfigure.x, xevent.xconfigure.y,
982 &xevent.xconfigure.x, &xevent.xconfigure.y,
986 if (xevent.xconfigure.x !=
data->last_xconfigure.x ||
987 xevent.xconfigure.y !=
data->last_xconfigure.y) {
989 xevent.xconfigure.x, xevent.xconfigure.y);
997 if (xevent.xconfigure.width !=
data->last_xconfigure.width ||
998 xevent.xconfigure.height !=
data->last_xconfigure.height) {
1000 xevent.xconfigure.width,
1001 xevent.xconfigure.height);
1003 data->last_xconfigure = xevent.xconfigure;
1008 case ClientMessage:{
1010 static int xdnd_version=0;
1012 if (xevent.xclient.message_type == videodata->
XdndEnter) {
1014 SDL_bool use_list = xevent.xclient.data.l[1] & 1;
1015 data->xdnd_source = xevent.xclient.data.l[0];
1016 xdnd_version = (xevent.xclient.data.l[1] >> 24);
1017 #ifdef DEBUG_XEVENTS
1018 printf(
"XID of source window : %ld\n",
data->xdnd_source);
1019 printf(
"Protocol version to use : %d\n", xdnd_version);
1020 printf(
"More then 3 data types : %d\n", (
int) use_list);
1028 data->xdnd_req = X11_PickTarget(display, (Atom*)
p.data,
p.count);
1032 data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]);
1035 else if (xevent.xclient.message_type == videodata->
XdndPosition) {
1037 #ifdef DEBUG_XEVENTS
1039 if(xdnd_version >= 2) {
1040 act = xevent.xclient.data.l[4];
1042 printf(
"Action requested by user is : %s\n", X11_XGetAtomName(display , act));
1047 memset(&
m, 0,
sizeof(XClientMessageEvent));
1048 m.type = ClientMessage;
1049 m.display = xevent.xclient.display;
1050 m.window = xevent.xclient.data.l[0];
1053 m.data.l[0] =
data->xwindow;
1054 m.data.l[1] = (
data->xdnd_req != None);
1059 X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&
m);
1060 X11_XFlush(display);
1062 else if(xevent.xclient.message_type == videodata->
XdndDrop) {
1063 if (
data->xdnd_req == None) {
1065 memset(&
m, 0,
sizeof(XClientMessageEvent));
1066 m.type = ClientMessage;
1067 m.display = xevent.xclient.display;
1068 m.window = xevent.xclient.data.l[0];
1071 m.data.l[0] =
data->xwindow;
1074 X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&
m);
1077 if(xdnd_version >= 1) {
1084 else if ((xevent.xclient.message_type == videodata->
WM_PROTOCOLS) &&
1085 (xevent.xclient.format == 32) &&
1086 (xevent.xclient.data.l[0] == videodata->
_NET_WM_PING)) {
1087 Window root = DefaultRootWindow(display);
1089 #ifdef DEBUG_XEVENTS
1090 printf(
"window %p: _NET_WM_PING\n",
data);
1092 xevent.xclient.window = root;
1093 X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
1097 else if ((xevent.xclient.message_type == videodata->
WM_PROTOCOLS) &&
1098 (xevent.xclient.format == 32) &&
1101 #ifdef DEBUG_XEVENTS
1102 printf(
"window %p: WM_DELETE_WINDOW\n",
data);
1107 else if ((xevent.xclient.message_type == videodata->
WM_PROTOCOLS) &&
1108 (xevent.xclient.format == 32) &&
1111 #ifdef DEBUG_XEVENTS
1112 printf(
"window %p: WM_TAKE_FOCUS\n",
data);
1122 #ifdef DEBUG_XEVENTS
1123 printf(
"window %p: Expose (count = %d)\n",
data, xevent.xexpose.count);
1133 printf(
"window %p: X11 motion: %d,%d\n",
data, xevent.xmotion.x, xevent.xmotion.y);
1142 int xticks = 0, yticks = 0;
1143 #ifdef DEBUG_XEVENTS
1144 printf(
"window %p: ButtonPress (X11 button = %d)\n",
data, xevent.xbutton.button);
1146 if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
1150 int button = xevent.xbutton.button;
1152 if (ProcessHitTest(
_this,
data, &xevent)) {
1162 if (
data->last_focus_event_time) {
1163 const int X11_FOCUS_CLICK_TIMEOUT = 10;
1167 data->last_focus_event_time = 0;
1169 if (!ignore_click) {
1173 X11_UpdateUserTime(
data, xevent.xbutton.time);
1177 case ButtonRelease:{
1178 int button = xevent.xbutton.button;
1180 int xticks = 0, yticks = 0;
1181 #ifdef DEBUG_XEVENTS
1182 printf(
"window %p: ButtonRelease (X11 button = %d)\n",
data, xevent.xbutton.button);
1184 if (!X11_IsWheelEvent(display, &xevent, &xticks, &yticks)) {
1194 case PropertyNotify:{
1195 #ifdef DEBUG_XEVENTS
1196 unsigned char *propdata;
1197 int status, real_format;
1199 unsigned long items_read, items_left;
1201 char *
name = X11_XGetAtomName(display, xevent.xproperty.atom);
1203 printf(
"window %p: PropertyNotify: %s %s time=%lu\n",
data,
name, (xevent.xproperty.state == PropertyDelete) ?
"deleted" :
"changed", xevent.xproperty.time);
1207 status = X11_XGetWindowProperty(display,
data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
1208 if (status == Success && items_read > 0) {
1209 if (real_type == XA_INTEGER) {
1210 int *
values = (
int *)propdata;
1213 for (
i = 0;
i < items_read;
i++) {
1217 }
else if (real_type == XA_CARDINAL) {
1218 if (real_format == 32) {
1222 for (
i = 0;
i < items_read;
i++) {
1226 }
else if (real_format == 16) {
1230 for (
i = 0;
i < items_read;
i++) {
1234 }
else if (real_format == 8) {
1238 for (
i = 0;
i < items_read;
i++) {
1243 }
else if (real_type == XA_STRING ||
1245 printf(
"{ \"%s\" }\n", propdata);
1246 }
else if (real_type == XA_ATOM) {
1247 Atom *atoms = (Atom *)propdata;
1250 for (
i = 0;
i < items_read;
i++) {
1251 char *atomname = X11_XGetAtomName(display, atoms[
i]);
1253 printf(
" %s", atomname);
1254 X11_XFree(atomname);
1259 char *atomname = X11_XGetAtomName(display, real_type);
1260 printf(
"Unknown type: %ld (%s)\n", real_type, atomname ? atomname :
"UNKNOWN");
1262 X11_XFree(atomname);
1266 if (status == Success) {
1267 X11_XFree(propdata);
1278 if (!
data->user_time) {
1279 data->user_time = xevent.xproperty.time;
1282 if (xevent.xproperty.atom ==
data->videodata->_NET_WM_STATE) {
1293 X11_DispatchUnmapNotify(
data);
1295 X11_DispatchMapNotify(
data);
1318 unsigned long nitems, bytes_after;
1319 unsigned char *property;
1320 if (X11_XGetWindowProperty(display,
data->xwindow, videodata->
_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &
type, &
format, &nitems, &bytes_after, &property) == Success) {
1321 if (
type != None && nitems == 4) {
1322 data->border_left = (int) ((
long*)property)[0];
1323 data->border_right = (int) ((
long*)property)[1];
1324 data->border_top = (int) ((
long*)property)[2];
1325 data->border_bottom = (int) ((
long*)property)[3];
1327 X11_XFree(property);
1329 #ifdef DEBUG_XEVENTS
1330 printf(
"New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n",
data->border_left,
data->border_right,
data->border_top,
data->border_bottom);
1337 case SelectionNotify: {
1338 Atom
target = xevent.xselection.target;
1339 #ifdef DEBUG_XEVENTS
1340 printf(
"window %p: SelectionNotify (requestor = %ld, target = %ld)\n",
data,
1341 xevent.xselection.requestor, xevent.xselection.target);
1346 X11_ReadProperty(&
p, display,
data->xwindow, videodata->
PRIMARY);
1348 if (
p.format == 8) {
1349 char* saveptr =
NULL;
1350 char*
name = X11_XGetAtomName(display,
target);
1351 char *token =
SDL_strtokr((
char *)
p.data,
"\r\n", &saveptr);
1352 while (token !=
NULL) {
1356 char *fn = X11_URIToLocal(token);
1369 m.type = ClientMessage;
1370 m.display = display;
1371 m.window =
data->xdnd_source;
1374 m.data.l[0] =
data->xwindow;
1377 X11_XSendEvent(display,
data->xdnd_source, False, NoEventMask, (XEvent*)&
m);
1379 X11_XSync(display, False);
1385 #ifdef DEBUG_XEVENTS
1386 printf(
"window %p: Unhandled event %d\n",
data, xevent.type);
1394 X11_HandleFocusChanges(
_THIS)
1418 X11_Pending(Display * display)
1421 X11_XFlush(display);
1422 if (X11_XEventsQueued(display, QueuedAlready)) {
1428 return (X11_XPending(display));
1440 if (
data->last_mode_change_deadline) {
1442 data->last_mode_change_deadline = 0;
1449 if (!
data->screensaver_activity ||
1451 X11_XResetScreenSaver(
data->display);
1454 SDL_DBus_ScreensaverTickle();
1457 data->screensaver_activity = now;
1462 while (X11_Pending(
data->display)) {
1463 X11_DispatchEvent(
_this);
1473 X11_HandleFocusChanges(
_this);
1480 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
1483 int major_version, minor_version;
1492 SDL_DBus_ScreensaverTickle();
1496 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
1497 if (SDL_X11_HAVE_XSS) {
1499 if (!X11_XScreenSaverQueryExtension(
data->display, &dummy, &dummy) ||
1500 !X11_XScreenSaverQueryVersion(
data->display,
1501 &major_version, &minor_version) ||
1502 major_version < 1 || (major_version == 1 && minor_version < 1)) {
1507 X11_XResetScreenSaver(
data->display);