src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 03 Oct 2012 13:37:44 -0700
changeset 6542 5c1b8ed19212
parent 6504 100c49578dba
child 6637 31e3f5b04120
permissions -rw-r--r--
Keep track of the configure events we've received from the X server.
When programmatically resizing a window on Unity 3D, we'll get a move event with the old size before we get a size event with the new size, and we don't want to clobber our internal state with the old size.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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 #ifdef SDL_INPUT_LINUXEV
    45 //Touch Input/event* includes
    46 #include <linux/input.h>
    47 #include <fcntl.h>
    48 #endif
    49 
    50 /*#define DEBUG_XEVENTS*/
    51 
    52 /* Check to see if this is a repeated key.
    53    (idea shamelessly lifted from GII -- thanks guys! :)
    54  */
    55 static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
    56 {
    57     XEvent peekevent;
    58 
    59     if (XPending(display)) {
    60         XPeekEvent(display, &peekevent);
    61         if ((peekevent.type == KeyPress) &&
    62             (peekevent.xkey.keycode == event->xkey.keycode) &&
    63             ((peekevent.xkey.time-event->xkey.time) < 2)) {
    64             return SDL_TRUE;
    65         }
    66     }
    67     return SDL_FALSE;
    68 }
    69 
    70 static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int * ticks)
    71 {
    72     XEvent peekevent;
    73     if (XPending(display)) {
    74         /* according to the xlib docs, no specific mouse wheel events exist.
    75            however, mouse wheel events trigger a button press and a button release
    76            immediately. thus, checking if the same button was released at the same
    77            time as it was pressed, should be an adequate hack to derive a mouse 
    78            wheel event. */
    79         XPeekEvent(display,&peekevent);
    80         if ((peekevent.type           == ButtonRelease) &&
    81             (peekevent.xbutton.button == event->xbutton.button) &&
    82             (peekevent.xbutton.time   == event->xbutton.time)) {
    83 
    84             /* by default, X11 only knows 5 buttons. on most 3 button + wheel mouse,
    85                Button4 maps to wheel up, Button5 maps to wheel down. */
    86             if (event->xbutton.button == Button4) {
    87                 *ticks = 1;
    88             }
    89             else if (event->xbutton.button == Button5) {
    90                 *ticks = -1;
    91             }
    92 
    93             /* remove the following release event, as this is now a wheel event */
    94             XNextEvent(display,&peekevent);
    95             return SDL_TRUE;
    96         }
    97     }
    98     return SDL_FALSE;
    99 }
   100 
   101 
   102 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
   103 static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event)
   104 {
   105     XGenericEventCookie *cookie = &event.xcookie;
   106     XGetEventData(videodata->display, cookie);
   107     X11_HandleXinput2Event(videodata,cookie);
   108     XFreeEventData(videodata->display,cookie);
   109 }
   110 #endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
   111 
   112 
   113 static void
   114 X11_DispatchFocusIn(SDL_WindowData *data)
   115 {
   116 #ifdef DEBUG_XEVENTS
   117     printf("window %p: Dispatching FocusIn\n", data);
   118 #endif
   119     SDL_SetKeyboardFocus(data->window);
   120 #ifdef X_HAVE_UTF8_STRING
   121     if (data->ic) {
   122         XSetICFocus(data->ic);
   123     }
   124 #endif
   125 }
   126 
   127 static void
   128 X11_DispatchFocusOut(SDL_WindowData *data)
   129 {
   130 #ifdef DEBUG_XEVENTS
   131     printf("window %p: Dispatching FocusOut\n", data);
   132 #endif
   133     SDL_SetKeyboardFocus(NULL);
   134 #ifdef X_HAVE_UTF8_STRING
   135     if (data->ic) {
   136         XUnsetICFocus(data->ic);
   137     }
   138 #endif
   139 }
   140 
   141 static void
   142 X11_DispatchMapNotify(SDL_WindowData *data)
   143 {
   144     SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
   145     SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
   146 }
   147 
   148 static void
   149 X11_DispatchUnmapNotify(SDL_WindowData *data)
   150 {
   151     SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   152     SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
   153 }
   154 
   155 static void
   156 X11_DispatchEvent(_THIS)
   157 {
   158     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   159     Display *display = videodata->display;
   160     SDL_WindowData *data;
   161     XEvent xevent;
   162     int i;
   163 
   164     SDL_zero(xevent);           /* valgrind fix. --ryan. */
   165     XNextEvent(display, &xevent);
   166 
   167     /* filter events catchs XIM events and sends them to the correct
   168        handler */
   169     if (XFilterEvent(&xevent, None) == True) {
   170 #if 0
   171         printf("Filtered event type = %d display = %d window = %d\n",
   172                xevent.type, xevent.xany.display, xevent.xany.window);
   173 #endif
   174         return;
   175     }
   176 
   177     /* Send a SDL_SYSWMEVENT if the application wants them */
   178     if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
   179         SDL_SysWMmsg wmmsg;
   180 
   181         SDL_VERSION(&wmmsg.version);
   182         wmmsg.subsystem = SDL_SYSWM_X11;
   183         wmmsg.msg.x11.event = xevent;
   184         SDL_SendSysWMEvent(&wmmsg);
   185     }
   186 
   187 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
   188     if(xevent.type == GenericEvent) {
   189         X11_HandleGenericEvent(videodata,xevent);
   190         return;
   191     }
   192 #endif
   193 
   194 #if 0
   195     printf("type = %d display = %d window = %d\n",
   196            xevent.type, xevent.xany.display, xevent.xany.window);
   197 #endif
   198 
   199     data = NULL;
   200     if (videodata && videodata->windowlist) {
   201         for (i = 0; i < videodata->numwindows; ++i) {
   202             if ((videodata->windowlist[i] != NULL) &&
   203                 (videodata->windowlist[i]->xwindow == xevent.xany.window)) {
   204                 data = videodata->windowlist[i];
   205                 break;
   206             }
   207         }
   208     }
   209     if (!data) {
   210         return;
   211     }
   212 
   213     switch (xevent.type) {
   214 
   215         /* Gaining mouse coverage? */
   216     case EnterNotify:{
   217 #ifdef DEBUG_XEVENTS
   218             printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
   219                    xevent.xcrossing.x,
   220                    xevent.xcrossing.y,
   221                    xevent.xcrossing.mode);
   222             if (xevent.xcrossing.mode == NotifyGrab)
   223                 printf("Mode: NotifyGrab\n");
   224             if (xevent.xcrossing.mode == NotifyUngrab)
   225                 printf("Mode: NotifyUngrab\n");
   226 #endif
   227             SDL_SetMouseFocus(data->window);
   228         }
   229         break;
   230         /* Losing mouse coverage? */
   231     case LeaveNotify:{
   232 #ifdef DEBUG_XEVENTS
   233             printf("window %p: LeaveNotify! (%d,%d,%d)\n", data,
   234                    xevent.xcrossing.x,
   235                    xevent.xcrossing.y,
   236                    xevent.xcrossing.mode);
   237             if (xevent.xcrossing.mode == NotifyGrab)
   238                 printf("Mode: NotifyGrab\n");
   239             if (xevent.xcrossing.mode == NotifyUngrab)
   240                 printf("Mode: NotifyUngrab\n");
   241 #endif
   242             if (xevent.xcrossing.mode != NotifyGrab &&
   243                 xevent.xcrossing.mode != NotifyUngrab &&
   244                 xevent.xcrossing.detail != NotifyInferior) {
   245                 SDL_SetMouseFocus(NULL);
   246             }
   247         }
   248         break;
   249 
   250         /* Gaining input focus? */
   251     case FocusIn:{
   252 #ifdef DEBUG_XEVENTS
   253             printf("window %p: FocusIn!\n", data);
   254 #endif
   255             data->pending_focus = PENDING_FOCUS_IN;
   256             data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME;
   257         }
   258         break;
   259 
   260         /* Losing input focus? */
   261     case FocusOut:{
   262 #ifdef DEBUG_XEVENTS
   263             printf("window %p: FocusOut!\n", data);
   264 #endif
   265             data->pending_focus = PENDING_FOCUS_OUT;
   266             data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME;
   267         }
   268         break;
   269 
   270         /* Generated upon EnterWindow and FocusIn */
   271     case KeymapNotify:{
   272 #ifdef DEBUG_XEVENTS
   273             printf("window %p: KeymapNotify!\n", data);
   274 #endif
   275             /* FIXME:
   276                X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
   277              */
   278         }
   279         break;
   280 
   281         /* Has the keyboard layout changed? */
   282     case MappingNotify:{
   283 #ifdef DEBUG_XEVENTS
   284             printf("window %p: MappingNotify!\n", data);
   285 #endif
   286             X11_UpdateKeymap(_this);
   287         }
   288         break;
   289 
   290         /* Key press? */
   291     case KeyPress:{
   292             KeyCode keycode = xevent.xkey.keycode;
   293             KeySym keysym = NoSymbol;
   294             char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
   295             Status status = 0;
   296 
   297 #ifdef DEBUG_XEVENTS
   298             printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
   299 #endif
   300             SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
   301 #if 1
   302             if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN) {
   303                 int min_keycode, max_keycode;
   304                 XDisplayKeycodes(display, &min_keycode, &max_keycode);
   305 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
   306                 keysym = XkbKeycodeToKeysym(display, keycode, 0, 0);
   307 #else
   308                 keysym = XKeycodeToKeysym(display, keycode, 0);
   309 #endif
   310                 fprintf(stderr,
   311                         "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",
   312                         keycode, keycode - min_keycode, keysym,
   313                         XKeysymToString(keysym));
   314             }
   315 #endif
   316             /* */
   317             SDL_zero(text);
   318 #ifdef X_HAVE_UTF8_STRING
   319             if (data->ic) {
   320                 Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
   321                                   &keysym, &status);
   322             }
   323 #else
   324             XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
   325 #endif
   326             if (*text) {
   327                 SDL_SendKeyboardText(text);
   328             }
   329         }
   330         break;
   331 
   332         /* Key release? */
   333     case KeyRelease:{
   334             KeyCode keycode = xevent.xkey.keycode;
   335 
   336 #ifdef DEBUG_XEVENTS
   337             printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
   338 #endif
   339             if (X11_KeyRepeat(display, &xevent)) {
   340                 /* We're about to get a repeated key down, ignore the key up */
   341                 break;
   342             }
   343             SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
   344         }
   345         break;
   346 
   347         /* Have we been iconified? */
   348     case UnmapNotify:{
   349 #ifdef DEBUG_XEVENTS
   350             printf("window %p: UnmapNotify!\n", data);
   351 #endif
   352             X11_DispatchUnmapNotify(data);
   353         }
   354         break;
   355 
   356         /* Have we been restored? */
   357     case MapNotify:{
   358 #ifdef DEBUG_XEVENTS
   359             printf("window %p: MapNotify!\n", data);
   360 #endif
   361             X11_DispatchMapNotify(data);
   362         }
   363         break;
   364 
   365         /* Have we been resized or moved? */
   366     case ConfigureNotify:{
   367 #ifdef DEBUG_XEVENTS
   368             printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data,
   369                    xevent.xconfigure.x, xevent.xconfigure.y,
   370                    xevent.xconfigure.width, xevent.xconfigure.height);
   371 #endif
   372             if (xevent.xconfigure.x != data->last_xconfigure.x ||
   373                 xevent.xconfigure.y != data->last_xconfigure.y) {
   374                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
   375                                     xevent.xconfigure.x, xevent.xconfigure.y);
   376             }
   377             if (xevent.xconfigure.width != data->last_xconfigure.width ||
   378                 xevent.xconfigure.height != data->last_xconfigure.height) {
   379                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED,
   380                                     xevent.xconfigure.width,
   381                                     xevent.xconfigure.height);
   382             }
   383             data->last_xconfigure = xevent.xconfigure;
   384         }
   385         break;
   386 
   387         /* Have we been requested to quit (or another client message?) */
   388     case ClientMessage:{
   389             if ((xevent.xclient.format == 32) &&
   390                 (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
   391 
   392                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
   393             }
   394         }
   395         break;
   396 
   397         /* Do we need to refresh ourselves? */
   398     case Expose:{
   399 #ifdef DEBUG_XEVENTS
   400             printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
   401 #endif
   402             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
   403         }
   404         break;
   405 
   406     case MotionNotify:{
   407             SDL_Mouse *mouse = SDL_GetMouse();  
   408             if(!mouse->relative_mode) {
   409 #ifdef DEBUG_MOTION
   410                 printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   411 #endif
   412 
   413                 SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);
   414             }
   415         }
   416         break;
   417 
   418     case ButtonPress:{
   419             int ticks = 0;
   420             if (X11_IsWheelEvent(display,&xevent,&ticks) == SDL_TRUE) {
   421                 SDL_SendMouseWheel(data->window, 0, ticks);
   422             }
   423             else {
   424                 SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button);
   425             }
   426         }
   427         break;
   428 
   429     case ButtonRelease:{
   430             SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button);
   431         }
   432         break;
   433 
   434     case PropertyNotify:{
   435 #ifdef DEBUG_XEVENTS
   436             unsigned char *propdata;
   437             int status, real_format;
   438             Atom real_type;
   439             unsigned long items_read, items_left, i;
   440 
   441             char *name = XGetAtomName(display, xevent.xproperty.atom);
   442             if (name) {
   443                 printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
   444                 XFree(name);
   445             }
   446 
   447             status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
   448             if (status == Success && items_read > 0) {
   449                 if (real_type == XA_INTEGER) {
   450                     int *values = (int *)propdata;
   451 
   452                     printf("{");
   453                     for (i = 0; i < items_read; i++) {
   454                         printf(" %d", values[i]);
   455                     }
   456                     printf(" }\n");
   457                 } else if (real_type == XA_CARDINAL) {
   458                     if (real_format == 32) {
   459                         Uint32 *values = (Uint32 *)propdata;
   460 
   461                         printf("{");
   462                         for (i = 0; i < items_read; i++) {
   463                             printf(" %d", values[i]);
   464                         }
   465                         printf(" }\n");
   466                     } else if (real_format == 16) {
   467                         Uint16 *values = (Uint16 *)propdata;
   468 
   469                         printf("{");
   470                         for (i = 0; i < items_read; i++) {
   471                             printf(" %d", values[i]);
   472                         }
   473                         printf(" }\n");
   474                     } else if (real_format == 8) {
   475                         Uint8 *values = (Uint8 *)propdata;
   476 
   477                         printf("{");
   478                         for (i = 0; i < items_read; i++) {
   479                             printf(" %d", values[i]);
   480                         }
   481                         printf(" }\n");
   482                     }
   483                 } else if (real_type == XA_STRING ||
   484                            real_type == videodata->UTF8_STRING) {
   485                     printf("{ \"%s\" }\n", propdata);
   486                 } else if (real_type == XA_ATOM) {
   487                     Atom *atoms = (Atom *)propdata;
   488 
   489                     printf("{");
   490                     for (i = 0; i < items_read; i++) {
   491                         char *name = XGetAtomName(display, atoms[i]);
   492                         if (name) {
   493                             printf(" %s", name);
   494                             XFree(name);
   495                         }
   496                     }
   497                     printf(" }\n");
   498                 } else {
   499                     char *name = XGetAtomName(display, real_type);
   500                     printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN");
   501                     if (name) {
   502                         XFree(name);
   503                     }
   504                 }
   505             }
   506             if (status == Success) {
   507                 XFree(propdata);
   508             }
   509 #endif /* DEBUG_XEVENTS */
   510 
   511             if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
   512                 /* Get the new state from the window manager.
   513                    Compositing window managers can alter visibility of windows
   514                    without ever mapping / unmapping them, so we handle that here,
   515                    because they use the NETWM protocol to notify us of changes.
   516                  */
   517                 Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
   518                 if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) {
   519                     if (flags & SDL_WINDOW_HIDDEN) {
   520                         X11_DispatchUnmapNotify(data);
   521                     } else {
   522                         X11_DispatchMapNotify(data);
   523                     }
   524                 }
   525             }
   526         }
   527         break;
   528 
   529     /* Copy the selection from XA_CUT_BUFFER0 to the requested property */
   530     case SelectionRequest: {
   531             XSelectionRequestEvent *req;
   532             XEvent sevent;
   533             int seln_format;
   534             unsigned long nbytes;
   535             unsigned long overflow;
   536             unsigned char *seln_data;
   537 
   538             req = &xevent.xselectionrequest;
   539 #ifdef DEBUG_XEVENTS
   540             printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data,
   541                 req->requestor, req->target);
   542 #endif
   543 
   544             SDL_zero(sevent);
   545             sevent.xany.type = SelectionNotify;
   546             sevent.xselection.selection = req->selection;
   547             sevent.xselection.target = None;
   548             sevent.xselection.property = None;
   549             sevent.xselection.requestor = req->requestor;
   550             sevent.xselection.time = req->time;
   551             if (XGetWindowProperty(display, DefaultRootWindow(display),
   552                     XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target,
   553                     &sevent.xselection.target, &seln_format, &nbytes,
   554                     &overflow, &seln_data) == Success) {
   555                 if (sevent.xselection.target == req->target) {
   556                     XChangeProperty(display, req->requestor, req->property,
   557                         sevent.xselection.target, seln_format, PropModeReplace,
   558                         seln_data, nbytes);
   559                     sevent.xselection.property = req->property;
   560                 }
   561                 XFree(seln_data);
   562             }
   563             XSendEvent(display, req->requestor, False, 0, &sevent);
   564             XSync(display, False);
   565         }
   566         break;
   567 
   568     case SelectionNotify: {
   569 #ifdef DEBUG_XEVENTS
   570             printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
   571                 xevent.xselection.requestor, xevent.xselection.target);
   572 #endif
   573             videodata->selection_waiting = SDL_FALSE;
   574         }
   575         break;
   576 
   577     default:{
   578 #ifdef DEBUG_XEVENTS
   579             printf("window %p: Unhandled event %d\n", data, xevent.type);
   580 #endif
   581         }
   582         break;
   583     }
   584 }
   585 
   586 static void
   587 X11_HandleFocusChanges(_THIS)
   588 {
   589     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   590     int i;
   591 
   592     if (videodata && videodata->windowlist) {
   593         for (i = 0; i < videodata->numwindows; ++i) {
   594             SDL_WindowData *data = videodata->windowlist[i];
   595             if (data && data->pending_focus != PENDING_FOCUS_NONE) {
   596                 Uint32 now = SDL_GetTicks();
   597                 if ( (int)(data->pending_focus_time-now) <= 0 ) {
   598                     if ( data->pending_focus == PENDING_FOCUS_IN ) {
   599                         X11_DispatchFocusIn(data);
   600                     } else {
   601                         X11_DispatchFocusOut(data);
   602                     }
   603                     data->pending_focus = PENDING_FOCUS_NONE;
   604                 }
   605             }
   606         }
   607     }
   608 }
   609 /* Ack!  XPending() actually performs a blocking read if no events available */
   610 static int
   611 X11_Pending(Display * display)
   612 {
   613     /* Flush the display connection and look to see if events are queued */
   614     XFlush(display);
   615     if (XEventsQueued(display, QueuedAlready)) {
   616         return (1);
   617     }
   618 
   619     /* More drastic measures are required -- see if X is ready to talk */
   620     {
   621         static struct timeval zero_time;        /* static == 0 */
   622         int x11_fd;
   623         fd_set fdset;
   624 
   625         x11_fd = ConnectionNumber(display);
   626         FD_ZERO(&fdset);
   627         FD_SET(x11_fd, &fdset);
   628         if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
   629             return (XPending(display));
   630         }
   631     }
   632 
   633     /* Oh well, nothing is ready .. */
   634     return (0);
   635 }
   636 
   637 
   638 /* !!! FIXME: this should be exposed in a header, or something. */
   639 int SDL_GetNumTouch(void);
   640 
   641 
   642 void
   643 X11_PumpEvents(_THIS)
   644 {
   645     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   646 
   647     /* Update activity every 30 seconds to prevent screensaver */
   648     if (_this->suspend_screensaver) {
   649         Uint32 now = SDL_GetTicks();
   650         if (!data->screensaver_activity ||
   651             (int) (now - data->screensaver_activity) >= 30000) {
   652             XResetScreenSaver(data->display);
   653             data->screensaver_activity = now;
   654         }
   655     }   
   656 
   657     /* Keep processing pending events */
   658     while (X11_Pending(data->display)) {
   659         X11_DispatchEvent(_this);
   660     }
   661 
   662     /* FIXME: Only need to do this when there are pending focus changes */
   663     X11_HandleFocusChanges(_this);
   664 
   665     /*Dont process evtouch events if XInput2 multitouch is supported*/
   666     if(X11_Xinput2IsMultitouchSupported()) {
   667         return;
   668     }
   669 
   670 #ifdef SDL_INPUT_LINUXEV
   671     /* Process Touch events*/
   672     int i = 0,rd;
   673     struct input_event ev[64];
   674     int size = sizeof (struct input_event);
   675 
   676 /* !!! FIXME: clean the tabstops out of here. */
   677     for(i = 0;i < SDL_GetNumTouch();++i) {
   678 	SDL_Touch* touch = SDL_GetTouchIndex(i);
   679 	if(!touch) printf("Touch %i/%i DNE\n",i,SDL_GetNumTouch());
   680 	EventTouchData* data;
   681 	data = (EventTouchData*)(touch->driverdata);
   682 	if(data == NULL) {
   683 	  printf("No driver data\n");
   684 	  continue;
   685 	}
   686 	if(data->eventStream <= 0) 
   687 	    printf("Error: Couldn't open stream\n");
   688 	rd = read(data->eventStream, ev, size * 64);
   689 	if(rd >= size) {
   690 	    for (i = 0; i < rd / sizeof(struct input_event); i++) {
   691 		switch (ev[i].type) {
   692 		case EV_ABS:
   693 		    switch (ev[i].code) {
   694 			case ABS_X:
   695 			    data->x = ev[i].value;
   696 			    break;
   697 			case ABS_Y:
   698 			    data->y = ev[i].value;
   699 			    break;
   700 			case ABS_PRESSURE:
   701 			    data->pressure = ev[i].value;
   702 			    if(data->pressure < 0) data->pressure = 0;
   703 			    break;
   704 			case ABS_MISC:
   705 			    if(ev[i].value == 0)
   706 			        data->up = SDL_TRUE;			    
   707 			    break;
   708 			}
   709 		    break;
   710 		case EV_MSC:
   711 			if(ev[i].code == MSC_SERIAL)
   712 				data->finger = ev[i].value;
   713 			break;
   714 		case EV_KEY:
   715 			if(ev[i].code == BTN_TOUCH)
   716 			    if(ev[i].value == 0)
   717 			        data->up = SDL_TRUE;
   718 			break;
   719 		case EV_SYN:
   720 		  if(!data->down) {
   721 		      data->down = SDL_TRUE;
   722 		      SDL_SendFingerDown(touch->id,data->finger,
   723 		    		  data->down, data->x, data->y,
   724 		    		  data->pressure);
   725 		  }
   726 		  else if(!data->up)
   727 		    SDL_SendTouchMotion(touch->id,data->finger, 
   728 					SDL_FALSE, data->x,data->y,
   729 					data->pressure);
   730 		  else
   731 		  {
   732 		      data->down = SDL_FALSE;
   733 			  SDL_SendFingerDown(touch->id,data->finger,
   734 					  data->down, data->x,data->y,
   735 					  data->pressure);
   736 			  data->x = -1;
   737 			  data->y = -1;
   738 			  data->pressure = -1;
   739 			  data->finger = 0;
   740 			  data->up = SDL_FALSE;
   741 		  }
   742 		  break;		
   743 		}
   744 	    }
   745 	}
   746     }
   747 #endif
   748 }
   749 
   750 /* This is so wrong it hurts */
   751 #define GNOME_SCREENSAVER_HACK
   752 #ifdef GNOME_SCREENSAVER_HACK
   753 #include <unistd.h>
   754 static pid_t screensaver_inhibit_pid;
   755 static void
   756 gnome_screensaver_disable()
   757 {
   758     screensaver_inhibit_pid = fork();
   759     if (screensaver_inhibit_pid == 0) {
   760         close(0);
   761         close(1);
   762         close(2);
   763         execl("/usr/bin/gnome-screensaver-command",
   764               "gnome-screensaver-command",
   765               "--inhibit",
   766               "--reason",
   767               "GNOME screensaver doesn't respect MIT-SCREEN-SAVER", NULL);
   768         exit(2);
   769     }
   770 }
   771 static void
   772 gnome_screensaver_enable()
   773 {
   774     kill(screensaver_inhibit_pid, 15);
   775 }
   776 #endif
   777 
   778 void
   779 X11_SuspendScreenSaver(_THIS)
   780 {
   781 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
   782     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   783     int dummy;
   784     int major_version, minor_version;
   785 
   786     if (SDL_X11_HAVE_XSS) {
   787         /* XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
   788         if (!XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
   789             !XScreenSaverQueryVersion(data->display,
   790                                       &major_version, &minor_version) ||
   791             major_version < 1 || (major_version == 1 && minor_version < 1)) {
   792             return;
   793         }
   794 
   795         XScreenSaverSuspend(data->display, _this->suspend_screensaver);
   796         XResetScreenSaver(data->display);
   797     }
   798 #endif
   799 
   800 #ifdef GNOME_SCREENSAVER_HACK
   801     if (_this->suspend_screensaver) {
   802         gnome_screensaver_disable();
   803     } else {
   804         gnome_screensaver_enable();
   805     }
   806 #endif
   807 }
   808 
   809 #endif /* SDL_VIDEO_DRIVER_X11 */
   810 
   811 /* vi: set ts=4 sw=4 expandtab: */