src/video/x11/SDL_x11events.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 28 Dec 2012 03:46:55 -0500
changeset 6774 ad8522052ce6
parent 6661 cd8befc0a969
child 6817 93103b719488
permissions -rw-r--r--
Replaced Gnome screensaver hack with D-Bus messages to org.gnome.ScreenSaver.
     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             if (xevent.xfocus.detail == NotifyInferior) {
   253 #ifdef DEBUG_XEVENTS
   254                 printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data);
   255 #endif
   256                 break;
   257             }
   258 #ifdef DEBUG_XEVENTS
   259             printf("window %p: FocusIn!\n", data);
   260 #endif
   261             if (data->pending_focus == PENDING_FOCUS_OUT &&
   262                 data->window == SDL_GetKeyboardFocus()) {
   263                 /* We want to reset the keyboard here, because we may have
   264                    missed keyboard messages after our previous FocusOut.
   265                  */
   266                 SDL_ResetKeyboard();
   267             }
   268             data->pending_focus = PENDING_FOCUS_IN;
   269             data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME;
   270         }
   271         break;
   272 
   273         /* Losing input focus? */
   274     case FocusOut:{
   275             if (xevent.xfocus.detail == NotifyInferior) {
   276                 /* We still have focus if a child gets focus */
   277 #ifdef DEBUG_XEVENTS
   278                 printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data);
   279 #endif
   280                 break;
   281             }
   282 #ifdef DEBUG_XEVENTS
   283             printf("window %p: FocusOut!\n", data);
   284 #endif
   285             data->pending_focus = PENDING_FOCUS_OUT;
   286             data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME;
   287         }
   288         break;
   289 
   290         /* Generated upon EnterWindow and FocusIn */
   291     case KeymapNotify:{
   292 #ifdef DEBUG_XEVENTS
   293             printf("window %p: KeymapNotify!\n", data);
   294 #endif
   295             /* FIXME:
   296                X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
   297              */
   298         }
   299         break;
   300 
   301         /* Has the keyboard layout changed? */
   302     case MappingNotify:{
   303 #ifdef DEBUG_XEVENTS
   304             printf("window %p: MappingNotify!\n", data);
   305 #endif
   306             X11_UpdateKeymap(_this);
   307         }
   308         break;
   309 
   310         /* Key press? */
   311     case KeyPress:{
   312             KeyCode keycode = xevent.xkey.keycode;
   313             KeySym keysym = NoSymbol;
   314             char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
   315             Status status = 0;
   316 
   317 #ifdef DEBUG_XEVENTS
   318             printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
   319 #endif
   320             SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
   321 #if 1
   322             if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN) {
   323                 int min_keycode, max_keycode;
   324                 XDisplayKeycodes(display, &min_keycode, &max_keycode);
   325 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
   326                 keysym = XkbKeycodeToKeysym(display, keycode, 0, 0);
   327 #else
   328                 keysym = XKeycodeToKeysym(display, keycode, 0);
   329 #endif
   330                 fprintf(stderr,
   331                         "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",
   332                         keycode, keycode - min_keycode, keysym,
   333                         XKeysymToString(keysym));
   334             }
   335 #endif
   336             /* */
   337             SDL_zero(text);
   338 #ifdef X_HAVE_UTF8_STRING
   339             if (data->ic) {
   340                 Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
   341                                   &keysym, &status);
   342             }
   343 #else
   344             XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
   345 #endif
   346             if (*text) {
   347                 SDL_SendKeyboardText(text);
   348             }
   349         }
   350         break;
   351 
   352         /* Key release? */
   353     case KeyRelease:{
   354             KeyCode keycode = xevent.xkey.keycode;
   355 
   356 #ifdef DEBUG_XEVENTS
   357             printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
   358 #endif
   359             if (X11_KeyRepeat(display, &xevent)) {
   360                 /* We're about to get a repeated key down, ignore the key up */
   361                 break;
   362             }
   363             SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
   364         }
   365         break;
   366 
   367         /* Have we been iconified? */
   368     case UnmapNotify:{
   369 #ifdef DEBUG_XEVENTS
   370             printf("window %p: UnmapNotify!\n", data);
   371 #endif
   372             X11_DispatchUnmapNotify(data);
   373         }
   374         break;
   375 
   376         /* Have we been restored? */
   377     case MapNotify:{
   378 #ifdef DEBUG_XEVENTS
   379             printf("window %p: MapNotify!\n", data);
   380 #endif
   381             X11_DispatchMapNotify(data);
   382         }
   383         break;
   384 
   385         /* Have we been resized or moved? */
   386     case ConfigureNotify:{
   387 #ifdef DEBUG_XEVENTS
   388             printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data,
   389                    xevent.xconfigure.x, xevent.xconfigure.y,
   390                    xevent.xconfigure.width, xevent.xconfigure.height);
   391 #endif
   392             if (xevent.xconfigure.x != data->last_xconfigure.x ||
   393                 xevent.xconfigure.y != data->last_xconfigure.y) {
   394                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
   395                                     xevent.xconfigure.x, xevent.xconfigure.y);
   396             }
   397             if (xevent.xconfigure.width != data->last_xconfigure.width ||
   398                 xevent.xconfigure.height != data->last_xconfigure.height) {
   399                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED,
   400                                     xevent.xconfigure.width,
   401                                     xevent.xconfigure.height);
   402             }
   403             data->last_xconfigure = xevent.xconfigure;
   404         }
   405         break;
   406 
   407         /* Have we been requested to quit (or another client message?) */
   408     case ClientMessage:{
   409             if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
   410                 (xevent.xclient.format == 32) &&
   411                 (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) {
   412                 Window root = DefaultRootWindow(display);
   413 
   414 #ifdef DEBUG_XEVENTS
   415                 printf("window %p: _NET_WM_PING\n", data);
   416 #endif
   417                 xevent.xclient.window = root;
   418                 XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
   419                 break;
   420             }
   421 
   422             else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
   423                 (xevent.xclient.format == 32) &&
   424                 (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
   425 
   426 #ifdef DEBUG_XEVENTS
   427                 printf("window %p: WM_DELETE_WINDOW\n", data);
   428 #endif
   429                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
   430                 break;
   431             }
   432         }
   433         break;
   434 
   435         /* Do we need to refresh ourselves? */
   436     case Expose:{
   437 #ifdef DEBUG_XEVENTS
   438             printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
   439 #endif
   440             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
   441         }
   442         break;
   443 
   444     case MotionNotify:{
   445             SDL_Mouse *mouse = SDL_GetMouse();  
   446             if(!mouse->relative_mode) {
   447 #ifdef DEBUG_MOTION
   448                 printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   449 #endif
   450 
   451                 SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);
   452             }
   453         }
   454         break;
   455 
   456     case ButtonPress:{
   457             int ticks = 0;
   458             if (X11_IsWheelEvent(display,&xevent,&ticks) == SDL_TRUE) {
   459                 SDL_SendMouseWheel(data->window, 0, ticks);
   460             }
   461             else {
   462                 SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button);
   463             }
   464         }
   465         break;
   466 
   467     case ButtonRelease:{
   468             SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button);
   469         }
   470         break;
   471 
   472     case PropertyNotify:{
   473 #ifdef DEBUG_XEVENTS
   474             unsigned char *propdata;
   475             int status, real_format;
   476             Atom real_type;
   477             unsigned long items_read, items_left, i;
   478 
   479             char *name = XGetAtomName(display, xevent.xproperty.atom);
   480             if (name) {
   481                 printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
   482                 XFree(name);
   483             }
   484 
   485             status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
   486             if (status == Success && items_read > 0) {
   487                 if (real_type == XA_INTEGER) {
   488                     int *values = (int *)propdata;
   489 
   490                     printf("{");
   491                     for (i = 0; i < items_read; i++) {
   492                         printf(" %d", values[i]);
   493                     }
   494                     printf(" }\n");
   495                 } else if (real_type == XA_CARDINAL) {
   496                     if (real_format == 32) {
   497                         Uint32 *values = (Uint32 *)propdata;
   498 
   499                         printf("{");
   500                         for (i = 0; i < items_read; i++) {
   501                             printf(" %d", values[i]);
   502                         }
   503                         printf(" }\n");
   504                     } else if (real_format == 16) {
   505                         Uint16 *values = (Uint16 *)propdata;
   506 
   507                         printf("{");
   508                         for (i = 0; i < items_read; i++) {
   509                             printf(" %d", values[i]);
   510                         }
   511                         printf(" }\n");
   512                     } else if (real_format == 8) {
   513                         Uint8 *values = (Uint8 *)propdata;
   514 
   515                         printf("{");
   516                         for (i = 0; i < items_read; i++) {
   517                             printf(" %d", values[i]);
   518                         }
   519                         printf(" }\n");
   520                     }
   521                 } else if (real_type == XA_STRING ||
   522                            real_type == videodata->UTF8_STRING) {
   523                     printf("{ \"%s\" }\n", propdata);
   524                 } else if (real_type == XA_ATOM) {
   525                     Atom *atoms = (Atom *)propdata;
   526 
   527                     printf("{");
   528                     for (i = 0; i < items_read; i++) {
   529                         char *name = XGetAtomName(display, atoms[i]);
   530                         if (name) {
   531                             printf(" %s", name);
   532                             XFree(name);
   533                         }
   534                     }
   535                     printf(" }\n");
   536                 } else {
   537                     char *name = XGetAtomName(display, real_type);
   538                     printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN");
   539                     if (name) {
   540                         XFree(name);
   541                     }
   542                 }
   543             }
   544             if (status == Success) {
   545                 XFree(propdata);
   546             }
   547 #endif /* DEBUG_XEVENTS */
   548 
   549             if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
   550                 /* Get the new state from the window manager.
   551                    Compositing window managers can alter visibility of windows
   552                    without ever mapping / unmapping them, so we handle that here,
   553                    because they use the NETWM protocol to notify us of changes.
   554                  */
   555                 Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
   556                 if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) {
   557                     if (flags & SDL_WINDOW_HIDDEN) {
   558                         X11_DispatchUnmapNotify(data);
   559                     } else {
   560                         X11_DispatchMapNotify(data);
   561                     }
   562                 }
   563             }
   564         }
   565         break;
   566 
   567     /* Copy the selection from XA_CUT_BUFFER0 to the requested property */
   568     case SelectionRequest: {
   569             XSelectionRequestEvent *req;
   570             XEvent sevent;
   571             int seln_format;
   572             unsigned long nbytes;
   573             unsigned long overflow;
   574             unsigned char *seln_data;
   575 
   576             req = &xevent.xselectionrequest;
   577 #ifdef DEBUG_XEVENTS
   578             printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data,
   579                 req->requestor, req->target);
   580 #endif
   581 
   582             SDL_zero(sevent);
   583             sevent.xany.type = SelectionNotify;
   584             sevent.xselection.selection = req->selection;
   585             sevent.xselection.target = None;
   586             sevent.xselection.property = None;
   587             sevent.xselection.requestor = req->requestor;
   588             sevent.xselection.time = req->time;
   589             if (XGetWindowProperty(display, DefaultRootWindow(display),
   590                     XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target,
   591                     &sevent.xselection.target, &seln_format, &nbytes,
   592                     &overflow, &seln_data) == Success) {
   593                 if (sevent.xselection.target == req->target) {
   594                     XChangeProperty(display, req->requestor, req->property,
   595                         sevent.xselection.target, seln_format, PropModeReplace,
   596                         seln_data, nbytes);
   597                     sevent.xselection.property = req->property;
   598                 }
   599                 XFree(seln_data);
   600             }
   601             XSendEvent(display, req->requestor, False, 0, &sevent);
   602             XSync(display, False);
   603         }
   604         break;
   605 
   606     case SelectionNotify: {
   607 #ifdef DEBUG_XEVENTS
   608             printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
   609                 xevent.xselection.requestor, xevent.xselection.target);
   610 #endif
   611             videodata->selection_waiting = SDL_FALSE;
   612         }
   613         break;
   614 
   615     default:{
   616 #ifdef DEBUG_XEVENTS
   617             printf("window %p: Unhandled event %d\n", data, xevent.type);
   618 #endif
   619         }
   620         break;
   621     }
   622 }
   623 
   624 static void
   625 X11_HandleFocusChanges(_THIS)
   626 {
   627     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   628     int i;
   629 
   630     if (videodata && videodata->windowlist) {
   631         for (i = 0; i < videodata->numwindows; ++i) {
   632             SDL_WindowData *data = videodata->windowlist[i];
   633             if (data && data->pending_focus != PENDING_FOCUS_NONE) {
   634                 Uint32 now = SDL_GetTicks();
   635                 if ( (int)(data->pending_focus_time-now) <= 0 ) {
   636                     if ( data->pending_focus == PENDING_FOCUS_IN ) {
   637                         X11_DispatchFocusIn(data);
   638                     } else {
   639                         X11_DispatchFocusOut(data);
   640                     }
   641                     data->pending_focus = PENDING_FOCUS_NONE;
   642                 }
   643             }
   644         }
   645     }
   646 }
   647 /* Ack!  XPending() actually performs a blocking read if no events available */
   648 static int
   649 X11_Pending(Display * display)
   650 {
   651     /* Flush the display connection and look to see if events are queued */
   652     XFlush(display);
   653     if (XEventsQueued(display, QueuedAlready)) {
   654         return (1);
   655     }
   656 
   657     /* More drastic measures are required -- see if X is ready to talk */
   658     {
   659         static struct timeval zero_time;        /* static == 0 */
   660         int x11_fd;
   661         fd_set fdset;
   662 
   663         x11_fd = ConnectionNumber(display);
   664         FD_ZERO(&fdset);
   665         FD_SET(x11_fd, &fdset);
   666         if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
   667             return (XPending(display));
   668         }
   669     }
   670 
   671     /* Oh well, nothing is ready .. */
   672     return (0);
   673 }
   674 
   675 
   676 /* !!! FIXME: this should be exposed in a header, or something. */
   677 int SDL_GetNumTouch(void);
   678 void SDL_dbus_screensaver_tickle(_THIS);
   679 
   680 void
   681 X11_PumpEvents(_THIS)
   682 {
   683     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   684 
   685     /* Update activity every 30 seconds to prevent screensaver */
   686     if (_this->suspend_screensaver) {
   687         Uint32 now = SDL_GetTicks();
   688         if (!data->screensaver_activity ||
   689             (int) (now - data->screensaver_activity) >= 30000) {
   690             XResetScreenSaver(data->display);
   691 
   692             #if SDL_USE_LIBDBUS
   693             SDL_dbus_screensaver_tickle(_this);
   694             #endif
   695 
   696             data->screensaver_activity = now;
   697         }
   698     }   
   699 
   700     /* Keep processing pending events */
   701     while (X11_Pending(data->display)) {
   702         X11_DispatchEvent(_this);
   703     }
   704 
   705     /* FIXME: Only need to do this when there are pending focus changes */
   706     X11_HandleFocusChanges(_this);
   707 
   708     /*Dont process evtouch events if XInput2 multitouch is supported*/
   709     if(X11_Xinput2IsMultitouchSupported()) {
   710         return;
   711     }
   712 
   713 #ifdef SDL_INPUT_LINUXEV
   714     /* Process Touch events*/
   715     int i = 0,rd;
   716     struct input_event ev[64];
   717     int size = sizeof (struct input_event);
   718 
   719 /* !!! FIXME: clean the tabstops out of here. */
   720     for(i = 0;i < SDL_GetNumTouch();++i) {
   721 	SDL_Touch* touch = SDL_GetTouchIndex(i);
   722 	if(!touch) printf("Touch %i/%i DNE\n",i,SDL_GetNumTouch());
   723 	EventTouchData* data;
   724 	data = (EventTouchData*)(touch->driverdata);
   725 	if(data == NULL) {
   726 	  printf("No driver data\n");
   727 	  continue;
   728 	}
   729 	if(data->eventStream <= 0) 
   730 	    printf("Error: Couldn't open stream\n");
   731 	rd = read(data->eventStream, ev, size * 64);
   732 	if(rd >= size) {
   733 	    for (i = 0; i < rd / sizeof(struct input_event); i++) {
   734 		switch (ev[i].type) {
   735 		case EV_ABS:
   736 		    switch (ev[i].code) {
   737 			case ABS_X:
   738 			    data->x = ev[i].value;
   739 			    break;
   740 			case ABS_Y:
   741 			    data->y = ev[i].value;
   742 			    break;
   743 			case ABS_PRESSURE:
   744 			    data->pressure = ev[i].value;
   745 			    if(data->pressure < 0) data->pressure = 0;
   746 			    break;
   747 			case ABS_MISC:
   748 			    if(ev[i].value == 0)
   749 			        data->up = SDL_TRUE;			    
   750 			    break;
   751 			}
   752 		    break;
   753 		case EV_MSC:
   754 			if(ev[i].code == MSC_SERIAL)
   755 				data->finger = ev[i].value;
   756 			break;
   757 		case EV_KEY:
   758 			if(ev[i].code == BTN_TOUCH)
   759 			    if(ev[i].value == 0)
   760 			        data->up = SDL_TRUE;
   761 			break;
   762 		case EV_SYN:
   763 		  if(!data->down) {
   764 		      data->down = SDL_TRUE;
   765 		      SDL_SendFingerDown(touch->id,data->finger,
   766 		    		  data->down, data->x, data->y,
   767 		    		  data->pressure);
   768 		  }
   769 		  else if(!data->up)
   770 		    SDL_SendTouchMotion(touch->id,data->finger, 
   771 					SDL_FALSE, data->x,data->y,
   772 					data->pressure);
   773 		  else
   774 		  {
   775 		      data->down = SDL_FALSE;
   776 			  SDL_SendFingerDown(touch->id,data->finger,
   777 					  data->down, data->x,data->y,
   778 					  data->pressure);
   779 			  data->x = -1;
   780 			  data->y = -1;
   781 			  data->pressure = -1;
   782 			  data->finger = 0;
   783 			  data->up = SDL_FALSE;
   784 		  }
   785 		  break;		
   786 		}
   787 	    }
   788 	}
   789     }
   790 #endif
   791 }
   792 
   793 
   794 void
   795 X11_SuspendScreenSaver(_THIS)
   796 {
   797 #if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
   798     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   799     int dummy;
   800     int major_version, minor_version;
   801 
   802     if (SDL_X11_HAVE_XSS) {
   803         /* XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
   804         if (!XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
   805             !XScreenSaverQueryVersion(data->display,
   806                                       &major_version, &minor_version) ||
   807             major_version < 1 || (major_version == 1 && minor_version < 1)) {
   808             return;
   809         }
   810 
   811         XScreenSaverSuspend(data->display, _this->suspend_screensaver);
   812         XResetScreenSaver(data->display);
   813     }
   814 #endif
   815 
   816 #if SDL_USE_LIBDBUS
   817     if (_this->suspend_screensaver) {
   818         SDL_dbus_screensaver_tickle(_this);
   819     }
   820 #endif
   821 }
   822 
   823 #endif /* SDL_VIDEO_DRIVER_X11 */
   824 
   825 /* vi: set ts=4 sw=4 expandtab: */