zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_x11events.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 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_config.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_x11video.h"
33 #include "SDL_x11touch.h"
34 #include "SDL_x11xinput2.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_timer.h"
40 #include "SDL_syswm.h"
41 
42 #include <stdio.h>
43 
44 typedef struct {
45  unsigned char *data;
46  int format, count;
47  Atom type;
48 } SDL_x11Prop;
49 
50 /* Reads property
51  Must call XFree on results
52  */
53 static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop)
54 {
55  unsigned char *ret=NULL;
56  Atom type;
57  int fmt;
58  unsigned long count;
59  unsigned long bytes_left;
60  int bytes_fetch = 0;
61 
62  do {
63  if (ret != 0) XFree(ret);
64  XGetWindowProperty(disp, w, prop, 0, bytes_fetch, False, AnyPropertyType, &type, &fmt, &count, &bytes_left, &ret);
65  bytes_fetch += bytes_left;
66  } while (bytes_left != 0);
67 
68  p->data=ret;
69  p->format=fmt;
70  p->count=count;
71  p->type=type;
72 }
73 
74 /* Find text-uri-list in a list of targets and return it's atom
75  if available, else return None */
76 static Atom X11_PickTarget(Display *disp, Atom list[], int list_count)
77 {
78  Atom request = None;
79  char *name;
80  int i;
81  for (i=0; i < list_count && request == None; i++) {
82  name = XGetAtomName(disp, list[i]);
83  if (strcmp("text/uri-list", name)==0) request = list[i];
84  XFree(name);
85  }
86  return request;
87 }
88 
89 /* Wrapper for X11_PickTarget for a maximum of three targets, a special
90  case in the Xdnd protocol */
91 static Atom X11_PickTargetFromAtoms(Display *disp, Atom a0, Atom a1, Atom a2)
92 {
93  int count=0;
94  Atom atom[3];
95  if (a0 != None) atom[count++] = a0;
96  if (a1 != None) atom[count++] = a1;
97  if (a2 != None) atom[count++] = a2;
98  return X11_PickTarget(disp, atom, count);
99 }
100 /* #define DEBUG_XEVENTS */
101 
102 struct KeyRepeatCheckData
103 {
104  XEvent *event;
105  SDL_bool found;
106 };
107 
108 static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
109  XPointer arg)
110 {
111  struct KeyRepeatCheckData *d = (struct KeyRepeatCheckData *) arg;
112  if (chkev->type == KeyPress &&
113  chkev->xkey.keycode == d->event->xkey.keycode &&
114  chkev->xkey.time - d->event->xkey.time < 2)
115  d->found = SDL_TRUE;
116  return False;
117 }
118 
119 /* Check to see if this is a repeated key.
120  (idea shamelessly lifted from GII -- thanks guys! :)
121  */
122 static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
123 {
124  XEvent dummyev;
125  struct KeyRepeatCheckData d;
126  d.event = event;
127  d.found = SDL_FALSE;
128  if (XPending(display))
129  XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent,
130  (XPointer) &d);
131  return d.found;
132 }
133 
134 static Bool X11_IsWheelCheckIfEvent(Display *display, XEvent *chkev,
135  XPointer arg)
136 {
137  XEvent *event = (XEvent *) arg;
138  /* we only handle buttons 4 and 5 - false positive avoidance */
139  if (chkev->type == ButtonRelease &&
140  (event->xbutton.button == Button4 || event->xbutton.button == Button5) &&
141  chkev->xbutton.button == event->xbutton.button &&
142  chkev->xbutton.time == event->xbutton.time)
143  return True;
144  return False;
145 }
146 
147 static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int * ticks)
148 {
149  XEvent relevent;
150  if (XPending(display)) {
151  /* according to the xlib docs, no specific mouse wheel events exist.
152  however, mouse wheel events trigger a button press and a button release
153  immediately. thus, checking if the same button was released at the same
154  time as it was pressed, should be an adequate hack to derive a mouse
155  wheel event.
156  However, there is broken and unusual hardware out there...
157  - False positive: a button for which a release event is
158  generated (or synthesised) immediately.
159  - False negative: a wheel which, when rolled, doesn't have
160  a release event generated immediately. */
161  if (XCheckIfEvent(display, &relevent, X11_IsWheelCheckIfEvent,
162  (XPointer) event)) {
163 
164  /* by default, X11 only knows 5 buttons. on most 3 button + wheel mouse,
165  Button4 maps to wheel up, Button5 maps to wheel down. */
166  if (event->xbutton.button == Button4) {
167  *ticks = 1;
168  }
169  else if (event->xbutton.button == Button5) {
170  *ticks = -1;
171  }
172  return SDL_TRUE;
173  }
174  }
175  return SDL_FALSE;
176 }
177 
178 /* Convert URI to local filename
179  return filename if possible, else NULL
180 */
181 static char* X11_URIToLocal(char* uri) {
182  char *file = NULL;
183  SDL_bool local;
184 
185  if (memcmp(uri,"file:/",6) == 0) uri += 6; /* local file? */
186  else if (strstr(uri,":/") != NULL) return file; /* wrong scheme */
187 
188  local = uri[0] != '/' || ( uri[0] != '\0' && uri[1] == '/' );
189 
190  /* got a hostname? */
191  if ( !local && uri[0] == '/' && uri[2] != '/' ) {
192  char* hostname_end = strchr( uri+1, '/' );
193  if ( hostname_end != NULL ) {
194  char hostname[ 257 ];
195  if ( gethostname( hostname, 255 ) == 0 ) {
196  hostname[ 256 ] = '\0';
197  if ( memcmp( uri+1, hostname, hostname_end - ( uri+1 )) == 0 ) {
198  uri = hostname_end + 1;
199  local = SDL_TRUE;
200  }
201  }
202  }
203  }
204  if ( local ) {
205  file = uri;
206  if ( uri[1] == '/' ) {
207  file++;
208  } else {
209  file--;
210  }
211  }
212  return file;
213 }
214 
215 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
216 static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event)
217 {
218  /* event is a union, so cookie == &event, but this is type safe. */
219  XGenericEventCookie *cookie = &event.xcookie;
220  if (XGetEventData(videodata->display, cookie)) {
221  X11_HandleXinput2Event(videodata, cookie);
222  XFreeEventData(videodata->display, cookie);
223  }
224 }
225 #endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
226 
227 
228 static void
229 X11_DispatchFocusIn(SDL_WindowData *data)
230 {
231 #ifdef DEBUG_XEVENTS
232  printf("window %p: Dispatching FocusIn\n", data);
233 #endif
235 #ifdef X_HAVE_UTF8_STRING
236  if (data->ic) {
237  XSetICFocus(data->ic);
238  }
239 #endif
240 }
241 
242 static void
243 X11_DispatchFocusOut(SDL_WindowData *data)
244 {
245 #ifdef DEBUG_XEVENTS
246  printf("window %p: Dispatching FocusOut\n", data);
247 #endif
249 #ifdef X_HAVE_UTF8_STRING
250  if (data->ic) {
251  XUnsetICFocus(data->ic);
252  }
253 #endif
254 }
255 
256 static void
257 X11_DispatchMapNotify(SDL_WindowData *data)
258 {
261 }
262 
263 static void
264 X11_DispatchUnmapNotify(SDL_WindowData *data)
265 {
268 }
269 
270 static void
271 X11_DispatchEvent(_THIS)
272 {
273  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
274  Display *display = videodata->display;
275  SDL_WindowData *data;
276  XEvent xevent;
277  int i;
278  XClientMessageEvent m;
279 
280  SDL_zero(xevent); /* valgrind fix. --ryan. */
281  XNextEvent(display, &xevent);
282 
283  /* filter events catchs XIM events and sends them to the correct
284  handler */
285  if (XFilterEvent(&xevent, None) == True) {
286 #if 0
287  printf("Filtered event type = %d display = %d window = %d\n",
288  xevent.type, xevent.xany.display, xevent.xany.window);
289 #endif
290  return;
291  }
292 
293  /* Send a SDL_SYSWMEVENT if the application wants them */
295  SDL_SysWMmsg wmmsg;
296 
297  SDL_VERSION(&wmmsg.version);
298  wmmsg.subsystem = SDL_SYSWM_X11;
299  wmmsg.msg.x11.event = xevent;
300  SDL_SendSysWMEvent(&wmmsg);
301  }
302 
303 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
304  if(xevent.type == GenericEvent) {
305  X11_HandleGenericEvent(videodata,xevent);
306  return;
307  }
308 #endif
309 
310 #if 0
311  printf("type = %d display = %d window = %d\n",
312  xevent.type, xevent.xany.display, xevent.xany.window);
313 #endif
314 
315  data = NULL;
316  if (videodata && videodata->windowlist) {
317  for (i = 0; i < videodata->numwindows; ++i) {
318  if ((videodata->windowlist[i] != NULL) &&
319  (videodata->windowlist[i]->xwindow == xevent.xany.window)) {
320  data = videodata->windowlist[i];
321  break;
322  }
323  }
324  }
325  if (!data) {
326  return;
327  }
328 
329  switch (xevent.type) {
330 
331  /* Gaining mouse coverage? */
332  case EnterNotify:{
333 #ifdef DEBUG_XEVENTS
334  printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
335  xevent.xcrossing.x,
336  xevent.xcrossing.y,
337  xevent.xcrossing.mode);
338  if (xevent.xcrossing.mode == NotifyGrab)
339  printf("Mode: NotifyGrab\n");
340  if (xevent.xcrossing.mode == NotifyUngrab)
341  printf("Mode: NotifyUngrab\n");
342 #endif
343  SDL_SetMouseFocus(data->window);
344 
345  if (!SDL_GetMouse()->relative_mode) {
346  SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
347  }
348  }
349  break;
350  /* Losing mouse coverage? */
351  case LeaveNotify:{
352 #ifdef DEBUG_XEVENTS
353  printf("window %p: LeaveNotify! (%d,%d,%d)\n", data,
354  xevent.xcrossing.x,
355  xevent.xcrossing.y,
356  xevent.xcrossing.mode);
357  if (xevent.xcrossing.mode == NotifyGrab)
358  printf("Mode: NotifyGrab\n");
359  if (xevent.xcrossing.mode == NotifyUngrab)
360  printf("Mode: NotifyUngrab\n");
361 #endif
362  if (!SDL_GetMouse()->relative_mode) {
363  SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
364  }
365 
366  if (xevent.xcrossing.mode != NotifyGrab &&
367  xevent.xcrossing.mode != NotifyUngrab &&
368  xevent.xcrossing.detail != NotifyInferior) {
370  }
371  }
372  break;
373 
374  /* Gaining input focus? */
375  case FocusIn:{
376  if (xevent.xfocus.detail == NotifyInferior) {
377 #ifdef DEBUG_XEVENTS
378  printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data);
379 #endif
380  break;
381  }
382 #ifdef DEBUG_XEVENTS
383  printf("window %p: FocusIn!\n", data);
384 #endif
385  if (data->pending_focus == PENDING_FOCUS_OUT &&
386  data->window == SDL_GetKeyboardFocus()) {
387  /* We want to reset the keyboard here, because we may have
388  missed keyboard messages after our previous FocusOut.
389  */
390  /* Actually, if we do this we clear the ALT key on Unity
391  because it briefly takes focus for their dashboard.
392 
393  I think it's better to think the ALT key is held down
394  when it's not, then always lose the ALT modifier on Unity.
395  */
396  /* SDL_ResetKeyboard(); */
397  }
400  }
401  break;
402 
403  /* Losing input focus? */
404  case FocusOut:{
405  if (xevent.xfocus.detail == NotifyInferior) {
406  /* We still have focus if a child gets focus */
407 #ifdef DEBUG_XEVENTS
408  printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data);
409 #endif
410  break;
411  }
412 #ifdef DEBUG_XEVENTS
413  printf("window %p: FocusOut!\n", data);
414 #endif
417  }
418  break;
419 
420  /* Generated upon EnterWindow and FocusIn */
421  case KeymapNotify:{
422 #ifdef DEBUG_XEVENTS
423  printf("window %p: KeymapNotify!\n", data);
424 #endif
425  /* FIXME:
426  X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
427  */
428  }
429  break;
430 
431  /* Has the keyboard layout changed? */
432  case MappingNotify:{
433 #ifdef DEBUG_XEVENTS
434  printf("window %p: MappingNotify!\n", data);
435 #endif
437  }
438  break;
439 
440  /* Key press? */
441  case KeyPress:{
442  KeyCode keycode = xevent.xkey.keycode;
443  KeySym keysym = NoSymbol;
444  char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
445  Status status = 0;
446 
447 #ifdef DEBUG_XEVENTS
448  printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
449 #endif
450  SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
451 #if 1
452  if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
453  int min_keycode, max_keycode;
454  XDisplayKeycodes(display, &min_keycode, &max_keycode);
455 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
456  keysym = XkbKeycodeToKeysym(display, keycode, 0, 0);
457 #else
458  keysym = XKeycodeToKeysym(display, keycode, 0);
459 #endif
460  fprintf(stderr,
461  "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
462  keycode, keycode - min_keycode, keysym,
463  XKeysymToString(keysym));
464  }
465 #endif
466  /* */
467  SDL_zero(text);
468 #ifdef X_HAVE_UTF8_STRING
469  if (data->ic) {
470  Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
471  &keysym, &status);
472  }
473 #else
474  XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
475 #endif
476  if (*text) {
477  SDL_SendKeyboardText(text);
478  }
479  }
480  break;
481 
482  /* Key release? */
483  case KeyRelease:{
484  KeyCode keycode = xevent.xkey.keycode;
485 
486 #ifdef DEBUG_XEVENTS
487  printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
488 #endif
489  if (X11_KeyRepeat(display, &xevent)) {
490  /* We're about to get a repeated key down, ignore the key up */
491  break;
492  }
493  SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
494  }
495  break;
496 
497  /* Have we been iconified? */
498  case UnmapNotify:{
499 #ifdef DEBUG_XEVENTS
500  printf("window %p: UnmapNotify!\n", data);
501 #endif
502  X11_DispatchUnmapNotify(data);
503  }
504  break;
505 
506  /* Have we been restored? */
507  case MapNotify:{
508 #ifdef DEBUG_XEVENTS
509  printf("window %p: MapNotify!\n", data);
510 #endif
511  X11_DispatchMapNotify(data);
512  }
513  break;
514 
515  /* Have we been resized or moved? */
516  case ConfigureNotify:{
517 #ifdef DEBUG_XEVENTS
518  printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data,
519  xevent.xconfigure.x, xevent.xconfigure.y,
520  xevent.xconfigure.width, xevent.xconfigure.height);
521 #endif
522  if (xevent.xconfigure.x != data->last_xconfigure.x ||
523  xevent.xconfigure.y != data->last_xconfigure.y) {
525  xevent.xconfigure.x, xevent.xconfigure.y);
526  }
527  if (xevent.xconfigure.width != data->last_xconfigure.width ||
528  xevent.xconfigure.height != data->last_xconfigure.height) {
530  xevent.xconfigure.width,
531  xevent.xconfigure.height);
532  }
533  data->last_xconfigure = xevent.xconfigure;
534  }
535  break;
536 
537  /* Have we been requested to quit (or another client message?) */
538  case ClientMessage:{
539 
540  int xdnd_version=0;
541 
542  if (xevent.xclient.message_type == videodata->XdndEnter) {
543  SDL_bool use_list = xevent.xclient.data.l[1] & 1;
544  data->xdnd_source = xevent.xclient.data.l[0];
545  xdnd_version = ( xevent.xclient.data.l[1] >> 24);
546  if (use_list) {
547  /* fetch conversion targets */
548  SDL_x11Prop p;
549  X11_ReadProperty(&p, display, data->xdnd_source, videodata->XdndTypeList);
550  /* pick one */
551  data->xdnd_req = X11_PickTarget(display, (Atom*)p.data, p.count);
552  XFree(p.data);
553  } else {
554  /* pick from list of three */
555  data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]);
556  }
557  }
558  else if (xevent.xclient.message_type == videodata->XdndPosition) {
559 
560  /* reply with status */
561  memset(&m, 0, sizeof(XClientMessageEvent));
562  m.type = ClientMessage;
563  m.display = xevent.xclient.display;
564  m.window = xevent.xclient.data.l[0];
565  m.message_type = videodata->XdndStatus;
566  m.format=32;
567  m.data.l[0] = data->xwindow;
568  m.data.l[1] = (data->xdnd_req != None);
569  m.data.l[2] = 0; /* specify an empty rectangle */
570  m.data.l[3] = 0;
571  m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */
572 
573  XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
574  XFlush(display);
575  }
576  else if(xevent.xclient.message_type == videodata->XdndDrop) {
577  if (data->xdnd_req == None) {
578  /* say again - not interested! */
579  memset(&m, 0, sizeof(XClientMessageEvent));
580  m.type = ClientMessage;
581  m.display = xevent.xclient.display;
582  m.window = xevent.xclient.data.l[0];
583  m.message_type = videodata->XdndFinished;
584  m.format=32;
585  m.data.l[0] = data->xwindow;
586  m.data.l[1] = 0;
587  m.data.l[2] = None; /* fail! */
588  XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
589  } else {
590  /* convert */
591  if(xdnd_version >= 1) {
592  XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
593  } else {
594  XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
595  }
596  }
597  }
598  else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
599  (xevent.xclient.format == 32) &&
600  (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) {
601  Window root = DefaultRootWindow(display);
602 
603 #ifdef DEBUG_XEVENTS
604  printf("window %p: _NET_WM_PING\n", data);
605 #endif
606  xevent.xclient.window = root;
607  XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
608  break;
609  }
610 
611  else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
612  (xevent.xclient.format == 32) &&
613  (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
614 
615 #ifdef DEBUG_XEVENTS
616  printf("window %p: WM_DELETE_WINDOW\n", data);
617 #endif
619  break;
620  }
621  }
622  break;
623 
624  /* Do we need to refresh ourselves? */
625  case Expose:{
626 #ifdef DEBUG_XEVENTS
627  printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
628 #endif
630  }
631  break;
632 
633  case MotionNotify:{
634  SDL_Mouse *mouse = SDL_GetMouse();
635  if(!mouse->relative_mode) {
636 #ifdef DEBUG_MOTION
637  printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
638 #endif
639 
640  SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
641  }
642  }
643  break;
644 
645  case ButtonPress:{
646  int ticks = 0;
647  if (X11_IsWheelEvent(display,&xevent,&ticks)) {
648  SDL_SendMouseWheel(data->window, 0, 0, ticks);
649  } else {
650  SDL_SendMouseButton(data->window, 0, SDL_PRESSED, xevent.xbutton.button);
651  }
652  }
653  break;
654 
655  case ButtonRelease:{
656  SDL_SendMouseButton(data->window, 0, SDL_RELEASED, xevent.xbutton.button);
657  }
658  break;
659 
660  case PropertyNotify:{
661 #ifdef DEBUG_XEVENTS
662  unsigned char *propdata;
663  int status, real_format;
664  Atom real_type;
665  unsigned long items_read, items_left, i;
666 
667  char *name = XGetAtomName(display, xevent.xproperty.atom);
668  if (name) {
669  printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
670  XFree(name);
671  }
672 
673  status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
674  if (status == Success && items_read > 0) {
675  if (real_type == XA_INTEGER) {
676  int *values = (int *)propdata;
677 
678  printf("{");
679  for (i = 0; i < items_read; i++) {
680  printf(" %d", values[i]);
681  }
682  printf(" }\n");
683  } else if (real_type == XA_CARDINAL) {
684  if (real_format == 32) {
685  Uint32 *values = (Uint32 *)propdata;
686 
687  printf("{");
688  for (i = 0; i < items_read; i++) {
689  printf(" %d", values[i]);
690  }
691  printf(" }\n");
692  } else if (real_format == 16) {
693  Uint16 *values = (Uint16 *)propdata;
694 
695  printf("{");
696  for (i = 0; i < items_read; i++) {
697  printf(" %d", values[i]);
698  }
699  printf(" }\n");
700  } else if (real_format == 8) {
701  Uint8 *values = (Uint8 *)propdata;
702 
703  printf("{");
704  for (i = 0; i < items_read; i++) {
705  printf(" %d", values[i]);
706  }
707  printf(" }\n");
708  }
709  } else if (real_type == XA_STRING ||
710  real_type == videodata->UTF8_STRING) {
711  printf("{ \"%s\" }\n", propdata);
712  } else if (real_type == XA_ATOM) {
713  Atom *atoms = (Atom *)propdata;
714 
715  printf("{");
716  for (i = 0; i < items_read; i++) {
717  char *name = XGetAtomName(display, atoms[i]);
718  if (name) {
719  printf(" %s", name);
720  XFree(name);
721  }
722  }
723  printf(" }\n");
724  } else {
725  char *name = XGetAtomName(display, real_type);
726  printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN");
727  if (name) {
728  XFree(name);
729  }
730  }
731  }
732  if (status == Success) {
733  XFree(propdata);
734  }
735 #endif /* DEBUG_XEVENTS */
736 
737  if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
738  /* Get the new state from the window manager.
739  Compositing window managers can alter visibility of windows
740  without ever mapping / unmapping them, so we handle that here,
741  because they use the NETWM protocol to notify us of changes.
742  */
743  Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
744  if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) {
745  if (flags & SDL_WINDOW_HIDDEN) {
746  X11_DispatchUnmapNotify(data);
747  } else {
748  X11_DispatchMapNotify(data);
749  }
750  }
751  }
752  }
753  break;
754 
755  /* Copy the selection from XA_CUT_BUFFER0 to the requested property */
756  case SelectionRequest: {
757  XSelectionRequestEvent *req;
758  XEvent sevent;
759  int seln_format;
760  unsigned long nbytes;
761  unsigned long overflow;
762  unsigned char *seln_data;
763 
764  req = &xevent.xselectionrequest;
765 #ifdef DEBUG_XEVENTS
766  printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data,
767  req->requestor, req->target);
768 #endif
769 
770  SDL_zero(sevent);
771  sevent.xany.type = SelectionNotify;
772  sevent.xselection.selection = req->selection;
773  sevent.xselection.target = None;
774  sevent.xselection.property = None;
775  sevent.xselection.requestor = req->requestor;
776  sevent.xselection.time = req->time;
777  if (XGetWindowProperty(display, DefaultRootWindow(display),
778  XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target,
779  &sevent.xselection.target, &seln_format, &nbytes,
780  &overflow, &seln_data) == Success) {
781  Atom XA_TARGETS = XInternAtom(display, "TARGETS", 0);
782  if (sevent.xselection.target == req->target) {
783  XChangeProperty(display, req->requestor, req->property,
784  sevent.xselection.target, seln_format, PropModeReplace,
785  seln_data, nbytes);
786  sevent.xselection.property = req->property;
787  } else if (XA_TARGETS == req->target) {
788  Atom SupportedFormats[] = { sevent.xselection.target, XA_TARGETS };
789  XChangeProperty(display, req->requestor, req->property,
790  XA_ATOM, 32, PropModeReplace,
791  (unsigned char*)SupportedFormats,
792  sizeof(SupportedFormats)/sizeof(*SupportedFormats));
793  sevent.xselection.property = req->property;
794  }
795  XFree(seln_data);
796  }
797  XSendEvent(display, req->requestor, False, 0, &sevent);
798  XSync(display, False);
799  }
800  break;
801 
802  case SelectionNotify: {
803 #ifdef DEBUG_XEVENTS
804  printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
805  xevent.xselection.requestor, xevent.xselection.target);
806 #endif
807  Atom target = xevent.xselection.target;
808  if (target == data->xdnd_req) {
809  /* read data */
810  SDL_x11Prop p;
811  X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
812 
813  if (p.format == 8) {
814  SDL_bool expect_lf = SDL_FALSE;
815  char *start = NULL;
816  char *scan = (char*)p.data;
817  char *fn;
818  char *uri;
819  int length = 0;
820  while (p.count--) {
821  if (!expect_lf) {
822  if (*scan == 0x0D) {
823  expect_lf = SDL_TRUE;
824  }
825  if (start == NULL) {
826  start = scan;
827  length = 0;
828  }
829  length++;
830  } else {
831  if (*scan == 0x0A && length > 0) {
832  uri = SDL_malloc(length--);
833  SDL_memcpy(uri, start, length);
834  uri[length] = '\0';
835  fn = X11_URIToLocal(uri);
836  if (fn) {
837  SDL_SendDropFile(fn);
838  }
839  SDL_free(uri);
840  }
841  expect_lf = SDL_FALSE;
842  start = NULL;
843  }
844  scan++;
845  }
846  }
847 
848  XFree(p.data);
849 
850  /* send reply */
851  SDL_memset(&m, 0, sizeof(XClientMessageEvent));
852  m.type = ClientMessage;
853  m.display = display;
854  m.window = data->xdnd_source;
855  m.message_type = videodata->XdndFinished;
856  m.format = 32;
857  m.data.l[0] = data->xwindow;
858  m.data.l[1] = 1;
859  m.data.l[2] = videodata->XdndActionCopy;
860  XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent*)&m);
861 
862  XSync(display, False);
863 
864  } else {
865  videodata->selection_waiting = SDL_FALSE;
866  }
867  }
868  break;
869 
870  default:{
871 #ifdef DEBUG_XEVENTS
872  printf("window %p: Unhandled event %d\n", data, xevent.type);
873 #endif
874  }
875  break;
876  }
877 }
878 
879 static void
880 X11_HandleFocusChanges(_THIS)
881 {
882  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
883  int i;
884 
885  if (videodata && videodata->windowlist) {
886  for (i = 0; i < videodata->numwindows; ++i) {
887  SDL_WindowData *data = videodata->windowlist[i];
888  if (data && data->pending_focus != PENDING_FOCUS_NONE) {
889  Uint32 now = SDL_GetTicks();
890  if ( (int)(data->pending_focus_time-now) <= 0 ) {
891  if ( data->pending_focus == PENDING_FOCUS_IN ) {
892  X11_DispatchFocusIn(data);
893  } else {
894  X11_DispatchFocusOut(data);
895  }
897  }
898  }
899  }
900  }
901 }
902 /* Ack! XPending() actually performs a blocking read if no events available */
903 static int
904 X11_Pending(Display * display)
905 {
906  /* Flush the display connection and look to see if events are queued */
907  XFlush(display);
908  if (XEventsQueued(display, QueuedAlready)) {
909  return (1);
910  }
911 
912  /* More drastic measures are required -- see if X is ready to talk */
913  {
914  static struct timeval zero_time; /* static == 0 */
915  int x11_fd;
916  fd_set fdset;
917 
918  x11_fd = ConnectionNumber(display);
919  FD_ZERO(&fdset);
920  FD_SET(x11_fd, &fdset);
921  if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
922  return (XPending(display));
923  }
924  }
925 
926  /* Oh well, nothing is ready .. */
927  return (0);
928 }
929 
930 
931 /* !!! FIXME: this should be exposed in a header, or something. */
932 int SDL_GetNumTouch(void);
933 void SDL_dbus_screensaver_tickle(_THIS);
934 
935 void
937 {
939 
940  /* Update activity every 30 seconds to prevent screensaver */
942  Uint32 now = SDL_GetTicks();
943  if (!data->screensaver_activity ||
944  (int) (now - data->screensaver_activity) >= 30000) {
945  XResetScreenSaver(data->display);
946 
947  #if SDL_USE_LIBDBUS
948  SDL_dbus_screensaver_tickle(_this);
949  #endif
950 
951  data->screensaver_activity = now;
952  }
953  }
954 
955  /* Keep processing pending events */
956  while (X11_Pending(data->display)) {
957  X11_DispatchEvent(_this);
958  }
959 
960  /* FIXME: Only need to do this when there are pending focus changes */
961  X11_HandleFocusChanges(_this);
962 }
963 
964 
965 void
967 {
968 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
970  int dummy;
971  int major_version, minor_version;
972 
973  if (SDL_X11_HAVE_XSS) {
974  /* XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
975  if (!XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
976  !XScreenSaverQueryVersion(data->display,
977  &major_version, &minor_version) ||
978  major_version < 1 || (major_version == 1 && minor_version < 1)) {
979  return;
980  }
981 
982  XScreenSaverSuspend(data->display, _this->suspend_screensaver);
983  XResetScreenSaver(data->display);
984  }
985 #endif
986 
987 #if SDL_USE_LIBDBUS
988  if (_this->suspend_screensaver) {
989  SDL_dbus_screensaver_tickle(_this);
990  }
991 #endif
992 }
993 
994 #endif /* SDL_VIDEO_DRIVER_X11 */
995 
996 /* vi: set ts=4 sw=4 expandtab: */
void X11_PumpEvents(_THIS)
SDL_version version
Definition: SDL_syswm.h:114
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 int return Display Window Cursor return Display Window return Display Drawable GC int int unsigned int unsigned int return Display Drawable GC int int _Xconst char int return Display Drawable GC int int unsigned int unsigned int return Display return Display Cursor return Display GC return XModifierKeymap return char Display Window int return Display return Display Atom return Display Window XWindowAttributes return Display Window return Display XEvent Bool(*) XPointer return Display Window Bool unsigned int int int Window Cursor Time return Display Window int return KeySym return Display _Xconst char Bool return Display _Xconst char retur XLookupString)
Definition: SDL_x11sym.h:86
Display * display
Definition: SDL_x11video.h:75
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:62
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:611
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
Uint32 X11_GetNetWMState(_THIS, Window xwindow)
#define NULL
Definition: ftobjs.h:61
GLuint start
Definition: glew.h:1239
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 int return Display Window Cursor return Display Window return Display Drawable GC int int unsigned int unsigned int return Display Drawable GC int int _Xconst char int return Display Drawable GC int int unsigned int unsigned int retur XFlush)
Definition: SDL_x11sym.h:54
SDL_bool
Definition: SDL_stdinc.h:116
#define local
Definition: zutil.h:30
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_WindowData ** windowlist
Definition: SDL_x11video.h:81
#define memset
Definition: SDL_malloc.c:633
#define SDL_ENABLE
Definition: SDL_events.h:688
FILE * file
Definition: visualinfo.c:88
EGLImageKHR EGLint * name
Definition: eglext.h:284
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
SDL_Window * window
return Display return Display Bool Bool int d
Definition: SDL_x11sym.h:30
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:93
char * display
Definition: visualinfo.c:85
if(!yyg->yy_init)
SDL_bool selection_waiting
Definition: SDL_x11video.h:115
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:624
ret
Definition: glew_str_glx.c:2
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 int return Display Window Cursor return Display Window return Display Drawable GC int int unsigned int unsigned int return Display Drawable GC int int _Xconst char int return Display Drawable GC int int unsigned int unsigned int return Display return Display Cursor return Display GC return XModifierKeymap return char Display Window int return Display return Display Atom return Display Window XWindowAttributes return Display Window return Display XEvent Bool(*) XPointer return Display Window Bool unsigned int int int Window Cursor Time return Display Window int return KeySym return Display _Xconst char Bool return Display _Xconst char return XKeyEvent char int KeySym XComposeStatus return Display int int int XVisualInfo return Display Window int int return _Xconst char return Display XEvent return Display Drawable GC XImage int int int int unsigned int unsigned int return Display Window Window Window int int int int unsigned int return Display Window Window int int return Display Window unsigned int unsigned int retur XSendEvent)
Definition: SDL_x11sym.h:104
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:650
Atom _NET_WM_STATE
Definition: SDL_x11video.h:90
#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:92
EGLContext EGLenum target
Definition: eglext.h:87
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
DECLSPEC Uint32 SDLCALL SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
Definition: SDL_systimer.c:44
return Display return Display Bool Bool int int int return XCheckIfEvent
Definition: SDL_x11sym.h:32
Uint32 screensaver_activity
Uint32 pending_focus_time
Definition: SDL_x11window.h:61
Atom WM_DELETE_WINDOW
Definition: SDL_x11video.h:89
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 int return Display Window Cursor return Display Window return Display Drawable GC int int unsigned int unsigned int return Display Drawable GC int int _Xconst char int return Display Drawable GC int int unsigned int unsigned int return Display return Display Cursor return Display GC return XModifierKeymap return char Display Window int return Display return Display Atom return Display Window XWindowAttributes return Display Window return Display XEvent Bool(*) XPointer return Display Window Bool unsigned int int int Window Cursor Time return Display Window int return KeySym retur XInternAtom)
Definition: SDL_x11sym.h:82
#define SDL_GetEventState(type)
Definition: SDL_events.h:701
void X11_SuspendScreenSaver(_THIS)
GLsizei GLsizei * length
Definition: gl2ext.h:792
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:178
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define _THIS
struct SDL_VideoData * videodata
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:784
GLint GLsizei count
Definition: gl2ext.h:1011
GLfloat GLfloat p
Definition: glew.h:14938
SDL_bool relative_mode
Definition: SDL_mouse_c.h:68
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
union SDL_SysWMmsg::@77 msg
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
void X11_UpdateKeymap(_THIS)
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 int return Display Window Cursor return Display Window return Display Drawable GC int int unsigned int unsigned int return Display Drawable GC int int _Xconst char int return Display Drawable GC int int unsigned int unsigned int return Display return Display Cursor return Display GC return XModifierKeymap return char Display Window int return Display return Display Atom return Display Window XWindowAttributes return Display Window return Display XEvent Bool(*) XPointer return Display Window Bool unsigned int int int Window Cursor Time return Display Window int retur XKeysymToString)
Definition: SDL_x11sym.h:80
#define PENDING_FOCUS_IN_TIME
Definition: SDL_x11window.h:30
Window xdnd_source
Definition: SDL_x11window.h:65
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:115
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
int SDL_SendDropFile(const char *file)
XConfigureEvent last_xconfigure
Definition: SDL_x11window.h:62
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, int x, int y)
Definition: SDL_mouse.c:332
int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie)
SDL_bool suspend_screensaver
Definition: SDL_sysvideo.h:263
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:137
#define SDL_TEXTINPUTEVENT_TEXT_SIZE
Definition: SDL_events.h:203
DECLSPEC SDL_Window *SDLCALL SDL_GetKeyboardFocus(void)
Get the window which currently has keyboard focus.
Definition: SDL_keyboard.c:603
#define SDL_zero(x)
Definition: SDL_stdinc.h:254
#define SDL_PRESSED
Definition: SDL_events.h:50
int i
Definition: pngrutil.c:1377
while(1)
char Bool
Definition: ftraster.c:307
Uint32 flags
Definition: SDL_sysvideo.h:81
#define SDL_RELEASED
Definition: SDL_events.h:49
PendingFocusEnum pending_focus
Definition: SDL_x11window.h:60
struct XGenericEventCookie XGenericEventCookie
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:276
#define PENDING_FOCUS_OUT_TIME
Definition: SDL_x11window.h:31
GLint GLsizei const GLuint64 * values
Definition: glew.h:3473
cl_event event
Definition: glew.h:3556
const GLdouble * m
Definition: glew.h:8385