SDL  2.0
SDL_x11events.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_X11
24 
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <limits.h> /* For INT_MAX */
30 
31 #include "SDL_x11video.h"
32 #include "SDL_x11touch.h"
33 #include "SDL_x11xinput2.h"
34 #include "../../events/SDL_events_c.h"
35 #include "../../events/SDL_mouse_c.h"
36 #include "../../events/SDL_touch_c.h"
37 
38 #include "SDL_timer.h"
39 #include "SDL_syswm.h"
40 
41 #include <stdio.h>
42 
43 /*#define DEBUG_XEVENTS*/
44 
45 #ifndef _NET_WM_MOVERESIZE_SIZE_TOPLEFT
46 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
47 #endif
48 
49 #ifndef _NET_WM_MOVERESIZE_SIZE_TOP
50 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
51 #endif
52 
53 #ifndef _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
54 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
55 #endif
56 
57 #ifndef _NET_WM_MOVERESIZE_SIZE_RIGHT
58 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
59 #endif
60 
61 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
62 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
63 #endif
64 
65 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOM
66 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
67 #endif
68 
69 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
70 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
71 #endif
72 
73 #ifndef _NET_WM_MOVERESIZE_SIZE_LEFT
74 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
75 #endif
76 
77 #ifndef _NET_WM_MOVERESIZE_MOVE
78 #define _NET_WM_MOVERESIZE_MOVE 8
79 #endif
80 
81 typedef struct {
82  unsigned char *data;
83  int format, count;
84  Atom type;
85 } SDL_x11Prop;
86 
87 /* Reads property
88  Must call X11_XFree on results
89  */
90 static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop)
91 {
92  unsigned char *ret=NULL;
93  Atom type;
94  int fmt;
95  unsigned long count;
96  unsigned long bytes_left;
97  int bytes_fetch = 0;
98 
99  do {
100  if (ret != 0) X11_XFree(ret);
101  X11_XGetWindowProperty(disp, w, prop, 0, bytes_fetch, False, AnyPropertyType, &type, &fmt, &count, &bytes_left, &ret);
102  bytes_fetch += bytes_left;
103  } while (bytes_left != 0);
104 
105  p->data=ret;
106  p->format=fmt;
107  p->count=count;
108  p->type=type;
109 }
110 
111 /* Find text-uri-list in a list of targets and return it's atom
112  if available, else return None */
113 static Atom X11_PickTarget(Display *disp, Atom list[], int list_count)
114 {
115  Atom request = None;
116  char *name;
117  int i;
118  for (i=0; i < list_count && request == None; i++) {
119  name = X11_XGetAtomName(disp, list[i]);
120  if (strcmp("text/uri-list", name)==0) request = list[i];
121  X11_XFree(name);
122  }
123  return request;
124 }
125 
126 /* Wrapper for X11_PickTarget for a maximum of three targets, a special
127  case in the Xdnd protocol */
128 static Atom X11_PickTargetFromAtoms(Display *disp, Atom a0, Atom a1, Atom a2)
129 {
130  int count=0;
131  Atom atom[3];
132  if (a0 != None) atom[count++] = a0;
133  if (a1 != None) atom[count++] = a1;
134  if (a2 != None) atom[count++] = a2;
135  return X11_PickTarget(disp, atom, count);
136 }
137 
138 struct KeyRepeatCheckData
139 {
140  XEvent *event;
141  SDL_bool found;
142 };
143 
144 static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
145  XPointer arg)
146 {
147  struct KeyRepeatCheckData *d = (struct KeyRepeatCheckData *) arg;
148  if (chkev->type == KeyPress &&
149  chkev->xkey.keycode == d->event->xkey.keycode &&
150  chkev->xkey.time - d->event->xkey.time < 2)
151  d->found = SDL_TRUE;
152  return False;
153 }
154 
155 /* Check to see if this is a repeated key.
156  (idea shamelessly lifted from GII -- thanks guys! :)
157  */
158 static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
159 {
160  XEvent dummyev;
161  struct KeyRepeatCheckData d;
162  d.event = event;
163  d.found = SDL_FALSE;
164  if (X11_XPending(display))
165  X11_XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent,
166  (XPointer) &d);
167  return d.found;
168 }
169 
170 static SDL_bool
171 X11_IsWheelEvent(Display * display,XEvent * event,int * xticks,int * yticks)
172 {
173  /* according to the xlib docs, no specific mouse wheel events exist.
174  However, the defacto standard is that the vertical wheel is X buttons
175  4 (up) and 5 (down) and a horizontal wheel is 6 (left) and 7 (right). */
176 
177  /* Xlib defines "Button1" through 5, so we just use literals here. */
178  switch (event->xbutton.button) {
179  case 4: *yticks = 1; return SDL_TRUE;
180  case 5: *yticks = -1; return SDL_TRUE;
181  case 6: *xticks = 1; return SDL_TRUE;
182  case 7: *xticks = -1; return SDL_TRUE;
183  default: break;
184  }
185  return SDL_FALSE;
186 }
187 
188 /* Decodes URI escape sequences in string buf of len bytes
189  (excluding the terminating NULL byte) in-place. Since
190  URI-encoded characters take three times the space of
191  normal characters, this should not be an issue.
192 
193  Returns the number of decoded bytes that wound up in
194  the buffer, excluding the terminating NULL byte.
195 
196  The buffer is guaranteed to be NULL-terminated but
197  may contain embedded NULL bytes.
198 
199  On error, -1 is returned.
200  */
201 int X11_URIDecode(char *buf, int len) {
202  int ri, wi, di;
203  char decode = '\0';
204  if (buf == NULL || len < 0) {
205  errno = EINVAL;
206  return -1;
207  }
208  if (len == 0) {
209  len = SDL_strlen(buf);
210  }
211  for (ri = 0, wi = 0, di = 0; ri < len && wi < len; ri += 1) {
212  if (di == 0) {
213  /* start decoding */
214  if (buf[ri] == '%') {
215  decode = '\0';
216  di += 1;
217  continue;
218  }
219  /* normal write */
220  buf[wi] = buf[ri];
221  wi += 1;
222  continue;
223  } else if (di == 1 || di == 2) {
224  char off = '\0';
225  char isa = buf[ri] >= 'a' && buf[ri] <= 'f';
226  char isA = buf[ri] >= 'A' && buf[ri] <= 'F';
227  char isn = buf[ri] >= '0' && buf[ri] <= '9';
228  if (!(isa || isA || isn)) {
229  /* not a hexadecimal */
230  int sri;
231  for (sri = ri - di; sri <= ri; sri += 1) {
232  buf[wi] = buf[sri];
233  wi += 1;
234  }
235  di = 0;
236  continue;
237  }
238  /* itsy bitsy magicsy */
239  if (isn) {
240  off = 0 - '0';
241  } else if (isa) {
242  off = 10 - 'a';
243  } else if (isA) {
244  off = 10 - 'A';
245  }
246  decode |= (buf[ri] + off) << (2 - di) * 4;
247  if (di == 2) {
248  buf[wi] = decode;
249  wi += 1;
250  di = 0;
251  } else {
252  di += 1;
253  }
254  continue;
255  }
256  }
257  buf[wi] = '\0';
258  return wi;
259 }
260 
261 /* Convert URI to local filename
262  return filename if possible, else NULL
263 */
264 static char* X11_URIToLocal(char* uri) {
265  char *file = NULL;
266  SDL_bool local;
267 
268  if (memcmp(uri,"file:/",6) == 0) uri += 6; /* local file? */
269  else if (strstr(uri,":/") != NULL) return file; /* wrong scheme */
270 
271  local = uri[0] != '/' || (uri[0] != '\0' && uri[1] == '/');
272 
273  /* got a hostname? */
274  if (!local && uri[0] == '/' && uri[2] != '/') {
275  char* hostname_end = strchr(uri+1, '/');
276  if (hostname_end != NULL) {
277  char hostname[ 257 ];
278  if (gethostname(hostname, 255) == 0) {
279  hostname[ 256 ] = '\0';
280  if (memcmp(uri+1, hostname, hostname_end - (uri+1)) == 0) {
281  uri = hostname_end + 1;
282  local = SDL_TRUE;
283  }
284  }
285  }
286  }
287  if (local) {
288  file = uri;
289  /* Convert URI escape sequences to real characters */
290  X11_URIDecode(file, 0);
291  if (uri[1] == '/') {
292  file++;
293  } else {
294  file--;
295  }
296  }
297  return file;
298 }
299 
300 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
301 static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event)
302 {
303  /* event is a union, so cookie == &event, but this is type safe. */
304  XGenericEventCookie *cookie = &event.xcookie;
305  if (X11_XGetEventData(videodata->display, cookie)) {
306  X11_HandleXinput2Event(videodata, cookie);
307  X11_XFreeEventData(videodata->display, cookie);
308  }
309 }
310 #endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
311 
312 static unsigned
313 X11_GetNumLockModifierMask(_THIS)
314 {
316  Display *display = viddata->display;
317  unsigned num_mask = 0;
318  int i, j;
319  XModifierKeymap *xmods;
320  unsigned n;
321 
322  xmods = X11_XGetModifierMapping(display);
323  n = xmods->max_keypermod;
324  for(i = 3; i < 8; i++) {
325  for(j = 0; j < n; j++) {
326  KeyCode kc = xmods->modifiermap[i * n + j];
327  if (viddata->key_layout[kc] == SDL_SCANCODE_NUMLOCKCLEAR) {
328  num_mask = 1 << i;
329  break;
330  }
331  }
332  }
333  X11_XFreeModifiermap(xmods);
334 
335  return num_mask;
336 }
337 
338 static void
339 X11_ReconcileKeyboardState(_THIS)
340 {
342  Display *display = viddata->display;
343  char keys[32];
344  int keycode;
345  Window junk_window;
346  int x, y;
347  unsigned int mask;
348 
349  X11_XQueryKeymap(display, keys);
350 
351  /* Sync up the keyboard modifier state */
352  if (X11_XQueryPointer(display, DefaultRootWindow(display), &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
353  SDL_ToggleModState(KMOD_CAPS, (mask & LockMask) != 0);
354  SDL_ToggleModState(KMOD_NUM, (mask & X11_GetNumLockModifierMask(_this)) != 0);
355  }
356 
357  for (keycode = 0; keycode < 256; ++keycode) {
358  if (keys[keycode / 8] & (1 << (keycode % 8))) {
359  SDL_SendKeyboardKey(SDL_PRESSED, viddata->key_layout[keycode]);
360  } else {
361  SDL_SendKeyboardKey(SDL_RELEASED, viddata->key_layout[keycode]);
362  }
363  }
364 }
365 
366 
367 static void
368 X11_DispatchFocusIn(_THIS, SDL_WindowData *data)
369 {
370 #ifdef DEBUG_XEVENTS
371  printf("window %p: Dispatching FocusIn\n", data);
372 #endif
374  X11_ReconcileKeyboardState(_this);
375 #ifdef X_HAVE_UTF8_STRING
376  if (data->ic) {
377  X11_XSetICFocus(data->ic);
378  }
379 #endif
380 #ifdef SDL_USE_IBUS
381  SDL_IBus_SetFocus(SDL_TRUE);
382 #endif
383 }
384 
385 static void
386 X11_DispatchFocusOut(_THIS, SDL_WindowData *data)
387 {
388 #ifdef DEBUG_XEVENTS
389  printf("window %p: Dispatching FocusOut\n", data);
390 #endif
391  /* If another window has already processed a focus in, then don't try to
392  * remove focus here. Doing so will incorrectly remove focus from that
393  * window, and the focus lost event for this window will have already
394  * been dispatched anyway. */
395  if (data->window == SDL_GetKeyboardFocus()) {
397  }
398 #ifdef X_HAVE_UTF8_STRING
399  if (data->ic) {
400  X11_XUnsetICFocus(data->ic);
401  }
402 #endif
403 #ifdef SDL_USE_IBUS
404  SDL_IBus_SetFocus(SDL_FALSE);
405 #endif
406 }
407 
408 static void
409 X11_DispatchMapNotify(SDL_WindowData *data)
410 {
413 }
414 
415 static void
416 X11_DispatchUnmapNotify(SDL_WindowData *data)
417 {
420 }
421 
422 static void
423 InitiateWindowMove(_THIS, const SDL_WindowData *data, const SDL_Point *point)
424 {
426  SDL_Window* window = data->window;
427  Display *display = viddata->display;
428  XEvent evt;
429 
430  /* !!! FIXME: we need to regrab this if necessary when the drag is done. */
431  X11_XUngrabPointer(display, 0L);
432  X11_XFlush(display);
433 
434  evt.xclient.type = ClientMessage;
435  evt.xclient.window = data->xwindow;
436  evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
437  evt.xclient.format = 32;
438  evt.xclient.data.l[0] = window->x + point->x;
439  evt.xclient.data.l[1] = window->y + point->y;
440  evt.xclient.data.l[2] = _NET_WM_MOVERESIZE_MOVE;
441  evt.xclient.data.l[3] = Button1;
442  evt.xclient.data.l[4] = 0;
443  X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
444 
445  X11_XSync(display, 0);
446 }
447 
448 static void
449 InitiateWindowResize(_THIS, const SDL_WindowData *data, const SDL_Point *point, int direction)
450 {
452  SDL_Window* window = data->window;
453  Display *display = viddata->display;
454  XEvent evt;
455 
456  if (direction < _NET_WM_MOVERESIZE_SIZE_TOPLEFT || direction > _NET_WM_MOVERESIZE_SIZE_LEFT)
457  return;
458 
459  /* !!! FIXME: we need to regrab this if necessary when the drag is done. */
460  X11_XUngrabPointer(display, 0L);
461  X11_XFlush(display);
462 
463  evt.xclient.type = ClientMessage;
464  evt.xclient.window = data->xwindow;
465  evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
466  evt.xclient.format = 32;
467  evt.xclient.data.l[0] = window->x + point->x;
468  evt.xclient.data.l[1] = window->y + point->y;
469  evt.xclient.data.l[2] = direction;
470  evt.xclient.data.l[3] = Button1;
471  evt.xclient.data.l[4] = 0;
472  X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
473 
474  X11_XSync(display, 0);
475 }
476 
477 static SDL_bool
478 ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
479 {
480  SDL_Window *window = data->window;
481 
482  if (window->hit_test) {
483  const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
484  const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
485  static const int directions[] = {
486  _NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP,
487  _NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT,
488  _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT, _NET_WM_MOVERESIZE_SIZE_BOTTOM,
489  _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT
490  };
491 
492  switch (rc) {
494  InitiateWindowMove(_this, data, &point);
495  return SDL_TRUE;
496 
505  InitiateWindowResize(_this, data, &point, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
506  return SDL_TRUE;
507 
508  default: return SDL_FALSE;
509  }
510  }
511 
512  return SDL_FALSE;
513 }
514 
515 static void
516 X11_DispatchEvent(_THIS)
517 {
518  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
519  Display *display = videodata->display;
520  SDL_WindowData *data;
521  XEvent xevent;
522  int orig_event_type;
523  KeyCode orig_keycode;
524  XClientMessageEvent m;
525  int i;
526 
527  SDL_zero(xevent); /* valgrind fix. --ryan. */
528  X11_XNextEvent(display, &xevent);
529 
530  /* Save the original keycode for dead keys, which are filtered out by
531  the XFilterEvent() call below.
532  */
533  orig_event_type = xevent.type;
534  if (orig_event_type == KeyPress || orig_event_type == KeyRelease) {
535  orig_keycode = xevent.xkey.keycode;
536  } else {
537  orig_keycode = 0;
538  }
539 
540  /* filter events catchs XIM events and sends them to the correct handler */
541  if (X11_XFilterEvent(&xevent, None) == True) {
542 #if 0
543  printf("Filtered event type = %d display = %d window = %d\n",
544  xevent.type, xevent.xany.display, xevent.xany.window);
545 #endif
546  if (orig_keycode) {
547  /* Make sure dead key press/release events are sent */
548  /* Actually, don't do this because it causes double-delivery
549  of some keys on Ubuntu 14.04 (bug 2526)
550  SDL_Scancode scancode = videodata->key_layout[orig_keycode];
551  if (orig_event_type == KeyPress) {
552  SDL_SendKeyboardKey(SDL_PRESSED, scancode);
553  } else {
554  SDL_SendKeyboardKey(SDL_RELEASED, scancode);
555  }
556  */
557  }
558  return;
559  }
560 
561  /* Send a SDL_SYSWMEVENT if the application wants them */
563  SDL_SysWMmsg wmmsg;
564 
565  SDL_VERSION(&wmmsg.version);
566  wmmsg.subsystem = SDL_SYSWM_X11;
567  wmmsg.msg.x11.event = xevent;
568  SDL_SendSysWMEvent(&wmmsg);
569  }
570 
571 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
572  if(xevent.type == GenericEvent) {
573  X11_HandleGenericEvent(videodata,xevent);
574  return;
575  }
576 #endif
577 
578 #if 0
579  printf("type = %d display = %d window = %d\n",
580  xevent.type, xevent.xany.display, xevent.xany.window);
581 #endif
582 
583  data = NULL;
584  if (videodata && videodata->windowlist) {
585  for (i = 0; i < videodata->numwindows; ++i) {
586  if ((videodata->windowlist[i] != NULL) &&
587  (videodata->windowlist[i]->xwindow == xevent.xany.window)) {
588  data = videodata->windowlist[i];
589  break;
590  }
591  }
592  }
593  if (!data) {
594  /* The window for KeymapNotify, etc events is 0 */
595  if (xevent.type == KeymapNotify) {
596  if (SDL_GetKeyboardFocus() != NULL) {
597  X11_ReconcileKeyboardState(_this);
598  }
599  } else if (xevent.type == MappingNotify) {
600  /* Has the keyboard layout changed? */
601  const int request = xevent.xmapping.request;
602 
603 #ifdef DEBUG_XEVENTS
604  printf("window %p: MappingNotify!\n", data);
605 #endif
606  if ((request == MappingKeyboard) || (request == MappingModifier)) {
607  X11_XRefreshKeyboardMapping(&xevent.xmapping);
608  }
609 
612  }
613  return;
614  }
615 
616  switch (xevent.type) {
617 
618  /* Gaining mouse coverage? */
619  case EnterNotify:{
620 #ifdef DEBUG_XEVENTS
621  printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
622  xevent.xcrossing.x,
623  xevent.xcrossing.y,
624  xevent.xcrossing.mode);
625  if (xevent.xcrossing.mode == NotifyGrab)
626  printf("Mode: NotifyGrab\n");
627  if (xevent.xcrossing.mode == NotifyUngrab)
628  printf("Mode: NotifyUngrab\n");
629 #endif
630  SDL_SetMouseFocus(data->window);
631 
632  if (!SDL_GetMouse()->relative_mode) {
633  SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
634  }
635  }
636  break;
637  /* Losing mouse coverage? */
638  case LeaveNotify:{
639 #ifdef DEBUG_XEVENTS
640  printf("window %p: LeaveNotify! (%d,%d,%d)\n", data,
641  xevent.xcrossing.x,
642  xevent.xcrossing.y,
643  xevent.xcrossing.mode);
644  if (xevent.xcrossing.mode == NotifyGrab)
645  printf("Mode: NotifyGrab\n");
646  if (xevent.xcrossing.mode == NotifyUngrab)
647  printf("Mode: NotifyUngrab\n");
648 #endif
649  if (!SDL_GetMouse()->relative_mode) {
650  SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
651  }
652 
653  if (xevent.xcrossing.mode != NotifyGrab &&
654  xevent.xcrossing.mode != NotifyUngrab &&
655  xevent.xcrossing.detail != NotifyInferior) {
657  }
658  }
659  break;
660 
661  /* Gaining input focus? */
662  case FocusIn:{
663  if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
664  /* Someone is handling a global hotkey, ignore it */
665 #ifdef DEBUG_XEVENTS
666  printf("window %p: FocusIn (NotifyGrab/NotifyUngrab, ignoring)\n", data);
667 #endif
668  break;
669  }
670 
671  if (xevent.xfocus.detail == NotifyInferior) {
672 #ifdef DEBUG_XEVENTS
673  printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data);
674 #endif
675  break;
676  }
677 #ifdef DEBUG_XEVENTS
678  printf("window %p: FocusIn!\n", data);
679 #endif
680  if (!videodata->last_mode_change_deadline) /* no recent mode changes */
681  {
683  data->pending_focus_time = 0;
684  X11_DispatchFocusIn(_this, data);
685  }
686  else
687  {
690  }
691  }
692  break;
693 
694  /* Losing input focus? */
695  case FocusOut:{
696  if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
697  /* Someone is handling a global hotkey, ignore it */
698 #ifdef DEBUG_XEVENTS
699  printf("window %p: FocusOut (NotifyGrab/NotifyUngrab, ignoring)\n", data);
700 #endif
701  break;
702  }
703  if (xevent.xfocus.detail == NotifyInferior) {
704  /* We still have focus if a child gets focus */
705 #ifdef DEBUG_XEVENTS
706  printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data);
707 #endif
708  break;
709  }
710 #ifdef DEBUG_XEVENTS
711  printf("window %p: FocusOut!\n", data);
712 #endif
713  if (!videodata->last_mode_change_deadline) /* no recent mode changes */
714  {
716  data->pending_focus_time = 0;
717  X11_DispatchFocusOut(_this, data);
718  }
719  else
720  {
723  }
724  }
725  break;
726 
727  /* Key press? */
728  case KeyPress:{
729  KeyCode keycode = xevent.xkey.keycode;
730  KeySym keysym = NoSymbol;
732  Status status = 0;
733  SDL_bool handled_by_ime = SDL_FALSE;
734 
735 #ifdef DEBUG_XEVENTS
736  printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
737 #endif
738 #if 1
739  if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
740  int min_keycode, max_keycode;
741  X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
742 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
743  keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
744 #else
745  keysym = X11_XKeycodeToKeysym(display, keycode, 0);
746 #endif
747  fprintf(stderr,
748  "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",
749  keycode, keycode - min_keycode, keysym,
750  X11_XKeysymToString(keysym));
751  }
752 #endif
753  /* */
754  SDL_zero(text);
755 #ifdef X_HAVE_UTF8_STRING
756  if (data->ic) {
757  X11_Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
758  &keysym, &status);
759  }
760 #else
761  X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
762 #endif
763 
764 #ifdef SDL_USE_IBUS
766  handled_by_ime = SDL_IBus_ProcessKeyEvent(keysym, keycode);
767  }
768 #endif
769  if (!handled_by_ime) {
770  SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
771  if(*text) {
772  SDL_SendKeyboardText(text);
773  }
774  }
775 
776  }
777  break;
778 
779  /* Key release? */
780  case KeyRelease:{
781  KeyCode keycode = xevent.xkey.keycode;
782 
783 #ifdef DEBUG_XEVENTS
784  printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
785 #endif
786  if (X11_KeyRepeat(display, &xevent)) {
787  /* We're about to get a repeated key down, ignore the key up */
788  break;
789  }
790  SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
791  }
792  break;
793 
794  /* Have we been iconified? */
795  case UnmapNotify:{
796 #ifdef DEBUG_XEVENTS
797  printf("window %p: UnmapNotify!\n", data);
798 #endif
799  X11_DispatchUnmapNotify(data);
800  }
801  break;
802 
803  /* Have we been restored? */
804  case MapNotify:{
805 #ifdef DEBUG_XEVENTS
806  printf("window %p: MapNotify!\n", data);
807 #endif
808  X11_DispatchMapNotify(data);
809  }
810  break;
811 
812  /* Have we been resized or moved? */
813  case ConfigureNotify:{
814 #ifdef DEBUG_XEVENTS
815  printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data,
816  xevent.xconfigure.x, xevent.xconfigure.y,
817  xevent.xconfigure.width, xevent.xconfigure.height);
818 #endif
819  long border_left = 0;
820  long border_top = 0;
821  if (data->xwindow) {
822  Atom _net_frame_extents = X11_XInternAtom(display, "_NET_FRAME_EXTENTS", 0);
823  Atom type;
824  int format;
825  unsigned long nitems, bytes_after;
826  unsigned char *property;
827  if (X11_XGetWindowProperty(display, data->xwindow,
828  _net_frame_extents, 0, 16, 0,
829  XA_CARDINAL, &type, &format,
830  &nitems, &bytes_after, &property) == Success) {
831  if (type != None && nitems == 4)
832  {
833  border_left = ((long*)property)[0];
834  border_top = ((long*)property)[2];
835  }
836  X11_XFree(property);
837  }
838  }
839 
840  if (xevent.xconfigure.x != data->last_xconfigure.x ||
841  xevent.xconfigure.y != data->last_xconfigure.y) {
843  xevent.xconfigure.x - border_left,
844  xevent.xconfigure.y - border_top);
845 #ifdef SDL_USE_IBUS
847  /* Update IBus candidate list position */
848  SDL_IBus_UpdateTextRect(NULL);
849  }
850 #endif
851  }
852  if (xevent.xconfigure.width != data->last_xconfigure.width ||
853  xevent.xconfigure.height != data->last_xconfigure.height) {
855  xevent.xconfigure.width,
856  xevent.xconfigure.height);
857  }
858  data->last_xconfigure = xevent.xconfigure;
859  }
860  break;
861 
862  /* Have we been requested to quit (or another client message?) */
863  case ClientMessage:{
864 
865  static int xdnd_version=0;
866 
867  if (xevent.xclient.message_type == videodata->XdndEnter) {
868 
869  SDL_bool use_list = xevent.xclient.data.l[1] & 1;
870  data->xdnd_source = xevent.xclient.data.l[0];
871  xdnd_version = (xevent.xclient.data.l[1] >> 24);
872 #ifdef DEBUG_XEVENTS
873  printf("XID of source window : %ld\n", data->xdnd_source);
874  printf("Protocol version to use : %d\n", xdnd_version);
875  printf("More then 3 data types : %d\n", (int) use_list);
876 #endif
877 
878  if (use_list) {
879  /* fetch conversion targets */
880  SDL_x11Prop p;
881  X11_ReadProperty(&p, display, data->xdnd_source, videodata->XdndTypeList);
882  /* pick one */
883  data->xdnd_req = X11_PickTarget(display, (Atom*)p.data, p.count);
884  X11_XFree(p.data);
885  } else {
886  /* pick from list of three */
887  data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]);
888  }
889  }
890  else if (xevent.xclient.message_type == videodata->XdndPosition) {
891 
892 #ifdef DEBUG_XEVENTS
893  Atom act= videodata->XdndActionCopy;
894  if(xdnd_version >= 2) {
895  act = xevent.xclient.data.l[4];
896  }
897  printf("Action requested by user is : %s\n", X11_XGetAtomName(display , act));
898 #endif
899 
900 
901  /* reply with status */
902  memset(&m, 0, sizeof(XClientMessageEvent));
903  m.type = ClientMessage;
904  m.display = xevent.xclient.display;
905  m.window = xevent.xclient.data.l[0];
906  m.message_type = videodata->XdndStatus;
907  m.format=32;
908  m.data.l[0] = data->xwindow;
909  m.data.l[1] = (data->xdnd_req != None);
910  m.data.l[2] = 0; /* specify an empty rectangle */
911  m.data.l[3] = 0;
912  m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */
913 
914  X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
915  X11_XFlush(display);
916  }
917  else if(xevent.xclient.message_type == videodata->XdndDrop) {
918  if (data->xdnd_req == None) {
919  /* say again - not interested! */
920  memset(&m, 0, sizeof(XClientMessageEvent));
921  m.type = ClientMessage;
922  m.display = xevent.xclient.display;
923  m.window = xevent.xclient.data.l[0];
924  m.message_type = videodata->XdndFinished;
925  m.format=32;
926  m.data.l[0] = data->xwindow;
927  m.data.l[1] = 0;
928  m.data.l[2] = None; /* fail! */
929  X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
930  } else {
931  /* convert */
932  if(xdnd_version >= 1) {
933  X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
934  } else {
935  X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
936  }
937  }
938  }
939  else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
940  (xevent.xclient.format == 32) &&
941  (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) {
942  Window root = DefaultRootWindow(display);
943 
944 #ifdef DEBUG_XEVENTS
945  printf("window %p: _NET_WM_PING\n", data);
946 #endif
947  xevent.xclient.window = root;
948  X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
949  break;
950  }
951 
952  else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
953  (xevent.xclient.format == 32) &&
954  (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
955 
956 #ifdef DEBUG_XEVENTS
957  printf("window %p: WM_DELETE_WINDOW\n", data);
958 #endif
960  break;
961  }
962  }
963  break;
964 
965  /* Do we need to refresh ourselves? */
966  case Expose:{
967 #ifdef DEBUG_XEVENTS
968  printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
969 #endif
971  }
972  break;
973 
974  case MotionNotify:{
975  SDL_Mouse *mouse = SDL_GetMouse();
976  if(!mouse->relative_mode || mouse->relative_mode_warp) {
977 #ifdef DEBUG_MOTION
978  printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
979 #endif
980 
981  SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
982  }
983  }
984  break;
985 
986  case ButtonPress:{
987  int xticks = 0, yticks = 0;
988  if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
989  SDL_SendMouseWheel(data->window, 0, xticks, yticks, SDL_MOUSEWHEEL_NORMAL);
990  } else {
991  int button = xevent.xbutton.button;
992  if(button == Button1) {
993  if (ProcessHitTest(_this, data, &xevent)) {
994  break; /* don't pass this event on to app. */
995  }
996  }
997  else if(button > 7) {
998  /* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
999  => subtract (8-SDL_BUTTON_X1) to get value SDL expects */
1000  button -= (8-SDL_BUTTON_X1);
1001  }
1002  SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
1003  }
1004  }
1005  break;
1006 
1007  case ButtonRelease:{
1008  int button = xevent.xbutton.button;
1009  /* The X server sends a Release event for each Press for wheels. Ignore them. */
1010  int xticks = 0, yticks = 0;
1011  if (!X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
1012  if (button > 7) {
1013  /* see explanation at case ButtonPress */
1014  button -= (8-SDL_BUTTON_X1);
1015  }
1016  SDL_SendMouseButton(data->window, 0, SDL_RELEASED, button);
1017  }
1018  }
1019  break;
1020 
1021  case PropertyNotify:{
1022 #ifdef DEBUG_XEVENTS
1023  unsigned char *propdata;
1024  int status, real_format;
1025  Atom real_type;
1026  unsigned long items_read, items_left;
1027 
1028  char *name = X11_XGetAtomName(display, xevent.xproperty.atom);
1029  if (name) {
1030  printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
1031  X11_XFree(name);
1032  }
1033 
1034  status = X11_XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
1035  if (status == Success && items_read > 0) {
1036  if (real_type == XA_INTEGER) {
1037  int *values = (int *)propdata;
1038 
1039  printf("{");
1040  for (i = 0; i < items_read; i++) {
1041  printf(" %d", values[i]);
1042  }
1043  printf(" }\n");
1044  } else if (real_type == XA_CARDINAL) {
1045  if (real_format == 32) {
1046  Uint32 *values = (Uint32 *)propdata;
1047 
1048  printf("{");
1049  for (i = 0; i < items_read; i++) {
1050  printf(" %d", values[i]);
1051  }
1052  printf(" }\n");
1053  } else if (real_format == 16) {
1054  Uint16 *values = (Uint16 *)propdata;
1055 
1056  printf("{");
1057  for (i = 0; i < items_read; i++) {
1058  printf(" %d", values[i]);
1059  }
1060  printf(" }\n");
1061  } else if (real_format == 8) {
1062  Uint8 *values = (Uint8 *)propdata;
1063 
1064  printf("{");
1065  for (i = 0; i < items_read; i++) {
1066  printf(" %d", values[i]);
1067  }
1068  printf(" }\n");
1069  }
1070  } else if (real_type == XA_STRING ||
1071  real_type == videodata->UTF8_STRING) {
1072  printf("{ \"%s\" }\n", propdata);
1073  } else if (real_type == XA_ATOM) {
1074  Atom *atoms = (Atom *)propdata;
1075 
1076  printf("{");
1077  for (i = 0; i < items_read; i++) {
1078  char *atomname = X11_XGetAtomName(display, atoms[i]);
1079  if (atomname) {
1080  printf(" %s", atomname);
1081  X11_XFree(atomname);
1082  }
1083  }
1084  printf(" }\n");
1085  } else {
1086  char *atomname = X11_XGetAtomName(display, real_type);
1087  printf("Unknown type: %ld (%s)\n", real_type, atomname ? atomname : "UNKNOWN");
1088  if (atomname) {
1089  X11_XFree(atomname);
1090  }
1091  }
1092  }
1093  if (status == Success) {
1094  X11_XFree(propdata);
1095  }
1096 #endif /* DEBUG_XEVENTS */
1097 
1098  if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
1099  /* Get the new state from the window manager.
1100  Compositing window managers can alter visibility of windows
1101  without ever mapping / unmapping them, so we handle that here,
1102  because they use the NETWM protocol to notify us of changes.
1103  */
1104  const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
1105  const Uint32 changed = flags ^ data->window->flags;
1106 
1107  if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) {
1108  if (flags & SDL_WINDOW_HIDDEN) {
1109  X11_DispatchUnmapNotify(data);
1110  } else {
1111  X11_DispatchMapNotify(data);
1112  }
1113  }
1114 
1115  if (changed & SDL_WINDOW_MAXIMIZED) {
1116  if (flags & SDL_WINDOW_MAXIMIZED) {
1118  } else {
1120  }
1121  }
1122  } else if (xevent.xproperty.atom == videodata->XKLAVIER_STATE) {
1123  /* Hack for Ubuntu 12.04 (etc) that doesn't send MappingNotify
1124  events when the keyboard layout changes (for example,
1125  changing from English to French on the menubar's keyboard
1126  icon). Since it changes the XKLAVIER_STATE property, we
1127  notice and reinit our keymap here. This might not be the
1128  right approach, but it seems to work. */
1131  }
1132  }
1133  break;
1134 
1135  /* Copy the selection from our own CUTBUFFER to the requested property */
1136  case SelectionRequest: {
1137  XSelectionRequestEvent *req;
1138  XEvent sevent;
1139  int seln_format;
1140  unsigned long nbytes;
1141  unsigned long overflow;
1142  unsigned char *seln_data;
1143 
1144  req = &xevent.xselectionrequest;
1145 #ifdef DEBUG_XEVENTS
1146  printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data,
1147  req->requestor, req->target);
1148 #endif
1149 
1150  SDL_zero(sevent);
1151  sevent.xany.type = SelectionNotify;
1152  sevent.xselection.selection = req->selection;
1153  sevent.xselection.target = None;
1154  sevent.xselection.property = None;
1155  sevent.xselection.requestor = req->requestor;
1156  sevent.xselection.time = req->time;
1157 
1158  if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
1159  X11_GetSDLCutBufferClipboardType(display), 0, INT_MAX/4, False, req->target,
1160  &sevent.xselection.target, &seln_format, &nbytes,
1161  &overflow, &seln_data) == Success) {
1162  Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
1163  if (sevent.xselection.target == req->target) {
1164  X11_XChangeProperty(display, req->requestor, req->property,
1165  sevent.xselection.target, seln_format, PropModeReplace,
1166  seln_data, nbytes);
1167  sevent.xselection.property = req->property;
1168  } else if (XA_TARGETS == req->target) {
1169  Atom SupportedFormats[] = { XA_TARGETS, sevent.xselection.target };
1170  X11_XChangeProperty(display, req->requestor, req->property,
1171  XA_ATOM, 32, PropModeReplace,
1172  (unsigned char*)SupportedFormats,
1173  SDL_arraysize(SupportedFormats));
1174  sevent.xselection.property = req->property;
1175  sevent.xselection.target = XA_TARGETS;
1176  }
1177  X11_XFree(seln_data);
1178  }
1179  X11_XSendEvent(display, req->requestor, False, 0, &sevent);
1180  X11_XSync(display, False);
1181  }
1182  break;
1183 
1184  case SelectionNotify: {
1185 #ifdef DEBUG_XEVENTS
1186  printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
1187  xevent.xselection.requestor, xevent.xselection.target);
1188 #endif
1189  Atom target = xevent.xselection.target;
1190  if (target == data->xdnd_req) {
1191  /* read data */
1192  SDL_x11Prop p;
1193  X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
1194 
1195  if (p.format == 8) {
1196  SDL_bool expect_lf = SDL_FALSE;
1197  char *start = NULL;
1198  char *scan = (char*)p.data;
1199  char *fn;
1200  char *uri;
1201  int length = 0;
1202  while (p.count--) {
1203  if (!expect_lf) {
1204  if (*scan == 0x0D) {
1205  expect_lf = SDL_TRUE;
1206  }
1207  if (start == NULL) {
1208  start = scan;
1209  length = 0;
1210  }
1211  length++;
1212  } else {
1213  if (*scan == 0x0A && length > 0) {
1214  uri = SDL_malloc(length--);
1215  SDL_memcpy(uri, start, length);
1216  uri[length] = '\0';
1217  fn = X11_URIToLocal(uri);
1218  if (fn) {
1219  SDL_SendDropFile(fn);
1220  }
1221  SDL_free(uri);
1222  }
1223  expect_lf = SDL_FALSE;
1224  start = NULL;
1225  }
1226  scan++;
1227  }
1228  }
1229 
1230  X11_XFree(p.data);
1231 
1232  /* send reply */
1233  SDL_memset(&m, 0, sizeof(XClientMessageEvent));
1234  m.type = ClientMessage;
1235  m.display = display;
1236  m.window = data->xdnd_source;
1237  m.message_type = videodata->XdndFinished;
1238  m.format = 32;
1239  m.data.l[0] = data->xwindow;
1240  m.data.l[1] = 1;
1241  m.data.l[2] = videodata->XdndActionCopy;
1242  X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent*)&m);
1243 
1244  X11_XSync(display, False);
1245 
1246  } else {
1247  videodata->selection_waiting = SDL_FALSE;
1248  }
1249  }
1250  break;
1251 
1252  case SelectionClear: {
1253  Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
1254 
1255  if (xevent.xselectionclear.selection == XA_PRIMARY ||
1256  (XA_CLIPBOARD != None && xevent.xselectionclear.selection == XA_CLIPBOARD)) {
1258  }
1259  }
1260  break;
1261 
1262  default:{
1263 #ifdef DEBUG_XEVENTS
1264  printf("window %p: Unhandled event %d\n", data, xevent.type);
1265 #endif
1266  }
1267  break;
1268  }
1269 }
1270 
1271 static void
1272 X11_HandleFocusChanges(_THIS)
1273 {
1274  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
1275  int i;
1276 
1277  if (videodata && videodata->windowlist) {
1278  for (i = 0; i < videodata->numwindows; ++i) {
1279  SDL_WindowData *data = videodata->windowlist[i];
1280  if (data && data->pending_focus != PENDING_FOCUS_NONE) {
1281  Uint32 now = SDL_GetTicks();
1282  if (SDL_TICKS_PASSED(now, data->pending_focus_time)) {
1283  if (data->pending_focus == PENDING_FOCUS_IN) {
1284  X11_DispatchFocusIn(_this, data);
1285  } else {
1286  X11_DispatchFocusOut(_this, data);
1287  }
1289  }
1290  }
1291  }
1292  }
1293 }
1294 /* Ack! X11_XPending() actually performs a blocking read if no events available */
1295 static int
1296 X11_Pending(Display * display)
1297 {
1298  /* Flush the display connection and look to see if events are queued */
1299  X11_XFlush(display);
1300  if (X11_XEventsQueued(display, QueuedAlready)) {
1301  return (1);
1302  }
1303 
1304  /* More drastic measures are required -- see if X is ready to talk */
1305  {
1306  static struct timeval zero_time; /* static == 0 */
1307  int x11_fd;
1308  fd_set fdset;
1309 
1310  x11_fd = ConnectionNumber(display);
1311  FD_ZERO(&fdset);
1312  FD_SET(x11_fd, &fdset);
1313  if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
1314  return (X11_XPending(display));
1315  }
1316  }
1317 
1318  /* Oh well, nothing is ready .. */
1319  return (0);
1320 }
1321 
1322 void
1324 {
1326 
1327  if (data->last_mode_change_deadline) {
1329  data->last_mode_change_deadline = 0; /* assume we're done. */
1330  }
1331  }
1332 
1333  /* Update activity every 30 seconds to prevent screensaver */
1334  if (_this->suspend_screensaver) {
1335  const Uint32 now = SDL_GetTicks();
1336  if (!data->screensaver_activity ||
1337  SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
1338  X11_XResetScreenSaver(data->display);
1339 
1340 #if SDL_USE_LIBDBUS
1341  SDL_DBus_ScreensaverTickle();
1342 #endif
1343 
1344  data->screensaver_activity = now;
1345  }
1346  }
1347 
1348  /* Keep processing pending events */
1349  while (X11_Pending(data->display)) {
1350  X11_DispatchEvent(_this);
1351  }
1352 
1353 #ifdef SDL_USE_IBUS
1355  SDL_IBus_PumpEvents();
1356  }
1357 #endif
1358 
1359  /* FIXME: Only need to do this when there are pending focus changes */
1360  X11_HandleFocusChanges(_this);
1361 }
1362 
1363 
1364 void
1366 {
1367 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
1369  int dummy;
1370  int major_version, minor_version;
1371 #endif /* SDL_VIDEO_DRIVER_X11_XSCRNSAVER */
1372 
1373 #if SDL_USE_LIBDBUS
1374  if (SDL_DBus_ScreensaverInhibit(_this->suspend_screensaver)) {
1375  return;
1376  }
1377 
1378  if (_this->suspend_screensaver) {
1379  SDL_DBus_ScreensaverTickle();
1380  }
1381 #endif
1382 
1383 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
1384  if (SDL_X11_HAVE_XSS) {
1385  /* X11_XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
1386  if (!X11_XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
1387  !X11_XScreenSaverQueryVersion(data->display,
1388  &major_version, &minor_version) ||
1389  major_version < 1 || (major_version == 1 && minor_version < 1)) {
1390  return;
1391  }
1392 
1393  X11_XScreenSaverSuspend(data->display, _this->suspend_screensaver);
1394  X11_XResetScreenSaver(data->display);
1395  }
1396 #endif
1397 }
1398 
1399 #endif /* SDL_VIDEO_DRIVER_X11 */
1400 
1401 /* vi: set ts=4 sw=4 expandtab: */
void X11_PumpEvents(_THIS)
SDL_version version
Definition: SDL_syswm.h:131
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:66
SDL_Texture * button
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
Uint32 X11_GetNetWMState(_THIS, Window xwindow)
GLdouble n
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:155
void * hit_test_data
Definition: SDL_sysvideo.h:102
SDL_bool relative_mode_warp
Definition: SDL_mouse_c.h:85
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1564
const GLfloat * m
struct wl_display * display
SDL_Window * window
GLfloat GLfloat p
The structure that defines a point.
Definition: SDL_rect.h:48
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
SDL_WindowData ** windowlist
Definition: SDL_x11video.h:82
#define memset
Definition: SDL_malloc.c:639
#define SDL_ENABLE
Definition: SDL_events.h:718
GLuint start
Definition: SDL_opengl.h:1564
GLuint const GLchar * name
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
SDL_Window * window
#define SDL_BUTTON_X1
Definition: SDL_mouse.h:283
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:103
#define SDL_GetKeyboardFocus
union SDL_SysWMmsg::@16 msg
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
GLenum GLsizei len
SDL_bool selection_waiting
Definition: SDL_x11video.h:117
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:636
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:661
Atom _NET_WM_STATE
Definition: SDL_x11video.h:91
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
static SDL_VideoDevice * _this
Definition: SDL_video.c:114
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:852
SDL_bool
Definition: SDL_stdinc.h:126
int x
Definition: SDL_rect.h:50
#define SDL_memcpy
Uint32 screensaver_activity
Uint32 pending_focus_time
Definition: SDL_x11window.h:60
Atom WM_DELETE_WINDOW
Definition: SDL_x11video.h:90
#define SDL_GetEventState(type)
Definition: SDL_events.h:731
void X11_SuspendScreenSaver(_THIS)
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:188
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
int y
Definition: SDL_rect.h:51
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
#define _THIS
struct SDL_VideoData * videodata
int SDL_SendClipboardUpdate(void)
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:774
struct _cl_event * event
void SDL_free(void *mem)
SDL_bool relative_mode
Definition: SDL_mouse_c.h:84
GLenum GLsizei GLsizei GLint * values
#define SDL_zero(x)
Definition: SDL_stdinc.h:355
void X11_UpdateKeymap(_THIS)
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLint GLuint mask
Window xdnd_source
Definition: SDL_x11window.h:64
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
Definition: SDL_keyboard.c:850
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_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:132
#define NULL
Definition: begin_code.h:143
SDL_HitTest hit_test
Definition: SDL_sysvideo.h:101
Atom X11_GetSDLCutBufferClipboardType(Display *display)
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:34
struct SDL_SysWMmsg::@16::@17 x11
int SDL_SendKeymapChangedEvent(void)
Definition: SDL_events.c:653
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1565
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
#define SDL_strlen
int SDL_SendDropFile(const char *file)
#define PENDING_FOCUS_TIME
Definition: SDL_x11window.h:30
The type used to identify a window.
Definition: SDL_sysvideo.h:71
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:147
XConfigureEvent last_xconfigure
Definition: SDL_x11window.h:61
int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie)
SDL_bool suspend_screensaver
Definition: SDL_sysvideo.h:278
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
GLbitfield flags
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:406
#define SDL_malloc
#define SDL_TEXTINPUTEVENT_TEXT_SIZE
Definition: SDL_events.h:214
GLubyte GLubyte GLubyte GLubyte w
Uint32 last_mode_change_deadline
Definition: SDL_x11video.h:119
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1564
#define SDL_PRESSED
Definition: SDL_events.h:50
GLuint GLsizei GLsizei * length
Uint32 flags
Definition: SDL_sysvideo.h:81
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
#define SDL_RELEASED
Definition: SDL_events.h:49
GLenum target
PendingFocusEnum pending_focus
Definition: SDL_x11window.h:59
struct XGenericEventCookie XGenericEventCookie
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:326
#define SDL_memset
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