SDL  2.0
SDL_x11events.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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 "../../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"
38 
39 #include "SDL_hints.h"
40 #include "SDL_timer.h"
41 #include "SDL_syswm.h"
42 #include "SDL_assert.h"
43 
44 #include <stdio.h>
45 
46 /*#define DEBUG_XEVENTS*/
47 
48 #ifndef _NET_WM_MOVERESIZE_SIZE_TOPLEFT
49 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
50 #endif
51 
52 #ifndef _NET_WM_MOVERESIZE_SIZE_TOP
53 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
54 #endif
55 
56 #ifndef _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
57 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
58 #endif
59 
60 #ifndef _NET_WM_MOVERESIZE_SIZE_RIGHT
61 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
62 #endif
63 
64 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
65 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
66 #endif
67 
68 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOM
69 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
70 #endif
71 
72 #ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
73 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
74 #endif
75 
76 #ifndef _NET_WM_MOVERESIZE_SIZE_LEFT
77 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
78 #endif
79 
80 #ifndef _NET_WM_MOVERESIZE_MOVE
81 #define _NET_WM_MOVERESIZE_MOVE 8
82 #endif
83 
84 typedef struct {
85  unsigned char *data;
86  int format, count;
87  Atom type;
88 } SDL_x11Prop;
89 
90 /* Reads property
91  Must call X11_XFree on results
92  */
93 static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop)
94 {
95  unsigned char *ret=NULL;
96  Atom type;
97  int fmt;
98  unsigned long count;
99  unsigned long bytes_left;
100  int bytes_fetch = 0;
101 
102  do {
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);
107 
108  p->data=ret;
109  p->format=fmt;
110  p->count=count;
111  p->type=type;
112 }
113 
114 /* Find text-uri-list in a list of targets and return it's atom
115  if available, else return None */
116 static Atom X11_PickTarget(Display *disp, Atom list[], int list_count)
117 {
118  Atom request = None;
119  char *name;
120  int i;
121  for (i=0; i < list_count && request == None; i++) {
122  name = X11_XGetAtomName(disp, list[i]);
123  if ((SDL_strcmp("text/uri-list", name) == 0) || (SDL_strcmp("text/plain", name) == 0)) {
124  request = list[i];
125  }
126  X11_XFree(name);
127  }
128  return request;
129 }
130 
131 /* Wrapper for X11_PickTarget for a maximum of three targets, a special
132  case in the Xdnd protocol */
133 static Atom X11_PickTargetFromAtoms(Display *disp, Atom a0, Atom a1, Atom a2)
134 {
135  int count=0;
136  Atom atom[3];
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);
141 }
142 
143 struct KeyRepeatCheckData
144 {
145  XEvent *event;
146  SDL_bool found;
147 };
148 
149 static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
150  XPointer arg)
151 {
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)
156  d->found = SDL_TRUE;
157  return False;
158 }
159 
160 /* Check to see if this is a repeated key.
161  (idea shamelessly lifted from GII -- thanks guys! :)
162  */
163 static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
164 {
165  XEvent dummyev;
166  struct KeyRepeatCheckData d;
167  d.event = event;
168  d.found = SDL_FALSE;
169  if (X11_XPending(display))
170  X11_XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent,
171  (XPointer) &d);
172  return d.found;
173 }
174 
175 static SDL_bool
176 X11_IsWheelEvent(Display * display,XEvent * event,int * xticks,int * yticks)
177 {
178  /* according to the xlib docs, no specific mouse wheel events exist.
179  However, the defacto standard is that the vertical wheel is X buttons
180  4 (up) and 5 (down) and a horizontal wheel is 6 (left) and 7 (right). */
181 
182  /* Xlib defines "Button1" through 5, so we just use literals here. */
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;
188  default: break;
189  }
190  return SDL_FALSE;
191 }
192 
193 /* Decodes URI escape sequences in string buf of len bytes
194  (excluding the terminating NULL byte) in-place. Since
195  URI-encoded characters take three times the space of
196  normal characters, this should not be an issue.
197 
198  Returns the number of decoded bytes that wound up in
199  the buffer, excluding the terminating NULL byte.
200 
201  The buffer is guaranteed to be NULL-terminated but
202  may contain embedded NULL bytes.
203 
204  On error, -1 is returned.
205  */
206 static int X11_URIDecode(char *buf, int len) {
207  int ri, wi, di;
208  char decode = '\0';
209  if (buf == NULL || len < 0) {
210  errno = EINVAL;
211  return -1;
212  }
213  if (len == 0) {
214  len = SDL_strlen(buf);
215  }
216  for (ri = 0, wi = 0, di = 0; ri < len && wi < len; ri += 1) {
217  if (di == 0) {
218  /* start decoding */
219  if (buf[ri] == '%') {
220  decode = '\0';
221  di += 1;
222  continue;
223  }
224  /* normal write */
225  buf[wi] = buf[ri];
226  wi += 1;
227  continue;
228  } else if (di == 1 || di == 2) {
229  char off = '\0';
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)) {
234  /* not a hexadecimal */
235  int sri;
236  for (sri = ri - di; sri <= ri; sri += 1) {
237  buf[wi] = buf[sri];
238  wi += 1;
239  }
240  di = 0;
241  continue;
242  }
243  /* itsy bitsy magicsy */
244  if (isn) {
245  off = 0 - '0';
246  } else if (isa) {
247  off = 10 - 'a';
248  } else if (isA) {
249  off = 10 - 'A';
250  }
251  decode |= (buf[ri] + off) << (2 - di) * 4;
252  if (di == 2) {
253  buf[wi] = decode;
254  wi += 1;
255  di = 0;
256  } else {
257  di += 1;
258  }
259  continue;
260  }
261  }
262  buf[wi] = '\0';
263  return wi;
264 }
265 
266 /* Convert URI to local filename
267  return filename if possible, else NULL
268 */
269 static char* X11_URIToLocal(char* uri) {
270  char *file = NULL;
271  SDL_bool local;
272 
273  if (memcmp(uri,"file:/",6) == 0) uri += 6; /* local file? */
274  else if (strstr(uri,":/") != NULL) return file; /* wrong scheme */
275 
276  local = uri[0] != '/' || (uri[0] != '\0' && uri[1] == '/');
277 
278  /* got a hostname? */
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;
287  local = SDL_TRUE;
288  }
289  }
290  }
291  }
292  if (local) {
293  file = uri;
294  /* Convert URI escape sequences to real characters */
295  X11_URIDecode(file, 0);
296  if (uri[1] == '/') {
297  file++;
298  } else {
299  file--;
300  }
301  }
302  return file;
303 }
304 
305 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
306 static void X11_HandleGenericEvent(SDL_VideoData *videodata, XEvent *xev)
307 {
308  /* event is a union, so cookie == &event, but this is type safe. */
309  XGenericEventCookie *cookie = &xev->xcookie;
310  if (X11_XGetEventData(videodata->display, cookie)) {
311  X11_HandleXinput2Event(videodata, cookie);
312 
313  /* Send a SDL_SYSWMEVENT if the application wants them.
314  * Since event data is only available until XFreeEventData is called,
315  * the *only* way for an application to access it is to register an event filter/watcher
316  * and do all the processing on the SDL_SYSWMEVENT inside the callback. */
318  SDL_SysWMmsg wmmsg;
319 
320  SDL_VERSION(&wmmsg.version);
321  wmmsg.subsystem = SDL_SYSWM_X11;
322  wmmsg.msg.x11.event = *xev;
323  SDL_SendSysWMEvent(&wmmsg);
324  }
325 
326  X11_XFreeEventData(videodata->display, cookie);
327  }
328 }
329 #endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
330 
331 static unsigned
332 X11_GetNumLockModifierMask(_THIS)
333 {
335  Display *display = viddata->display;
336  unsigned num_mask = 0;
337  int i, j;
338  XModifierKeymap *xmods;
339  unsigned n;
340 
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];
346  if (viddata->key_layout[kc] == SDL_SCANCODE_NUMLOCKCLEAR) {
347  num_mask = 1 << i;
348  break;
349  }
350  }
351  }
352  X11_XFreeModifiermap(xmods);
353 
354  return num_mask;
355 }
356 
357 static void
358 X11_ReconcileKeyboardState(_THIS)
359 {
361  Display *display = viddata->display;
362  char keys[32];
363  int keycode;
364  Window junk_window;
365  int x, y;
366  unsigned int mask;
367  const Uint8 *keyboardState;
368 
369  X11_XQueryKeymap(display, keys);
370 
371  /* Sync up the keyboard modifier state */
372  if (X11_XQueryPointer(display, DefaultRootWindow(display), &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
373  SDL_ToggleModState(KMOD_CAPS, (mask & LockMask) != 0);
374  SDL_ToggleModState(KMOD_NUM, (mask & X11_GetNumLockModifierMask(_this)) != 0);
375  }
376 
377  keyboardState = SDL_GetKeyboardState(0);
378  for (keycode = 0; keycode < 256; ++keycode) {
379  SDL_Scancode scancode = viddata->key_layout[keycode];
380  SDL_bool x11KeyPressed = (keys[keycode / 8] & (1 << (keycode % 8))) != 0;
381  SDL_bool sdlKeyPressed = keyboardState[scancode] == SDL_PRESSED;
382 
383  if (x11KeyPressed && !sdlKeyPressed) {
384  SDL_SendKeyboardKey(SDL_PRESSED, scancode);
385  } else if (!x11KeyPressed && sdlKeyPressed) {
387  }
388  }
389 }
390 
391 
392 static void
393 X11_DispatchFocusIn(_THIS, SDL_WindowData *data)
394 {
395 #ifdef DEBUG_XEVENTS
396  printf("window %p: Dispatching FocusIn\n", data);
397 #endif
398  SDL_SetKeyboardFocus(data->window);
399  X11_ReconcileKeyboardState(_this);
400 #ifdef X_HAVE_UTF8_STRING
401  if (data->ic) {
402  X11_XSetICFocus(data->ic);
403  }
404 #endif
405 #ifdef SDL_USE_IME
407 #endif
408 }
409 
410 static void
411 X11_DispatchFocusOut(_THIS, SDL_WindowData *data)
412 {
413 #ifdef DEBUG_XEVENTS
414  printf("window %p: Dispatching FocusOut\n", data);
415 #endif
416  /* If another window has already processed a focus in, then don't try to
417  * remove focus here. Doing so will incorrectly remove focus from that
418  * window, and the focus lost event for this window will have already
419  * been dispatched anyway. */
420  if (data->window == SDL_GetKeyboardFocus()) {
422  }
423 #ifdef X_HAVE_UTF8_STRING
424  if (data->ic) {
425  X11_XUnsetICFocus(data->ic);
426  }
427 #endif
428 #ifdef SDL_USE_IME
430 #endif
431 }
432 
433 static void
434 X11_DispatchMapNotify(SDL_WindowData *data)
435 {
438 }
439 
440 static void
441 X11_DispatchUnmapNotify(SDL_WindowData *data)
442 {
445 }
446 
447 static void
448 InitiateWindowMove(_THIS, const SDL_WindowData *data, const SDL_Point *point)
449 {
451  SDL_Window* window = data->window;
452  Display *display = viddata->display;
453  XEvent evt;
454 
455  /* !!! FIXME: we need to regrab this if necessary when the drag is done. */
456  X11_XUngrabPointer(display, 0L);
457  X11_XFlush(display);
458 
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);
469 
470  X11_XSync(display, 0);
471 }
472 
473 static void
474 InitiateWindowResize(_THIS, const SDL_WindowData *data, const SDL_Point *point, int direction)
475 {
477  SDL_Window* window = data->window;
478  Display *display = viddata->display;
479  XEvent evt;
480 
481  if (direction < _NET_WM_MOVERESIZE_SIZE_TOPLEFT || direction > _NET_WM_MOVERESIZE_SIZE_LEFT)
482  return;
483 
484  /* !!! FIXME: we need to regrab this if necessary when the drag is done. */
485  X11_XUngrabPointer(display, 0L);
486  X11_XFlush(display);
487 
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);
498 
499  X11_XSync(display, 0);
500 }
501 
502 static SDL_bool
503 ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
504 {
505  SDL_Window *window = data->window;
506 
507  if (window->hit_test) {
508  const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
509  const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
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
515  };
516 
517  switch (rc) {
519  InitiateWindowMove(_this, data, &point);
520  return SDL_TRUE;
521 
530  InitiateWindowResize(_this, data, &point, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
531  return SDL_TRUE;
532 
533  default: return SDL_FALSE;
534  }
535  }
536 
537  return SDL_FALSE;
538 }
539 
540 static void
541 X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
542 {
543  if (latest && (latest != data->user_time)) {
544  SDL_VideoData *videodata = data->videodata;
545  Display *display = videodata->display;
546  X11_XChangeProperty(display, data->xwindow, videodata->_NET_WM_USER_TIME,
547  XA_CARDINAL, 32, PropModeReplace,
548  (const unsigned char *) &latest, 1);
549 #ifdef DEBUG_XEVENTS
550  printf("window %p: updating _NET_WM_USER_TIME to %lu\n", data, latest);
551 #endif
552  data->user_time = latest;
553  }
554 }
555 
556 static void
557 X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
558 {
559  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
560  Display *display = videodata->display;
561 
562  SDL_assert(videodata->clipboard_window != None);
563  SDL_assert(xevent->xany.window == videodata->clipboard_window);
564 
565  switch (xevent->type) {
566  /* Copy the selection from our own CUTBUFFER to the requested property */
567  case SelectionRequest: {
568  const XSelectionRequestEvent *req = &xevent->xselectionrequest;
569  XEvent sevent;
570  int seln_format;
571  unsigned long nbytes;
572  unsigned long overflow;
573  unsigned char *seln_data;
574 
575 #ifdef DEBUG_XEVENTS
576  printf("window CLIPBOARD: SelectionRequest (requestor = %ld, target = %ld)\n",
577  req->requestor, req->target);
578 #endif
579 
580  SDL_zero(sevent);
581  sevent.xany.type = SelectionNotify;
582  sevent.xselection.selection = req->selection;
583  sevent.xselection.target = None;
584  sevent.xselection.property = None; /* tell them no by default */
585  sevent.xselection.requestor = req->requestor;
586  sevent.xselection.time = req->time;
587 
588  /* !!! FIXME: We were probably storing this on the root window
589  because an SDL window might go away...? but we don't have to do
590  this now (or ever, really). */
591  if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
592  X11_GetSDLCutBufferClipboardType(display), 0, INT_MAX/4, False, req->target,
593  &sevent.xselection.target, &seln_format, &nbytes,
594  &overflow, &seln_data) == Success) {
595  /* !!! FIXME: cache atoms */
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,
600  seln_data, nbytes);
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,
607  SDL_arraysize(SupportedFormats));
608  sevent.xselection.property = req->property;
609  sevent.xselection.target = XA_TARGETS;
610  }
611  X11_XFree(seln_data);
612  }
613  X11_XSendEvent(display, req->requestor, False, 0, &sevent);
614  X11_XSync(display, False);
615  }
616  break;
617 
618  case SelectionNotify: {
619 #ifdef DEBUG_XEVENTS
620  printf("window CLIPBOARD: SelectionNotify (requestor = %ld, target = %ld)\n",
621  xevent->xselection.requestor, xevent->xselection.target);
622 #endif
623  videodata->selection_waiting = SDL_FALSE;
624  }
625  break;
626 
627  case SelectionClear: {
628  /* !!! FIXME: cache atoms */
629  Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
630 
631 #ifdef DEBUG_XEVENTS
632  printf("window CLIPBOARD: SelectionClear (requestor = %ld, target = %ld)\n",
633  xevent->xselection.requestor, xevent->xselection.target);
634 #endif
635 
636  if (xevent->xselectionclear.selection == XA_PRIMARY ||
637  (XA_CLIPBOARD != None && xevent->xselectionclear.selection == XA_CLIPBOARD)) {
639  }
640  }
641  break;
642  }
643 }
644 
645 
646 static void
647 X11_DispatchEvent(_THIS)
648 {
649  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
650  Display *display;
652  XEvent xevent;
653  int orig_event_type;
654  KeyCode orig_keycode;
655  XClientMessageEvent m;
656  int i;
657 
658  if (!videodata) {
659  return;
660  }
661  display = videodata->display;
662 
663  SDL_zero(xevent); /* valgrind fix. --ryan. */
664  X11_XNextEvent(display, &xevent);
665 
666  /* Save the original keycode for dead keys, which are filtered out by
667  the XFilterEvent() call below.
668  */
669  orig_event_type = xevent.type;
670  if (orig_event_type == KeyPress || orig_event_type == KeyRelease) {
671  orig_keycode = xevent.xkey.keycode;
672  } else {
673  orig_keycode = 0;
674  }
675 
676  /* filter events catchs XIM events and sends them to the correct handler */
677  if (X11_XFilterEvent(&xevent, None) == True) {
678 #if 0
679  printf("Filtered event type = %d display = %d window = %d\n",
680  xevent.type, xevent.xany.display, xevent.xany.window);
681 #endif
682  /* Make sure dead key press/release events are sent */
683  /* But only if we're using one of the DBus IMEs, otherwise
684  some XIM IMEs will generate duplicate events */
685  if (orig_keycode) {
686 #if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX_FRONTEND_H)
687  SDL_Scancode scancode = videodata->key_layout[orig_keycode];
688  videodata->filter_code = orig_keycode;
689  videodata->filter_time = xevent.xkey.time;
690 
691  if (orig_event_type == KeyPress) {
692  SDL_SendKeyboardKey(SDL_PRESSED, scancode);
693  } else {
695  }
696 #endif
697  }
698  return;
699  }
700 
701 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
702  if(xevent.type == GenericEvent) {
703  X11_HandleGenericEvent(videodata, &xevent);
704  return;
705  }
706 #endif
707 
708  /* Send a SDL_SYSWMEVENT if the application wants them */
710  SDL_SysWMmsg wmmsg;
711 
712  SDL_VERSION(&wmmsg.version);
713  wmmsg.subsystem = SDL_SYSWM_X11;
714  wmmsg.msg.x11.event = xevent;
715  SDL_SendSysWMEvent(&wmmsg);
716  }
717 
718 #if 0
719  printf("type = %d display = %d window = %d\n",
720  xevent.type, xevent.xany.display, xevent.xany.window);
721 #endif
722 
723  if ((videodata->clipboard_window != None) &&
724  (videodata->clipboard_window == xevent.xany.window)) {
725  X11_HandleClipboardEvent(_this, &xevent);
726  return;
727  }
728 
729  data = NULL;
730  if (videodata && videodata->windowlist) {
731  for (i = 0; i < videodata->numwindows; ++i) {
732  if ((videodata->windowlist[i] != NULL) &&
733  (videodata->windowlist[i]->xwindow == xevent.xany.window)) {
734  data = videodata->windowlist[i];
735  break;
736  }
737  }
738  }
739  if (!data) {
740  /* The window for KeymapNotify, etc events is 0 */
741  if (xevent.type == KeymapNotify) {
742  if (SDL_GetKeyboardFocus() != NULL) {
743  X11_ReconcileKeyboardState(_this);
744  }
745  } else if (xevent.type == MappingNotify) {
746  /* Has the keyboard layout changed? */
747  const int request = xevent.xmapping.request;
748 
749 #ifdef DEBUG_XEVENTS
750  printf("window %p: MappingNotify!\n", data);
751 #endif
752  if ((request == MappingKeyboard) || (request == MappingModifier)) {
753  X11_XRefreshKeyboardMapping(&xevent.xmapping);
754  }
755 
758  }
759  return;
760  }
761 
762  switch (xevent.type) {
763 
764  /* Gaining mouse coverage? */
765  case EnterNotify:{
766  SDL_Mouse *mouse = SDL_GetMouse();
767 #ifdef DEBUG_XEVENTS
768  printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
769  xevent.xcrossing.x,
770  xevent.xcrossing.y,
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");
776 #endif
777  SDL_SetMouseFocus(data->window);
778 
779  mouse->last_x = xevent.xcrossing.x;
780  mouse->last_y = xevent.xcrossing.y;
781 
782  if (!mouse->relative_mode) {
783  SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
784  }
785  }
786  break;
787  /* Losing mouse coverage? */
788  case LeaveNotify:{
789 #ifdef DEBUG_XEVENTS
790  printf("window %p: LeaveNotify! (%d,%d,%d)\n", data,
791  xevent.xcrossing.x,
792  xevent.xcrossing.y,
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");
798 #endif
799  if (!SDL_GetMouse()->relative_mode) {
800  SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
801  }
802 
803  if (xevent.xcrossing.mode != NotifyGrab &&
804  xevent.xcrossing.mode != NotifyUngrab &&
805  xevent.xcrossing.detail != NotifyInferior) {
807  }
808  }
809  break;
810 
811  /* Gaining input focus? */
812  case FocusIn:{
813  if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
814  /* Someone is handling a global hotkey, ignore it */
815 #ifdef DEBUG_XEVENTS
816  printf("window %p: FocusIn (NotifyGrab/NotifyUngrab, ignoring)\n", data);
817 #endif
818  break;
819  }
820 
821  if (xevent.xfocus.detail == NotifyInferior) {
822 #ifdef DEBUG_XEVENTS
823  printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data);
824 #endif
825  break;
826  }
827 #ifdef DEBUG_XEVENTS
828  printf("window %p: FocusIn!\n", data);
829 #endif
830  if (!videodata->last_mode_change_deadline) /* no recent mode changes */
831  {
832  data->pending_focus = PENDING_FOCUS_NONE;
833  data->pending_focus_time = 0;
834  X11_DispatchFocusIn(_this, data);
835  }
836  else
837  {
838  data->pending_focus = PENDING_FOCUS_IN;
839  data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
840  }
841  data->last_focus_event_time = SDL_GetTicks();
842  }
843  break;
844 
845  /* Losing input focus? */
846  case FocusOut:{
847  if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
848  /* Someone is handling a global hotkey, ignore it */
849 #ifdef DEBUG_XEVENTS
850  printf("window %p: FocusOut (NotifyGrab/NotifyUngrab, ignoring)\n", data);
851 #endif
852  break;
853  }
854  if (xevent.xfocus.detail == NotifyInferior) {
855  /* We still have focus if a child gets focus */
856 #ifdef DEBUG_XEVENTS
857  printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data);
858 #endif
859  break;
860  }
861 #ifdef DEBUG_XEVENTS
862  printf("window %p: FocusOut!\n", data);
863 #endif
864  if (!videodata->last_mode_change_deadline) /* no recent mode changes */
865  {
866  data->pending_focus = PENDING_FOCUS_NONE;
867  data->pending_focus_time = 0;
868  X11_DispatchFocusOut(_this, data);
869  }
870  else
871  {
872  data->pending_focus = PENDING_FOCUS_OUT;
873  data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
874  }
875  }
876  break;
877 
878  /* Key press? */
879  case KeyPress:{
880  KeyCode keycode = xevent.xkey.keycode;
881  KeySym keysym = NoSymbol;
883  Status status = 0;
884  SDL_bool handled_by_ime = SDL_FALSE;
885 
886 #ifdef DEBUG_XEVENTS
887  printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
888 #endif
889 #if 1
890  if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
891  int min_keycode, max_keycode;
892  X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
893  keysym = X11_KeyCodeToSym(_this, keycode, xevent.xkey.state >> 13);
894  fprintf(stderr,
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));
898  }
899 #endif
900  /* */
901  SDL_zero(text);
902 #ifdef X_HAVE_UTF8_STRING
903  if (data->ic) {
904  X11_Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
905  &keysym, &status);
906  } else {
907  X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
908  }
909 #else
910  X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
911 #endif
912 
913 #ifdef SDL_USE_IME
915  handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode);
916  }
917 #endif
918  if (!handled_by_ime) {
919  /* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
920  if (xevent.xkey.keycode != videodata->filter_code || xevent.xkey.time != videodata->filter_time) {
921  SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
922  }
923  if(*text) {
925  }
926  }
927 
928  X11_UpdateUserTime(data, xevent.xkey.time);
929  }
930  break;
931 
932  /* Key release? */
933  case KeyRelease:{
934  KeyCode keycode = xevent.xkey.keycode;
935 
936 #ifdef DEBUG_XEVENTS
937  printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
938 #endif
939  if (X11_KeyRepeat(display, &xevent)) {
940  /* We're about to get a repeated key down, ignore the key up */
941  break;
942  }
943  SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
944  }
945  break;
946 
947  /* Have we been iconified? */
948  case UnmapNotify:{
949 #ifdef DEBUG_XEVENTS
950  printf("window %p: UnmapNotify!\n", data);
951 #endif
952  X11_DispatchUnmapNotify(data);
953  }
954  break;
955 
956  /* Have we been restored? */
957  case MapNotify:{
958 #ifdef DEBUG_XEVENTS
959  printf("window %p: MapNotify!\n", data);
960 #endif
961  X11_DispatchMapNotify(data);
962  }
963  break;
964 
965  /* Have we been resized or moved? */
966  case ConfigureNotify:{
967 #ifdef DEBUG_XEVENTS
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);
971 #endif
972  /* Real configure notify events are relative to the parent, synthetic events are absolute. */
973  if (!xevent.xconfigure.send_event) {
974  unsigned int NumChildren;
975  Window ChildReturn, Root, Parent;
976  Window * Children;
977  /* Translate these coodinates back to relative to root */
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,
983  &ChildReturn);
984  }
985 
986  if (xevent.xconfigure.x != data->last_xconfigure.x ||
987  xevent.xconfigure.y != data->last_xconfigure.y) {
989  xevent.xconfigure.x, xevent.xconfigure.y);
990 #ifdef SDL_USE_IME
992  /* Update IME candidate list position */
994  }
995 #endif
996  }
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);
1002  }
1003  data->last_xconfigure = xevent.xconfigure;
1004  }
1005  break;
1006 
1007  /* Have we been requested to quit (or another client message?) */
1008  case ClientMessage:{
1009 
1010  static int xdnd_version=0;
1011 
1012  if (xevent.xclient.message_type == videodata->XdndEnter) {
1013 
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);
1021 #endif
1022 
1023  if (use_list) {
1024  /* fetch conversion targets */
1025  SDL_x11Prop p;
1026  X11_ReadProperty(&p, display, data->xdnd_source, videodata->XdndTypeList);
1027  /* pick one */
1028  data->xdnd_req = X11_PickTarget(display, (Atom*)p.data, p.count);
1029  X11_XFree(p.data);
1030  } else {
1031  /* pick from list of three */
1032  data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]);
1033  }
1034  }
1035  else if (xevent.xclient.message_type == videodata->XdndPosition) {
1036 
1037 #ifdef DEBUG_XEVENTS
1038  Atom act= videodata->XdndActionCopy;
1039  if(xdnd_version >= 2) {
1040  act = xevent.xclient.data.l[4];
1041  }
1042  printf("Action requested by user is : %s\n", X11_XGetAtomName(display , act));
1043 #endif
1044 
1045 
1046  /* reply with status */
1047  memset(&m, 0, sizeof(XClientMessageEvent));
1048  m.type = ClientMessage;
1049  m.display = xevent.xclient.display;
1050  m.window = xevent.xclient.data.l[0];
1051  m.message_type = videodata->XdndStatus;
1052  m.format=32;
1053  m.data.l[0] = data->xwindow;
1054  m.data.l[1] = (data->xdnd_req != None);
1055  m.data.l[2] = 0; /* specify an empty rectangle */
1056  m.data.l[3] = 0;
1057  m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */
1058 
1059  X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
1060  X11_XFlush(display);
1061  }
1062  else if(xevent.xclient.message_type == videodata->XdndDrop) {
1063  if (data->xdnd_req == None) {
1064  /* say again - not interested! */
1065  memset(&m, 0, sizeof(XClientMessageEvent));
1066  m.type = ClientMessage;
1067  m.display = xevent.xclient.display;
1068  m.window = xevent.xclient.data.l[0];
1069  m.message_type = videodata->XdndFinished;
1070  m.format=32;
1071  m.data.l[0] = data->xwindow;
1072  m.data.l[1] = 0;
1073  m.data.l[2] = None; /* fail! */
1074  X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
1075  } else {
1076  /* convert */
1077  if(xdnd_version >= 1) {
1078  X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
1079  } else {
1080  X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
1081  }
1082  }
1083  }
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);
1088 
1089 #ifdef DEBUG_XEVENTS
1090  printf("window %p: _NET_WM_PING\n", data);
1091 #endif
1092  xevent.xclient.window = root;
1093  X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
1094  break;
1095  }
1096 
1097  else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
1098  (xevent.xclient.format == 32) &&
1099  (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
1100 
1101 #ifdef DEBUG_XEVENTS
1102  printf("window %p: WM_DELETE_WINDOW\n", data);
1103 #endif
1105  break;
1106  }
1107  else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
1108  (xevent.xclient.format == 32) &&
1109  (xevent.xclient.data.l[0] == videodata->WM_TAKE_FOCUS)) {
1110 
1111 #ifdef DEBUG_XEVENTS
1112  printf("window %p: WM_TAKE_FOCUS\n", data);
1113 #endif
1115  break;
1116  }
1117  }
1118  break;
1119 
1120  /* Do we need to refresh ourselves? */
1121  case Expose:{
1122 #ifdef DEBUG_XEVENTS
1123  printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
1124 #endif
1126  }
1127  break;
1128 
1129  case MotionNotify:{
1130  SDL_Mouse *mouse = SDL_GetMouse();
1131  if(!mouse->relative_mode || mouse->relative_mode_warp) {
1132 #ifdef DEBUG_MOTION
1133  printf("window %p: X11 motion: %d,%d\n", data, xevent.xmotion.x, xevent.xmotion.y);
1134 #endif
1135 
1136  SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
1137  }
1138  }
1139  break;
1140 
1141  case ButtonPress:{
1142  int xticks = 0, yticks = 0;
1143 #ifdef DEBUG_XEVENTS
1144  printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent.xbutton.button);
1145 #endif
1146  if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
1147  SDL_SendMouseWheel(data->window, 0, (float) xticks, (float) yticks, SDL_MOUSEWHEEL_NORMAL);
1148  } else {
1149  SDL_bool ignore_click = SDL_FALSE;
1150  int button = xevent.xbutton.button;
1151  if(button == Button1) {
1152  if (ProcessHitTest(_this, data, &xevent)) {
1154  break; /* don't pass this event on to app. */
1155  }
1156  }
1157  else if(button > 7) {
1158  /* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
1159  => subtract (8-SDL_BUTTON_X1) to get value SDL expects */
1160  button -= (8-SDL_BUTTON_X1);
1161  }
1162  if (data->last_focus_event_time) {
1163  const int X11_FOCUS_CLICK_TIMEOUT = 10;
1164  if (!SDL_TICKS_PASSED(SDL_GetTicks(), data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
1166  }
1167  data->last_focus_event_time = 0;
1168  }
1169  if (!ignore_click) {
1171  }
1172  }
1173  X11_UpdateUserTime(data, xevent.xbutton.time);
1174  }
1175  break;
1176 
1177  case ButtonRelease:{
1178  int button = xevent.xbutton.button;
1179  /* The X server sends a Release event for each Press for wheels. Ignore them. */
1180  int xticks = 0, yticks = 0;
1181 #ifdef DEBUG_XEVENTS
1182  printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent.xbutton.button);
1183 #endif
1184  if (!X11_IsWheelEvent(display, &xevent, &xticks, &yticks)) {
1185  if (button > 7) {
1186  /* see explanation at case ButtonPress */
1187  button -= (8-SDL_BUTTON_X1);
1188  }
1190  }
1191  }
1192  break;
1193 
1194  case PropertyNotify:{
1195 #ifdef DEBUG_XEVENTS
1196  unsigned char *propdata;
1197  int status, real_format;
1198  Atom real_type;
1199  unsigned long items_read, items_left;
1200 
1201  char *name = X11_XGetAtomName(display, xevent.xproperty.atom);
1202  if (name) {
1203  printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent.xproperty.time);
1204  X11_XFree(name);
1205  }
1206 
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;
1211 
1212  printf("{");
1213  for (i = 0; i < items_read; i++) {
1214  printf(" %d", values[i]);
1215  }
1216  printf(" }\n");
1217  } else if (real_type == XA_CARDINAL) {
1218  if (real_format == 32) {
1219  Uint32 *values = (Uint32 *)propdata;
1220 
1221  printf("{");
1222  for (i = 0; i < items_read; i++) {
1223  printf(" %d", values[i]);
1224  }
1225  printf(" }\n");
1226  } else if (real_format == 16) {
1227  Uint16 *values = (Uint16 *)propdata;
1228 
1229  printf("{");
1230  for (i = 0; i < items_read; i++) {
1231  printf(" %d", values[i]);
1232  }
1233  printf(" }\n");
1234  } else if (real_format == 8) {
1235  Uint8 *values = (Uint8 *)propdata;
1236 
1237  printf("{");
1238  for (i = 0; i < items_read; i++) {
1239  printf(" %d", values[i]);
1240  }
1241  printf(" }\n");
1242  }
1243  } else if (real_type == XA_STRING ||
1244  real_type == videodata->UTF8_STRING) {
1245  printf("{ \"%s\" }\n", propdata);
1246  } else if (real_type == XA_ATOM) {
1247  Atom *atoms = (Atom *)propdata;
1248 
1249  printf("{");
1250  for (i = 0; i < items_read; i++) {
1251  char *atomname = X11_XGetAtomName(display, atoms[i]);
1252  if (atomname) {
1253  printf(" %s", atomname);
1254  X11_XFree(atomname);
1255  }
1256  }
1257  printf(" }\n");
1258  } else {
1259  char *atomname = X11_XGetAtomName(display, real_type);
1260  printf("Unknown type: %ld (%s)\n", real_type, atomname ? atomname : "UNKNOWN");
1261  if (atomname) {
1262  X11_XFree(atomname);
1263  }
1264  }
1265  }
1266  if (status == Success) {
1267  X11_XFree(propdata);
1268  }
1269 #endif /* DEBUG_XEVENTS */
1270 
1271  /* Take advantage of this moment to make sure user_time has a
1272  valid timestamp from the X server, so if we later try to
1273  raise/restore this window, _NET_ACTIVE_WINDOW can have a
1274  non-zero timestamp, even if there's never been a mouse or
1275  key press to this window so far. Note that we don't try to
1276  set _NET_WM_USER_TIME here, though. That's only for legit
1277  user interaction with the window. */
1278  if (!data->user_time) {
1279  data->user_time = xevent.xproperty.time;
1280  }
1281 
1282  if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
1283  /* Get the new state from the window manager.
1284  Compositing window managers can alter visibility of windows
1285  without ever mapping / unmapping them, so we handle that here,
1286  because they use the NETWM protocol to notify us of changes.
1287  */
1288  const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
1289  const Uint32 changed = flags ^ data->window->flags;
1290 
1291  if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) {
1292  if (flags & SDL_WINDOW_HIDDEN) {
1293  X11_DispatchUnmapNotify(data);
1294  } else {
1295  X11_DispatchMapNotify(data);
1296  }
1297  }
1298 
1299  if (changed & SDL_WINDOW_MAXIMIZED) {
1300  if (flags & SDL_WINDOW_MAXIMIZED) {
1302  } else {
1304  }
1305  }
1306  } else if (xevent.xproperty.atom == videodata->XKLAVIER_STATE) {
1307  /* Hack for Ubuntu 12.04 (etc) that doesn't send MappingNotify
1308  events when the keyboard layout changes (for example,
1309  changing from English to French on the menubar's keyboard
1310  icon). Since it changes the XKLAVIER_STATE property, we
1311  notice and reinit our keymap here. This might not be the
1312  right approach, but it seems to work. */
1315  } else if (xevent.xproperty.atom == videodata->_NET_FRAME_EXTENTS) {
1316  Atom type;
1317  int format;
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];
1326  }
1327  X11_XFree(property);
1328 
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);
1331  #endif
1332  }
1333  }
1334  }
1335  break;
1336 
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);
1342 #endif
1343  if (target == data->xdnd_req) {
1344  /* read data */
1345  SDL_x11Prop p;
1346  X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
1347 
1348  if (p.format == 8) {
1349  /* !!! FIXME: don't use strtok here. It's not reentrant and not in SDL_stdinc. */
1350  char* name = X11_XGetAtomName(display, target);
1351  char *token = strtok((char *) p.data, "\r\n");
1352  while (token != NULL) {
1353  if (SDL_strcmp("text/plain", name)==0) {
1354  SDL_SendDropText(data->window, token);
1355  } else if (SDL_strcmp("text/uri-list", name)==0) {
1356  char *fn = X11_URIToLocal(token);
1357  if (fn) {
1358  SDL_SendDropFile(data->window, fn);
1359  }
1360  }
1361  token = strtok(NULL, "\r\n");
1362  }
1363  SDL_SendDropComplete(data->window);
1364  }
1365  X11_XFree(p.data);
1366 
1367  /* send reply */
1368  SDL_memset(&m, 0, sizeof(XClientMessageEvent));
1369  m.type = ClientMessage;
1370  m.display = display;
1371  m.window = data->xdnd_source;
1372  m.message_type = videodata->XdndFinished;
1373  m.format = 32;
1374  m.data.l[0] = data->xwindow;
1375  m.data.l[1] = 1;
1376  m.data.l[2] = videodata->XdndActionCopy;
1377  X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent*)&m);
1378 
1379  X11_XSync(display, False);
1380  }
1381  }
1382  break;
1383 
1384  default:{
1385 #ifdef DEBUG_XEVENTS
1386  printf("window %p: Unhandled event %d\n", data, xevent.type);
1387 #endif
1388  }
1389  break;
1390  }
1391 }
1392 
1393 static void
1394 X11_HandleFocusChanges(_THIS)
1395 {
1396  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
1397  int i;
1398 
1399  if (videodata && videodata->windowlist) {
1400  for (i = 0; i < videodata->numwindows; ++i) {
1401  SDL_WindowData *data = videodata->windowlist[i];
1402  if (data && data->pending_focus != PENDING_FOCUS_NONE) {
1403  Uint32 now = SDL_GetTicks();
1404  if (SDL_TICKS_PASSED(now, data->pending_focus_time)) {
1405  if (data->pending_focus == PENDING_FOCUS_IN) {
1406  X11_DispatchFocusIn(_this, data);
1407  } else {
1408  X11_DispatchFocusOut(_this, data);
1409  }
1410  data->pending_focus = PENDING_FOCUS_NONE;
1411  }
1412  }
1413  }
1414  }
1415 }
1416 /* Ack! X11_XPending() actually performs a blocking read if no events available */
1417 static int
1418 X11_Pending(Display * display)
1419 {
1420  /* Flush the display connection and look to see if events are queued */
1421  X11_XFlush(display);
1422  if (X11_XEventsQueued(display, QueuedAlready)) {
1423  return (1);
1424  }
1425 
1426  /* More drastic measures are required -- see if X is ready to talk */
1427  if (SDL_IOReady(ConnectionNumber(display), SDL_FALSE, 0)) {
1428  return (X11_XPending(display));
1429  }
1430 
1431  /* Oh well, nothing is ready .. */
1432  return (0);
1433 }
1434 
1435 void
1437 {
1439 
1440  if (data->last_mode_change_deadline) {
1441  if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) {
1442  data->last_mode_change_deadline = 0; /* assume we're done. */
1443  }
1444  }
1445 
1446  /* Update activity every 30 seconds to prevent screensaver */
1447  if (_this->suspend_screensaver) {
1448  const Uint32 now = SDL_GetTicks();
1449  if (!data->screensaver_activity ||
1450  SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
1451  X11_XResetScreenSaver(data->display);
1452 
1453 #if SDL_USE_LIBDBUS
1454  SDL_DBus_ScreensaverTickle();
1455 #endif
1456 
1457  data->screensaver_activity = now;
1458  }
1459  }
1460 
1461  /* Keep processing pending events */
1462  while (X11_Pending(data->display)) {
1463  X11_DispatchEvent(_this);
1464  }
1465 
1466 #ifdef SDL_USE_IME
1469  }
1470 #endif
1471 
1472  /* FIXME: Only need to do this when there are pending focus changes */
1473  X11_HandleFocusChanges(_this);
1474 }
1475 
1476 
1477 void
1479 {
1480 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
1482  int dummy;
1483  int major_version, minor_version;
1484 #endif /* SDL_VIDEO_DRIVER_X11_XSCRNSAVER */
1485 
1486 #if SDL_USE_LIBDBUS
1487  if (SDL_DBus_ScreensaverInhibit(_this->suspend_screensaver)) {
1488  return;
1489  }
1490 
1491  if (_this->suspend_screensaver) {
1492  SDL_DBus_ScreensaverTickle();
1493  }
1494 #endif
1495 
1496 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
1497  if (SDL_X11_HAVE_XSS) {
1498  /* X11_XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
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)) {
1503  return;
1504  }
1505 
1506  X11_XScreenSaverSuspend(data->display, _this->suspend_screensaver);
1507  X11_XResetScreenSaver(data->display);
1508  }
1509 #endif
1510 }
1511 
1512 #endif /* SDL_VIDEO_DRIVER_X11 */
1513 
1514 /* vi: set ts=4 sw=4 expandtab: */
SDL_HITTEST_DRAGGABLE
@ SDL_HITTEST_DRAGGABLE
Definition: SDL_video.h:1023
SDL_GetMouse
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_SysWMmsg
Definition: SDL_syswm.h:138
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_Point::x
int x
Definition: SDL_rect.h:50
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
SDL_VideoData::selection_waiting
SDL_bool selection_waiting
Definition: SDL_x11video.h:127
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_SendSysWMEvent
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:979
SDL_SysWMmsg::subsystem
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:141
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:381
SDL_VideoData::_NET_WM_PING
Atom _NET_WM_PING
Definition: SDL_x11video.h:109
SDL_x11video.h
target
GLenum target
Definition: SDL_opengl_glext.h:1551
mask
GLenum GLint GLuint mask
Definition: SDL_opengl_glext.h:657
SDL_VideoData::XdndEnter
Atom XdndEnter
Definition: SDL_x11video.h:116
NULL
#define NULL
Definition: begin_code.h:167
SDL_timer.h
SDL_WINDOWEVENT_CLOSE
@ SDL_WINDOWEVENT_CLOSE
Definition: SDL_video.h:167
SDL_VERSION
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
PENDING_FOCUS_TIME
#define PENDING_FOCUS_TIME
Definition: SDL_x11window.h:30
SDL_SysWMmsg::version
SDL_version version
Definition: SDL_syswm.h:140
SDL_WindowData
Definition: SDL_androidwindow.h:38
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
KMOD_NUM
@ KMOD_NUM
Definition: SDL_keycode.h:336
SDL_WINDOW_FULLSCREEN
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
SDL_WINDOWEVENT_RESIZED
@ SDL_WINDOWEVENT_RESIZED
Definition: SDL_video.h:155
SDL_Scancode
SDL_Scancode
The SDL keyboard scancode representation.
Definition: SDL_scancode.h:43
SDL_VideoData::WM_TAKE_FOCUS
Atom WM_TAKE_FOCUS
Definition: SDL_x11video.h:94
SDL_VideoData::last_mode_change_deadline
Uint32 last_mode_change_deadline
Definition: SDL_x11video.h:131
SDL_SetKeyboardFocus
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
SDL_SysWMmsg::msg
union SDL_SysWMmsg::@15 msg
SDL_ENABLE
#define SDL_ENABLE
Definition: SDL_events.h:759
SDL_VideoData::_NET_WM_USER_TIME
Atom _NET_WM_USER_TIME
Definition: SDL_x11video.h:111
SDL_HITTEST_RESIZE_TOPLEFT
@ SDL_HITTEST_RESIZE_TOPLEFT
Definition: SDL_video.h:1024
SDL_VideoData::WM_PROTOCOLS
Atom WM_PROTOCOLS
Definition: SDL_x11video.h:92
PENDING_FOCUS_IN
@ PENDING_FOCUS_IN
Definition: SDL_x11window.h:39
SDL_WINDOW_MAXIMIZED
@ SDL_WINDOW_MAXIMIZED
Definition: SDL_video.h:107
SDL_WINDOWEVENT_MOVED
@ SDL_WINDOWEVENT_MOVED
Definition: SDL_video.h:153
SDL_VideoData::filter_time
Time filter_time
Definition: SDL_x11video.h:142
SDL_VideoData::clipboard_window
Window clipboard_window
Definition: SDL_x11video.h:86
SDL_x11touch.h
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_VideoData::windowlist
SDL_WindowData ** windowlist
Definition: SDL_x11video.h:83
SDL_SetMouseFocus
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:211
SDL_SendKeyboardKey
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:679
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_BUTTON_X1
#define SDL_BUTTON_X1
Definition: SDL_mouse.h:285
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_VideoData::filter_code
KeyCode filter_code
Definition: SDL_x11video.h:141
SDL_GetKeyboardFocus
#define SDL_GetKeyboardFocus
Definition: SDL_dynapi_overrides.h:216
n
GLdouble n
Definition: SDL_opengl_glext.h:1952
PENDING_FOCUS_NONE
@ PENDING_FOCUS_NONE
Definition: SDL_x11window.h:38
SDL_SendClipboardUpdate
int SDL_SendClipboardUpdate(void)
Definition: SDL_clipboardevents.c:31
SDL_IME_ProcessKeyEvent
SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
Definition: SDL_ime.c:130
SDL_WINDOWEVENT_SHOWN
@ SDL_WINDOWEVENT_SHOWN
Definition: SDL_video.h:149
values
GLenum GLsizei GLsizei GLint * values
Definition: SDL_opengl_glext.h:1486
SDL_SendKeyboardText
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:789
SDL_VideoData::XdndStatus
Atom XdndStatus
Definition: SDL_x11video.h:118
SDL_VideoData::PRIMARY
Atom PRIMARY
Definition: SDL_x11video.h:115
SDL_PRESSED
#define SDL_PRESSED
Definition: SDL_events.h:50
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
buf
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: SDL_opengl_glext.h:2480
SDL_HITTEST_RESIZE_BOTTOMRIGHT
@ SDL_HITTEST_RESIZE_BOTTOMRIGHT
Definition: SDL_video.h:1028
PENDING_FOCUS_OUT
@ PENDING_FOCUS_OUT
Definition: SDL_x11window.h:40
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_ToggleModState
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
Definition: SDL_keyboard.c:865
SDL_VideoData::numwindows
int numwindows
Definition: SDL_x11video.h:82
SDL_Mouse::relative_mode
SDL_bool relative_mode
Definition: SDL_mouse_c.h:87
SDL_WindowData::xwindow
Window xwindow
Definition: SDL_x11window.h:46
SDL_HITTEST_RESIZE_TOPRIGHT
@ SDL_HITTEST_RESIZE_TOPRIGHT
Definition: SDL_video.h:1026
p
GLfloat GLfloat p
Definition: SDL_opengl_glext.h:11090
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_HitTestResult
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:1020
X11_UpdateKeymap
void X11_UpdateKeymap(_THIS)
SDL_VideoData::XdndSelection
Atom XdndSelection
Definition: SDL_x11video.h:123
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_IOReady
int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
Definition: SDL_poll.c:38
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_TEXTINPUT
@ SDL_TEXTINPUT
Definition: SDL_events.h:99
SDL_VideoData::XdndPosition
Atom XdndPosition
Definition: SDL_x11video.h:117
SDL_VideoData::XKLAVIER_STATE
Atom XKLAVIER_STATE
Definition: SDL_x11video.h:124
SDL_HITTEST_RESIZE_BOTTOM
@ SDL_HITTEST_RESIZE_BOTTOM
Definition: SDL_video.h:1029
SDL_SYSWM_X11
@ SDL_SYSWM_X11
Definition: SDL_syswm.h:123
SDL_GetKeyboardState
#define SDL_GetKeyboardState
Definition: SDL_dynapi_overrides.h:217
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_SendDropFile
int SDL_SendDropFile(SDL_Window *window, const char *file)
Definition: SDL_dropevents.c:80
X11_KeyCodeToSym
KeySym X11_KeyCodeToSym(_THIS, KeyCode, unsigned char group)
SDL_HITTEST_RESIZE_LEFT
@ SDL_HITTEST_RESIZE_LEFT
Definition: SDL_video.h:1031
SDL_SendMouseMotion
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:301
SDL_WINDOWEVENT_EXPOSED
@ SDL_WINDOWEVENT_EXPOSED
Definition: SDL_video.h:151
SDL_IME_SetFocus
void SDL_IME_SetFocus(SDL_bool focused)
Definition: SDL_ime.c:116
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
SDL_assert.h
SDL_GetTicks
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_WINDOWEVENT_HIT_TEST
@ SDL_WINDOWEVENT_HIT_TEST
Definition: SDL_video.h:169
text
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
SDL_Mouse
Definition: SDL_mouse_c.h:43
SDL_SendDropComplete
int SDL_SendDropComplete(SDL_Window *window)
Definition: SDL_dropevents.c:92
SDL_Mouse::relative_mode_warp
SDL_bool relative_mode_warp
Definition: SDL_mouse_c.h:88
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_WINDOWEVENT_MINIMIZED
@ SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:159
SDL_WINDOWEVENT_TAKE_FOCUS
@ SDL_WINDOWEVENT_TAKE_FOCUS
Definition: SDL_video.h:168
SDL_VideoData::key_layout
void * key_layout
Definition: SDL_cocoavideo.h:104
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_SCANCODE_UNKNOWN
@ SDL_SCANCODE_UNKNOWN
Definition: SDL_scancode.h:45
SDL_SendMouseWheel
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:611
SDL_VideoData::XdndTypeList
Atom XdndTypeList
Definition: SDL_x11video.h:119
SDL_HITTEST_RESIZE_RIGHT
@ SDL_HITTEST_RESIZE_RIGHT
Definition: SDL_video.h:1027
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
X11_SuspendScreenSaver
void X11_SuspendScreenSaver(_THIS)
SDL_Mouse::last_y
int last_y
Definition: SDL_mouse_c.h:82
SDL_VideoData::display
struct wl_display * display
Definition: SDL_waylandvideo.h:50
m
const GLfloat * m
Definition: SDL_opengl_glext.h:6092
X11_GetNetWMState
Uint32 X11_GetNetWMState(_THIS, Window xwindow)
SDL_SendDropText
int SDL_SendDropText(SDL_Window *window, const char *text)
Definition: SDL_dropevents.c:86
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
memset
#define memset
Definition: SDL_malloc.c:627
SDL_WINDOW_HIDDEN
@ SDL_WINDOW_HIDDEN
Definition: SDL_video.h:103
SDL_Mouse::last_x
int last_x
Definition: SDL_mouse_c.h:82
SDL_SysWMmsg::x11
struct SDL_SysWMmsg::@15::@16 x11
SDL_TEXTINPUTEVENT_TEXT_SIZE
#define SDL_TEXTINPUTEVENT_TEXT_SIZE
Definition: SDL_events.h:238
SDL_Point
The structure that defines a point (integer)
Definition: SDL_rect.h:48
INT_MAX
#define INT_MAX
Definition: SDL_wave.c:31
SDL_VideoData::XdndFinished
Atom XdndFinished
Definition: SDL_x11video.h:122
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:50
SDL_x11xinput2.h
SDL_hints.h
SDL_VideoData::UTF8_STRING
Atom UTF8_STRING
Definition: SDL_x11video.h:114
SDL_SCANCODE_NUMLOCKCLEAR
@ SDL_SCANCODE_NUMLOCKCLEAR
Definition: SDL_scancode.h:181
SDL_IME_UpdateTextRect
void SDL_IME_UpdateTextRect(SDL_Rect *rect)
Definition: SDL_ime.c:139
SDL_SendKeymapChangedEvent
int SDL_SendKeymapChangedEvent(void)
Definition: SDL_events.c:996
SDL_SendWindowEvent
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
Definition: SDL_windowevents.c:74
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:393
SDL_SYSWMEVENT
@ SDL_SYSWMEVENT
Definition: SDL_events.h:93
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
X11_HandleXinput2Event
int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie)
SDL_MOUSEWHEEL_NORMAL
@ SDL_MOUSEWHEEL_NORMAL
Definition: SDL_mouse.h:68
SDL_WINDOWEVENT_HIDDEN
@ SDL_WINDOWEVENT_HIDDEN
Definition: SDL_video.h:150
SDL_WINDOWEVENT_RESTORED
@ SDL_WINDOWEVENT_RESTORED
Definition: SDL_video.h:161
SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
Allow mouse click events when clicking to focus an SDL window.
Definition: SDL_hints.h:305
XGenericEventCookie
struct XGenericEventCookie XGenericEventCookie
Definition: SDL_x11xinput2.h:30
SDL_VideoData::_NET_FRAME_EXTENTS
Atom _NET_FRAME_EXTENTS
Definition: SDL_x11video.h:113
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:417
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
SDL_IME_PumpEvents
void SDL_IME_PumpEvents()
Definition: SDL_ime.c:146
X11_PumpEvents
void X11_PumpEvents(_THIS)
SDL_VideoData::WM_DELETE_WINDOW
Atom WM_DELETE_WINDOW
Definition: SDL_x11video.h:93
SDL_VideoData::XdndActionCopy
Atom XdndActionCopy
Definition: SDL_x11video.h:120
SDL_HITTEST_RESIZE_TOP
@ SDL_HITTEST_RESIZE_TOP
Definition: SDL_video.h:1025
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
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:50
KMOD_CAPS
@ KMOD_CAPS
Definition: SDL_keycode.h:337
SDL_VideoDevice::suspend_screensaver
SDL_bool suspend_screensaver
Definition: SDL_sysvideo.h:314
button
SDL_Texture * button
Definition: testgamecontroller.c:67
SDL_VideoData::XdndDrop
Atom XdndDrop
Definition: SDL_x11video.h:121
SDL_HITTEST_RESIZE_BOTTOMLEFT
@ SDL_HITTEST_RESIZE_BOTTOMLEFT
Definition: SDL_video.h:1030
SDL_Point::y
int y
Definition: SDL_rect.h:51
SDL_SendMouseButton
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:605
SDL_WINDOWEVENT_MAXIMIZED
@ SDL_WINDOWEVENT_MAXIMIZED
Definition: SDL_video.h:160
X11_GetSDLCutBufferClipboardType
Atom X11_GetSDLCutBufferClipboardType(Display *display)
SDL_VideoData
Definition: SDL_androidvideo.h:36
d
const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char const char const SDL_SCANF_FORMAT_STRING 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:117
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_syswm.h
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179