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