src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
permissions -rw-r--r--
more tweaking indent options
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* Handle the event stream, converting X11 events into SDL events */
    25 
    26 #include <setjmp.h>
    27 #include <X11/Xlib.h>
    28 #include <X11/Xutil.h>
    29 #include <X11/keysym.h>
    30 #ifdef __SVR4
    31 #include <X11/Sunkeysym.h>
    32 #endif
    33 #include <sys/types.h>
    34 #include <sys/time.h>
    35 #include <unistd.h>
    36 
    37 #include "SDL_timer.h"
    38 #include "SDL_syswm.h"
    39 #include "../SDL_sysvideo.h"
    40 #include "../../events/SDL_sysevents.h"
    41 #include "../../events/SDL_events_c.h"
    42 #include "SDL_x11video.h"
    43 #include "SDL_x11dga_c.h"
    44 #include "SDL_x11modes_c.h"
    45 #include "SDL_x11image_c.h"
    46 #include "SDL_x11gamma_c.h"
    47 #include "SDL_x11wm_c.h"
    48 #include "SDL_x11mouse_c.h"
    49 #include "SDL_x11events_c.h"
    50 
    51 
    52 /* Define this if you want to debug X11 events */
    53 /*#define DEBUG_XEVENTS*/
    54 
    55 /* The translation tables from an X11 keysym to a SDL keysym */
    56 static SDLKey ODD_keymap[256];
    57 static SDLKey MISC_keymap[256];
    58 SDLKey X11_TranslateKeycode(Display * display, KeyCode kc);
    59 
    60 
    61 #ifdef X_HAVE_UTF8_STRING
    62 Uint32
    63 Utf8ToUcs4(const Uint8 * utf8)
    64 {
    65     Uint32 c;
    66     int i = 1;
    67     int noOctets = 0;
    68     int firstOctetMask = 0;
    69     unsigned char firstOctet = utf8[0];
    70     if (firstOctet < 0x80) {
    71         /*
    72            Characters in the range:
    73            00000000 to 01111111 (ASCII Range)
    74            are stored in one octet:
    75            0xxxxxxx (The same as its ASCII representation)
    76            The least 6 significant bits of the first octet is the most 6 significant nonzero bits
    77            of the UCS4 representation.
    78          */
    79         noOctets = 1;
    80         firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
    81     } else if ((firstOctet & 0xE0)      /* get the most 3 significant bits by AND'ing with 11100000 */
    82                == 0xC0) {       /* see if those 3 bits are 110. If so, the char is in this range */
    83         /*
    84            Characters in the range:
    85            00000000 10000000 to 00000111 11111111
    86            are stored in two octets:
    87            110xxxxx 10xxxxxx
    88            The least 5 significant bits of the first octet is the most 5 significant nonzero bits
    89            of the UCS4 representation.
    90          */
    91         noOctets = 2;
    92         firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
    93     } else if ((firstOctet & 0xF0)      /* get the most 4 significant bits by AND'ing with 11110000 */
    94                == 0xE0) {       /* see if those 4 bits are 1110. If so, the char is in this range */
    95         /*
    96            Characters in the range:
    97            00001000 00000000 to 11111111 11111111
    98            are stored in three octets:
    99            1110xxxx 10xxxxxx 10xxxxxx
   100            The least 4 significant bits of the first octet is the most 4 significant nonzero bits
   101            of the UCS4 representation.
   102          */
   103         noOctets = 3;
   104         firstOctetMask = 0x0F;  /* 0000(1111) - The most 4 significant bits are ignored */
   105     } else if ((firstOctet & 0xF8)      /* get the most 5 significant bits by AND'ing with 11111000 */
   106                == 0xF0) {       /* see if those 5 bits are 11110. If so, the char is in this range */
   107         /*
   108            Characters in the range:
   109            00000001 00000000 00000000 to 00011111 11111111 11111111
   110            are stored in four octets:
   111            11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   112            The least 3 significant bits of the first octet is the most 3 significant nonzero bits
   113            of the UCS4 representation.
   114          */
   115         noOctets = 4;
   116         firstOctetMask = 0x07;  /* 11110(111) - The most 5 significant bits are ignored */
   117     } else if ((firstOctet & 0xFC)      /* get the most 6 significant bits by AND'ing with 11111100 */
   118                == 0xF8) {       /* see if those 6 bits are 111110. If so, the char is in this range */
   119         /*
   120            Characters in the range:
   121            00000000 00100000 00000000 00000000 to
   122            00000011 11111111 11111111 11111111
   123            are stored in five octets:
   124            111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   125            The least 2 significant bits of the first octet is the most 2 significant nonzero bits
   126            of the UCS4 representation.
   127          */
   128         noOctets = 5;
   129         firstOctetMask = 0x03;  /* 111110(11) - The most 6 significant bits are ignored */
   130     } else if ((firstOctet & 0xFE)      /* get the most 7 significant bits by AND'ing with 11111110 */
   131                == 0xFC) {       /* see if those 7 bits are 1111110. If so, the char is in this range */
   132         /*
   133            Characters in the range:
   134            00000100 00000000 00000000 00000000 to
   135            01111111 11111111 11111111 11111111
   136            are stored in six octets:
   137            1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   138            The least significant bit of the first octet is the most significant nonzero bit
   139            of the UCS4 representation.
   140          */
   141         noOctets = 6;
   142         firstOctetMask = 0x01;  /* 1111110(1) - The most 7 significant bits are ignored */
   143     } else
   144         return 0;               /* The given chunk is not a valid UTF-8 encoded Unicode character */
   145 
   146     /*
   147        The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
   148        of the UCS4 representation.
   149        The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   150        firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   151        This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   152        number of continuing octets (if any) and leave only the free bits (the x's)
   153        Sample:
   154        1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   155        2-octets:  110xxxxx  &  00011111 = 000xxxxx
   156      */
   157     c = firstOctet & firstOctetMask;
   158 
   159     /* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   160     for (i = 1; i < noOctets; i++) {
   161         /* A valid continuing octet is of the form 10xxxxxx */
   162         if ((utf8[i] & 0xC0)    /* get the most 2 significant bits by AND'ing with 11000000 */
   163             !=0x80)
   164             /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   165             /*The given chunk is a partial sequence at the end of a string that could
   166                begin a valid character */
   167             return 0;
   168 
   169         /* Make room for the next 6-bits */
   170         c <<= 6;
   171 
   172         /*
   173            Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   174            of c.ucs4 with them.
   175            This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   176          */
   177         c |= utf8[i] & 0x3F;
   178     }
   179     return c;
   180 }
   181 #endif
   182 
   183 /* Check to see if this is a repeated key.
   184    (idea shamelessly lifted from GII -- thanks guys! :)
   185  */
   186 static int
   187 X11_KeyRepeat(Display * display, XEvent * event)
   188 {
   189     XEvent peekevent;
   190     int repeated;
   191 
   192     repeated = 0;
   193     if (XPending(display)) {
   194         XPeekEvent(display, &peekevent);
   195         if ((peekevent.type == KeyPress) &&
   196             (peekevent.xkey.keycode == event->xkey.keycode) &&
   197             ((peekevent.xkey.time - event->xkey.time) < 2)) {
   198             repeated = 1;
   199             XNextEvent(display, &peekevent);
   200         }
   201     }
   202     return (repeated);
   203 }
   204 
   205 /* Note:  The X server buffers and accumulates mouse motion events, so
   206    the motion event generated by the warp may not appear exactly as we
   207    expect it to.  We work around this (and improve performance) by only
   208    warping the pointer when it reaches the edge, and then wait for it.
   209 */
   210 #define MOUSE_FUDGE_FACTOR	8
   211 
   212 static __inline__ int
   213 X11_WarpedMotion(_THIS, XEvent * xevent)
   214 {
   215     int w, h, i;
   216     int deltax, deltay;
   217     int posted;
   218 
   219     w = SDL_VideoSurface->w;
   220     h = SDL_VideoSurface->h;
   221     deltax = xevent->xmotion.x - mouse_last.x;
   222     deltay = xevent->xmotion.y - mouse_last.y;
   223 #ifdef DEBUG_MOTION
   224     printf("Warped mouse motion: %d,%d\n", deltax, deltay);
   225 #endif
   226     mouse_last.x = xevent->xmotion.x;
   227     mouse_last.y = xevent->xmotion.y;
   228     posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   229 
   230     if ((xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
   231         (xevent->xmotion.x > (w - MOUSE_FUDGE_FACTOR)) ||
   232         (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
   233         (xevent->xmotion.y > (h - MOUSE_FUDGE_FACTOR))) {
   234         /* Get the events that have accumulated */
   235         while (XCheckTypedEvent(SDL_Display, MotionNotify, xevent)) {
   236             deltax = xevent->xmotion.x - mouse_last.x;
   237             deltay = xevent->xmotion.y - mouse_last.y;
   238 #ifdef DEBUG_MOTION
   239             printf("Extra mouse motion: %d,%d\n", deltax, deltay);
   240 #endif
   241             mouse_last.x = xevent->xmotion.x;
   242             mouse_last.y = xevent->xmotion.y;
   243             posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   244         }
   245         mouse_last.x = w / 2;
   246         mouse_last.y = h / 2;
   247         XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
   248                      mouse_last.x, mouse_last.y);
   249         for (i = 0; i < 10; ++i) {
   250             XMaskEvent(SDL_Display, PointerMotionMask, xevent);
   251             if ((xevent->xmotion.x >
   252                  (mouse_last.x - MOUSE_FUDGE_FACTOR)) &&
   253                 (xevent->xmotion.x <
   254                  (mouse_last.x + MOUSE_FUDGE_FACTOR)) &&
   255                 (xevent->xmotion.y >
   256                  (mouse_last.y - MOUSE_FUDGE_FACTOR)) &&
   257                 (xevent->xmotion.y < (mouse_last.y + MOUSE_FUDGE_FACTOR))) {
   258                 break;
   259             }
   260 #ifdef DEBUG_XEVENTS
   261             printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x,
   262                    xevent->xmotion.y);
   263 #endif
   264         }
   265 #ifdef DEBUG_XEVENTS
   266         if (i == 10) {
   267             printf("Warning: didn't detect mouse warp motion\n");
   268         }
   269 #endif
   270     }
   271     return (posted);
   272 }
   273 
   274 static int
   275 X11_DispatchEvent(_THIS)
   276 {
   277     int posted;
   278     XEvent xevent;
   279 
   280     SDL_memset(&xevent, '\0', sizeof(XEvent));  /* valgrind fix. --ryan. */
   281     XNextEvent(SDL_Display, &xevent);
   282 
   283     posted = 0;
   284     switch (xevent.type) {
   285 
   286         /* Gaining mouse coverage? */
   287     case EnterNotify:
   288         {
   289 #ifdef DEBUG_XEVENTS
   290             printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x,
   291                    xevent.xcrossing.y);
   292             if (xevent.xcrossing.mode == NotifyGrab)
   293                 printf("Mode: NotifyGrab\n");
   294             if (xevent.xcrossing.mode == NotifyUngrab)
   295                 printf("Mode: NotifyUngrab\n");
   296 #endif
   297             if ((xevent.xcrossing.mode != NotifyGrab) &&
   298                 (xevent.xcrossing.mode != NotifyUngrab)) {
   299                 if (SDL_CurrentWindow.input_grab == SDL_GRAB_OFF) {
   300                     posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   301                 }
   302                 posted = SDL_PrivateMouseMotion(0, 0,
   303                                                 xevent.xcrossing.x,
   304                                                 xevent.xcrossing.y);
   305             }
   306         }
   307         break;
   308 
   309         /* Losing mouse coverage? */
   310     case LeaveNotify:
   311         {
   312 #ifdef DEBUG_XEVENTS
   313             printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x,
   314                    xevent.xcrossing.y);
   315             if (xevent.xcrossing.mode == NotifyGrab)
   316                 printf("Mode: NotifyGrab\n");
   317             if (xevent.xcrossing.mode == NotifyUngrab)
   318                 printf("Mode: NotifyUngrab\n");
   319 #endif
   320             if ((xevent.xcrossing.mode != NotifyGrab) &&
   321                 (xevent.xcrossing.mode != NotifyUngrab) &&
   322                 (xevent.xcrossing.detail != NotifyInferior)) {
   323                 if (SDL_CurrentWindow.input_grab == SDL_GRAB_OFF) {
   324                     posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
   325                 } else {
   326                     posted = SDL_PrivateMouseMotion(0, 0,
   327                                                     xevent.xcrossing.x,
   328                                                     xevent.xcrossing.y);
   329                 }
   330             }
   331         }
   332         break;
   333 
   334         /* Gaining input focus? */
   335     case FocusIn:
   336         {
   337 #ifdef DEBUG_XEVENTS
   338             printf("FocusIn!\n");
   339 #endif
   340             posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   341 
   342 #ifdef X_HAVE_UTF8_STRING
   343             if (SDL_IC != NULL) {
   344                 XSetICFocus(SDL_IC);
   345             }
   346 #endif
   347             /* Queue entry into fullscreen mode */
   348             switch_waiting = 0x01 | SDL_FULLSCREEN;
   349             switch_time = SDL_GetTicks() + 1500;
   350         }
   351         break;
   352 
   353         /* Losing input focus? */
   354     case FocusOut:
   355         {
   356 #ifdef DEBUG_XEVENTS
   357             printf("FocusOut!\n");
   358 #endif
   359             posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
   360 
   361 #ifdef X_HAVE_UTF8_STRING
   362             if (SDL_IC != NULL) {
   363                 XUnsetICFocus(SDL_IC);
   364             }
   365 #endif
   366             /* Queue leaving fullscreen mode */
   367             switch_waiting = 0x01;
   368             switch_time = SDL_GetTicks() + 200;
   369         }
   370         break;
   371 
   372         /* Generated upon EnterWindow and FocusIn */
   373     case KeymapNotify:
   374         {
   375 #ifdef DEBUG_XEVENTS
   376             printf("KeymapNotify!\n");
   377 #endif
   378             X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
   379         }
   380         break;
   381 
   382         /* Mouse motion? */
   383     case MotionNotify:
   384         {
   385             if (SDL_VideoSurface) {
   386                 if (mouse_relative) {
   387                     if (using_dga & DGA_MOUSE) {
   388 #ifdef DEBUG_MOTION
   389                         printf("DGA motion: %d,%d\n",
   390                                xevent.xmotion.x_root, xevent.xmotion.y_root);
   391 #endif
   392                         posted = SDL_PrivateMouseMotion(0, 1,
   393                                                         xevent.
   394                                                         xmotion.
   395                                                         x_root,
   396                                                         xevent.
   397                                                         xmotion.y_root);
   398                     } else {
   399                         posted = X11_WarpedMotion(_this, &xevent);
   400                     }
   401                 } else {
   402 #ifdef DEBUG_MOTION
   403                     printf("X11 motion: %d,%d\n", xevent.xmotion.x,
   404                            xevent.xmotion.y);
   405 #endif
   406                     posted = SDL_PrivateMouseMotion(0, 0,
   407                                                     xevent.xmotion.x,
   408                                                     xevent.xmotion.y);
   409                 }
   410             }
   411         }
   412         break;
   413 
   414         /* Mouse button press? */
   415     case ButtonPress:
   416         {
   417             posted = SDL_PrivateMouseButton(SDL_PRESSED,
   418                                             xevent.xbutton.button, 0, 0);
   419         }
   420         break;
   421 
   422         /* Mouse button release? */
   423     case ButtonRelease:
   424         {
   425             posted = SDL_PrivateMouseButton(SDL_RELEASED,
   426                                             xevent.xbutton.button, 0, 0);
   427         }
   428         break;
   429 
   430         /* Key press? */
   431     case KeyPress:
   432         {
   433             static SDL_keysym saved_keysym;
   434             SDL_keysym keysym;
   435             KeyCode keycode = xevent.xkey.keycode;
   436 
   437 #ifdef DEBUG_XEVENTS
   438             printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   439 #endif
   440             /* Get the translated SDL virtual keysym */
   441             if (keycode) {
   442                 keysym.scancode = keycode;
   443                 keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   444                 keysym.mod = KMOD_NONE;
   445                 keysym.unicode = 0;
   446             } else {
   447                 keysym = saved_keysym;
   448             }
   449 
   450             /* If we're not doing translation, we're done! */
   451             if (!SDL_TranslateUNICODE) {
   452                 posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   453                 break;
   454             }
   455 
   456             if (XFilterEvent(&xevent, None)) {
   457                 if (xevent.xkey.keycode) {
   458                     posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   459                 } else {
   460                     /* Save event to be associated with IM text
   461                        In 1.3 we'll have a text event instead.. */
   462                     saved_keysym = keysym;
   463                 }
   464                 break;
   465             }
   466 
   467             /* Look up the translated value for the key event */
   468 #ifdef X_HAVE_UTF8_STRING
   469             if (SDL_IC != NULL) {
   470                 static Status state;
   471                 /* A UTF-8 character can be at most 6 bytes */
   472                 char keybuf[6];
   473                 if (Xutf8LookupString(SDL_IC, &xevent.xkey,
   474                                       keybuf, sizeof(keybuf), NULL, &state)) {
   475                     keysym.unicode = Utf8ToUcs4((Uint8 *) keybuf);
   476                 }
   477             } else
   478 #endif
   479             {
   480                 static XComposeStatus state;
   481                 char keybuf[32];
   482 
   483                 if (XLookupString(&xevent.xkey,
   484                                   keybuf, sizeof(keybuf), NULL, &state)) {
   485                     /*
   486                      * FIXME: XLookupString() may yield more than one
   487                      * character, so we need a mechanism to allow for
   488                      * this (perhaps null keypress events with a
   489                      * unicode value)
   490                      */
   491                     keysym.unicode = (Uint8) keybuf[0];
   492                 }
   493             }
   494             posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   495         }
   496         break;
   497 
   498         /* Key release? */
   499     case KeyRelease:
   500         {
   501             SDL_keysym keysym;
   502             KeyCode keycode = xevent.xkey.keycode;
   503 
   504 #ifdef DEBUG_XEVENTS
   505             printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   506 #endif
   507             /* Check to see if this is a repeated key */
   508             if (X11_KeyRepeat(SDL_Display, &xevent)) {
   509                 break;
   510             }
   511 
   512             /* Get the translated SDL virtual keysym */
   513             keysym.scancode = keycode;
   514             keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   515             keysym.mod = KMOD_NONE;
   516             keysym.unicode = 0;
   517 
   518             posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
   519         }
   520         break;
   521 
   522         /* Have we been iconified? */
   523     case UnmapNotify:
   524         {
   525 #ifdef DEBUG_XEVENTS
   526             printf("UnmapNotify!\n");
   527 #endif
   528             /* If we're active, make ourselves inactive */
   529             if (SDL_GetAppState() & SDL_APPACTIVE) {
   530                 /* Swap out the gamma before we go inactive */
   531                 X11_SwapVidModeGamma(_this);
   532 
   533                 /* Send an internal deactivate event */
   534                 posted = SDL_PrivateAppActive(0,
   535                                               SDL_APPACTIVE |
   536                                               SDL_APPINPUTFOCUS);
   537             }
   538         }
   539         break;
   540 
   541         /* Have we been restored? */
   542     case MapNotify:
   543         {
   544 #ifdef DEBUG_XEVENTS
   545             printf("MapNotify!\n");
   546 #endif
   547             /* If we're not active, make ourselves active */
   548             if (!(SDL_GetAppState() & SDL_APPACTIVE)) {
   549                 /* Send an internal activate event */
   550                 posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
   551 
   552                 /* Now that we're active, swap the gamma back */
   553                 X11_SwapVidModeGamma(_this);
   554             }
   555 
   556             if (SDL_VideoSurface &&
   557                 (SDL_VideoSurface->flags & SDL_FULLSCREEN)) {
   558                 X11_EnterFullScreen(_this);
   559             } else {
   560                 X11_GrabInputNoLock(_this, SDL_CurrentWindow.input_grab);
   561             }
   562             X11_CheckMouseModeNoLock(_this);
   563 
   564             if (SDL_VideoSurface) {
   565                 X11_RefreshDisplay(_this);
   566             }
   567         }
   568         break;
   569 
   570         /* Have we been resized or moved? */
   571     case ConfigureNotify:
   572         {
   573 #ifdef DEBUG_XEVENTS
   574             printf("ConfigureNotify! (resize: %dx%d)\n",
   575                    xevent.xconfigure.width, xevent.xconfigure.height);
   576 #endif
   577             if (SDL_VideoSurface) {
   578                 if ((xevent.xconfigure.width != SDL_VideoSurface->w) ||
   579                     (xevent.xconfigure.height != SDL_VideoSurface->h)) {
   580                     /* FIXME: Find a better fix for the bug with KDE 1.2 */
   581                     if (!((xevent.xconfigure.width == 32) &&
   582                           (xevent.xconfigure.height == 32))) {
   583                         SDL_PrivateResize(xevent.xconfigure.width,
   584                                           xevent.xconfigure.height);
   585                     }
   586                 } else {
   587                     /* OpenGL windows need to know about the change */
   588                     if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) {
   589                         SDL_PrivateExpose();
   590                     }
   591                 }
   592             }
   593         }
   594         break;
   595 
   596         /* Have we been requested to quit (or another client message?) */
   597     case ClientMessage:
   598         {
   599             if ((xevent.xclient.format == 32) &&
   600                 (xevent.xclient.data.l[0] == WM_DELETE_WINDOW)) {
   601                 posted = SDL_PrivateQuit();
   602             } else if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
   603                 SDL_SysWMmsg wmmsg;
   604 
   605                 SDL_VERSION(&wmmsg.version);
   606                 wmmsg.subsystem = SDL_SYSWM_X11;
   607                 wmmsg.event.xevent = xevent;
   608                 posted = SDL_PrivateSysWMEvent(&wmmsg);
   609             }
   610         }
   611         break;
   612 
   613         /* Do we need to refresh ourselves? */
   614     case Expose:
   615         {
   616 #ifdef DEBUG_XEVENTS
   617             printf("Expose (count = %d)\n", xevent.xexpose.count);
   618 #endif
   619             if (SDL_VideoSurface && (xevent.xexpose.count == 0)) {
   620                 X11_RefreshDisplay(_this);
   621             }
   622         }
   623         break;
   624 
   625     default:
   626         {
   627 #ifdef DEBUG_XEVENTS
   628             printf("Unhandled event %d\n", xevent.type);
   629 #endif
   630             /* Only post the event if we're watching for it */
   631             if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
   632                 SDL_SysWMmsg wmmsg;
   633 
   634                 SDL_VERSION(&wmmsg.version);
   635                 wmmsg.subsystem = SDL_SYSWM_X11;
   636                 wmmsg.event.xevent = xevent;
   637                 posted = SDL_PrivateSysWMEvent(&wmmsg);
   638             }
   639         }
   640         break;
   641     }
   642     return (posted);
   643 }
   644 
   645 /* Ack!  XPending() actually performs a blocking read if no events available */
   646 int
   647 X11_Pending(Display * display)
   648 {
   649     /* Flush the display connection and look to see if events are queued */
   650     XFlush(display);
   651     if (XEventsQueued(display, QueuedAlready)) {
   652         return (1);
   653     }
   654 
   655     /* More drastic measures are required -- see if X is ready to talk */
   656     {
   657         static struct timeval zero_time;        /* static == 0 */
   658         int x11_fd;
   659         fd_set fdset;
   660 
   661         x11_fd = ConnectionNumber(display);
   662         FD_ZERO(&fdset);
   663         FD_SET(x11_fd, &fdset);
   664         if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
   665             return (XPending(display));
   666         }
   667     }
   668 
   669     /* Oh well, nothing is ready .. */
   670     return (0);
   671 }
   672 
   673 void
   674 X11_PumpEvents(_THIS)
   675 {
   676     int pending;
   677 
   678     /* Keep processing pending events */
   679     pending = 0;
   680     while (X11_Pending(SDL_Display)) {
   681         X11_DispatchEvent(_this);
   682         ++pending;
   683     }
   684     if (switch_waiting) {
   685         Uint32 now;
   686 
   687         now = SDL_GetTicks();
   688         if (pending || !SDL_VideoSurface) {
   689             /* Try again later... */
   690             if (switch_waiting & SDL_FULLSCREEN) {
   691                 switch_time = now + 1500;
   692             } else {
   693                 switch_time = now + 200;
   694             }
   695         } else if ((int) (switch_time - now) <= 0) {
   696             Uint32 go_fullscreen;
   697 
   698             go_fullscreen = switch_waiting & SDL_FULLSCREEN;
   699             switch_waiting = 0;
   700             if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
   701                 if (go_fullscreen) {
   702                     X11_EnterFullScreen(_this);
   703                 } else {
   704                     X11_LeaveFullScreen(_this);
   705                 }
   706             }
   707             /* Handle focus in/out when grabbed */
   708             if (go_fullscreen) {
   709                 X11_GrabInputNoLock(_this, SDL_CurrentWindow.input_grab);
   710             } else {
   711                 X11_GrabInputNoLock(_this, SDL_GRAB_OFF);
   712             }
   713             X11_CheckMouseModeNoLock(_this);
   714         }
   715     }
   716 }
   717 
   718 void
   719 X11_InitKeymap(void)
   720 {
   721     int i;
   722 
   723     /* Odd keys used in international keyboards */
   724     for (i = 0; i < SDL_arraysize(ODD_keymap); ++i)
   725         ODD_keymap[i] = SDLK_UNKNOWN;
   726 
   727     /* Some of these might be mappable to an existing SDLK_ code */
   728     ODD_keymap[XK_dead_grave & 0xFF] = SDLK_COMPOSE;
   729     ODD_keymap[XK_dead_acute & 0xFF] = SDLK_COMPOSE;
   730     ODD_keymap[XK_dead_tilde & 0xFF] = SDLK_COMPOSE;
   731     ODD_keymap[XK_dead_macron & 0xFF] = SDLK_COMPOSE;
   732     ODD_keymap[XK_dead_breve & 0xFF] = SDLK_COMPOSE;
   733     ODD_keymap[XK_dead_abovedot & 0xFF] = SDLK_COMPOSE;
   734     ODD_keymap[XK_dead_diaeresis & 0xFF] = SDLK_COMPOSE;
   735     ODD_keymap[XK_dead_abovering & 0xFF] = SDLK_COMPOSE;
   736     ODD_keymap[XK_dead_doubleacute & 0xFF] = SDLK_COMPOSE;
   737     ODD_keymap[XK_dead_caron & 0xFF] = SDLK_COMPOSE;
   738     ODD_keymap[XK_dead_cedilla & 0xFF] = SDLK_COMPOSE;
   739     ODD_keymap[XK_dead_ogonek & 0xFF] = SDLK_COMPOSE;
   740     ODD_keymap[XK_dead_iota & 0xFF] = SDLK_COMPOSE;
   741     ODD_keymap[XK_dead_voiced_sound & 0xFF] = SDLK_COMPOSE;
   742     ODD_keymap[XK_dead_semivoiced_sound & 0xFF] = SDLK_COMPOSE;
   743     ODD_keymap[XK_dead_belowdot & 0xFF] = SDLK_COMPOSE;
   744 #ifdef XK_dead_hook
   745     ODD_keymap[XK_dead_hook & 0xFF] = SDLK_COMPOSE;
   746 #endif
   747 #ifdef XK_dead_horn
   748     ODD_keymap[XK_dead_horn & 0xFF] = SDLK_COMPOSE;
   749 #endif
   750 
   751 #ifdef XK_dead_circumflex
   752     /* These X keysyms have 0xFE as the high byte */
   753     ODD_keymap[XK_dead_circumflex & 0xFF] = SDLK_CARET;
   754 #endif
   755 #ifdef XK_ISO_Level3_Shift
   756     ODD_keymap[XK_ISO_Level3_Shift & 0xFF] = SDLK_MODE; /* "Alt Gr" key */
   757 #endif
   758 
   759     /* Map the miscellaneous keys */
   760     for (i = 0; i < SDL_arraysize(MISC_keymap); ++i)
   761         MISC_keymap[i] = SDLK_UNKNOWN;
   762 
   763     /* These X keysyms have 0xFF as the high byte */
   764     MISC_keymap[XK_BackSpace & 0xFF] = SDLK_BACKSPACE;
   765     MISC_keymap[XK_Tab & 0xFF] = SDLK_TAB;
   766     MISC_keymap[XK_Clear & 0xFF] = SDLK_CLEAR;
   767     MISC_keymap[XK_Return & 0xFF] = SDLK_RETURN;
   768     MISC_keymap[XK_Pause & 0xFF] = SDLK_PAUSE;
   769     MISC_keymap[XK_Escape & 0xFF] = SDLK_ESCAPE;
   770     MISC_keymap[XK_Delete & 0xFF] = SDLK_DELETE;
   771 
   772     MISC_keymap[XK_KP_0 & 0xFF] = SDLK_KP0;     /* Keypad 0-9 */
   773     MISC_keymap[XK_KP_1 & 0xFF] = SDLK_KP1;
   774     MISC_keymap[XK_KP_2 & 0xFF] = SDLK_KP2;
   775     MISC_keymap[XK_KP_3 & 0xFF] = SDLK_KP3;
   776     MISC_keymap[XK_KP_4 & 0xFF] = SDLK_KP4;
   777     MISC_keymap[XK_KP_5 & 0xFF] = SDLK_KP5;
   778     MISC_keymap[XK_KP_6 & 0xFF] = SDLK_KP6;
   779     MISC_keymap[XK_KP_7 & 0xFF] = SDLK_KP7;
   780     MISC_keymap[XK_KP_8 & 0xFF] = SDLK_KP8;
   781     MISC_keymap[XK_KP_9 & 0xFF] = SDLK_KP9;
   782     MISC_keymap[XK_KP_Insert & 0xFF] = SDLK_KP0;
   783     MISC_keymap[XK_KP_End & 0xFF] = SDLK_KP1;
   784     MISC_keymap[XK_KP_Down & 0xFF] = SDLK_KP2;
   785     MISC_keymap[XK_KP_Page_Down & 0xFF] = SDLK_KP3;
   786     MISC_keymap[XK_KP_Left & 0xFF] = SDLK_KP4;
   787     MISC_keymap[XK_KP_Begin & 0xFF] = SDLK_KP5;
   788     MISC_keymap[XK_KP_Right & 0xFF] = SDLK_KP6;
   789     MISC_keymap[XK_KP_Home & 0xFF] = SDLK_KP7;
   790     MISC_keymap[XK_KP_Up & 0xFF] = SDLK_KP8;
   791     MISC_keymap[XK_KP_Page_Up & 0xFF] = SDLK_KP9;
   792     MISC_keymap[XK_KP_Delete & 0xFF] = SDLK_KP_PERIOD;
   793     MISC_keymap[XK_KP_Decimal & 0xFF] = SDLK_KP_PERIOD;
   794     MISC_keymap[XK_KP_Divide & 0xFF] = SDLK_KP_DIVIDE;
   795     MISC_keymap[XK_KP_Multiply & 0xFF] = SDLK_KP_MULTIPLY;
   796     MISC_keymap[XK_KP_Subtract & 0xFF] = SDLK_KP_MINUS;
   797     MISC_keymap[XK_KP_Add & 0xFF] = SDLK_KP_PLUS;
   798     MISC_keymap[XK_KP_Enter & 0xFF] = SDLK_KP_ENTER;
   799     MISC_keymap[XK_KP_Equal & 0xFF] = SDLK_KP_EQUALS;
   800 
   801     MISC_keymap[XK_Up & 0xFF] = SDLK_UP;
   802     MISC_keymap[XK_Down & 0xFF] = SDLK_DOWN;
   803     MISC_keymap[XK_Right & 0xFF] = SDLK_RIGHT;
   804     MISC_keymap[XK_Left & 0xFF] = SDLK_LEFT;
   805     MISC_keymap[XK_Insert & 0xFF] = SDLK_INSERT;
   806     MISC_keymap[XK_Home & 0xFF] = SDLK_HOME;
   807     MISC_keymap[XK_End & 0xFF] = SDLK_END;
   808     MISC_keymap[XK_Page_Up & 0xFF] = SDLK_PAGEUP;
   809     MISC_keymap[XK_Page_Down & 0xFF] = SDLK_PAGEDOWN;
   810 
   811     MISC_keymap[XK_F1 & 0xFF] = SDLK_F1;
   812     MISC_keymap[XK_F2 & 0xFF] = SDLK_F2;
   813     MISC_keymap[XK_F3 & 0xFF] = SDLK_F3;
   814     MISC_keymap[XK_F4 & 0xFF] = SDLK_F4;
   815     MISC_keymap[XK_F5 & 0xFF] = SDLK_F5;
   816     MISC_keymap[XK_F6 & 0xFF] = SDLK_F6;
   817     MISC_keymap[XK_F7 & 0xFF] = SDLK_F7;
   818     MISC_keymap[XK_F8 & 0xFF] = SDLK_F8;
   819     MISC_keymap[XK_F9 & 0xFF] = SDLK_F9;
   820     MISC_keymap[XK_F10 & 0xFF] = SDLK_F10;
   821     MISC_keymap[XK_F11 & 0xFF] = SDLK_F11;
   822     MISC_keymap[XK_F12 & 0xFF] = SDLK_F12;
   823     MISC_keymap[XK_F13 & 0xFF] = SDLK_F13;
   824     MISC_keymap[XK_F14 & 0xFF] = SDLK_F14;
   825     MISC_keymap[XK_F15 & 0xFF] = SDLK_F15;
   826 
   827     MISC_keymap[XK_Num_Lock & 0xFF] = SDLK_NUMLOCK;
   828     MISC_keymap[XK_Caps_Lock & 0xFF] = SDLK_CAPSLOCK;
   829     MISC_keymap[XK_Scroll_Lock & 0xFF] = SDLK_SCROLLOCK;
   830     MISC_keymap[XK_Shift_R & 0xFF] = SDLK_RSHIFT;
   831     MISC_keymap[XK_Shift_L & 0xFF] = SDLK_LSHIFT;
   832     MISC_keymap[XK_Control_R & 0xFF] = SDLK_RCTRL;
   833     MISC_keymap[XK_Control_L & 0xFF] = SDLK_LCTRL;
   834     MISC_keymap[XK_Alt_R & 0xFF] = SDLK_RALT;
   835     MISC_keymap[XK_Alt_L & 0xFF] = SDLK_LALT;
   836     MISC_keymap[XK_Meta_R & 0xFF] = SDLK_RMETA;
   837     MISC_keymap[XK_Meta_L & 0xFF] = SDLK_LMETA;
   838     MISC_keymap[XK_Super_L & 0xFF] = SDLK_LSUPER;       /* Left "Windows" */
   839     MISC_keymap[XK_Super_R & 0xFF] = SDLK_RSUPER;       /* Right "Windows */
   840     MISC_keymap[XK_Mode_switch & 0xFF] = SDLK_MODE;     /* "Alt Gr" key */
   841     MISC_keymap[XK_Multi_key & 0xFF] = SDLK_COMPOSE;    /* Multi-key compose */
   842 
   843     MISC_keymap[XK_Help & 0xFF] = SDLK_HELP;
   844     MISC_keymap[XK_Print & 0xFF] = SDLK_PRINT;
   845     MISC_keymap[XK_Sys_Req & 0xFF] = SDLK_SYSREQ;
   846     MISC_keymap[XK_Break & 0xFF] = SDLK_BREAK;
   847     MISC_keymap[XK_Menu & 0xFF] = SDLK_MENU;
   848     MISC_keymap[XK_Hyper_R & 0xFF] = SDLK_MENU; /* Windows "Menu" key */
   849 }
   850 
   851 /* Get the translated SDL virtual keysym */
   852 SDLKey
   853 X11_TranslateKeycode(Display * display, KeyCode kc)
   854 {
   855     KeySym xsym;
   856     SDLKey key;
   857 
   858     xsym = XKeycodeToKeysym(display, kc, 0);
   859 #ifdef DEBUG_KEYS
   860     fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
   861 #endif
   862     key = SDLK_UNKNOWN;
   863     if (xsym) {
   864         switch (xsym >> 8) {
   865         case 0x1005FF:
   866 #ifdef SunXK_F36
   867             if (xsym == SunXK_F36)
   868                 key = SDLK_F11;
   869 #endif
   870 #ifdef SunXK_F37
   871             if (xsym == SunXK_F37)
   872                 key = SDLK_F12;
   873 #endif
   874             break;
   875         case 0x00:             /* Latin 1 */
   876             key = (SDLKey) (xsym & 0xFF);
   877             break;
   878         case 0x01:             /* Latin 2 */
   879         case 0x02:             /* Latin 3 */
   880         case 0x03:             /* Latin 4 */
   881         case 0x04:             /* Katakana */
   882         case 0x05:             /* Arabic */
   883         case 0x06:             /* Cyrillic */
   884         case 0x07:             /* Greek */
   885         case 0x08:             /* Technical */
   886         case 0x0A:             /* Publishing */
   887         case 0x0C:             /* Hebrew */
   888         case 0x0D:             /* Thai */
   889             /* These are wrong, but it's better than nothing */
   890             key = (SDLKey) (xsym & 0xFF);
   891             break;
   892         case 0xFE:
   893             key = ODD_keymap[xsym & 0xFF];
   894             break;
   895         case 0xFF:
   896             key = MISC_keymap[xsym & 0xFF];
   897             break;
   898         default:
   899             /*
   900                fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
   901                (unsigned int)xsym);
   902              */
   903             break;
   904         }
   905     } else {
   906         /* X11 doesn't know how to translate the key! */
   907         switch (kc) {
   908             /* Caution:
   909                These keycodes are from the Microsoft Keyboard
   910              */
   911         case 115:
   912             key = SDLK_LSUPER;
   913             break;
   914         case 116:
   915             key = SDLK_RSUPER;
   916             break;
   917         case 117:
   918             key = SDLK_MENU;
   919             break;
   920         default:
   921             /*
   922              * no point in an error message; happens for
   923              * several keys when we get a keymap notify
   924              */
   925             break;
   926         }
   927     }
   928     return key;
   929 }
   930 
   931 /* X11 modifier masks for various keys */
   932 static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
   933 static unsigned num_mask, mode_switch_mask;
   934 
   935 static void
   936 get_modifier_masks(Display * display)
   937 {
   938     static unsigned got_masks;
   939     int i, j;
   940     XModifierKeymap *xmods;
   941     unsigned n;
   942 
   943     if (got_masks)
   944         return;
   945 
   946     xmods = XGetModifierMapping(display);
   947     n = xmods->max_keypermod;
   948     for (i = 3; i < 8; i++) {
   949         for (j = 0; j < n; j++) {
   950             KeyCode kc = xmods->modifiermap[i * n + j];
   951             KeySym ks = XKeycodeToKeysym(display, kc, 0);
   952             unsigned mask = 1 << i;
   953             switch (ks) {
   954             case XK_Num_Lock:
   955                 num_mask = mask;
   956                 break;
   957             case XK_Alt_L:
   958                 alt_l_mask = mask;
   959                 break;
   960             case XK_Alt_R:
   961                 alt_r_mask = mask;
   962                 break;
   963             case XK_Meta_L:
   964                 meta_l_mask = mask;
   965                 break;
   966             case XK_Meta_R:
   967                 meta_r_mask = mask;
   968                 break;
   969             case XK_Mode_switch:
   970                 mode_switch_mask = mask;
   971                 break;
   972             }
   973         }
   974     }
   975     XFreeModifiermap(xmods);
   976     got_masks = 1;
   977 }
   978 
   979 
   980 /*
   981  * This function is semi-official; it is not officially exported and should
   982  * not be considered part of the SDL API, but may be used by client code
   983  * that *really* needs it (including legacy code).
   984  * It is slow, though, and should be avoided if possible.
   985  *
   986  * Note that it isn't completely accurate either; in particular, multi-key
   987  * sequences (dead accents, compose key sequences) will not work since the
   988  * state has been irrevocably lost.
   989  */
   990 Uint16
   991 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers)
   992 {
   993     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   994     char keybuf[32];
   995     int i;
   996     KeySym xsym = 0;
   997     XKeyEvent xkey;
   998     Uint16 unicode;
   999 
  1000     if (!_this || !SDL_Display) {
  1001         return 0;
  1002     }
  1003 
  1004     SDL_memset(&xkey, 0, sizeof(xkey));
  1005     xkey.display = SDL_Display;
  1006 
  1007     xsym = keysym;              /* last resort if not found */
  1008     for (i = 0; i < 256; ++i) {
  1009         if (MISC_keymap[i] == keysym) {
  1010             xsym = 0xFF00 | i;
  1011             break;
  1012         } else if (ODD_keymap[i] == keysym) {
  1013             xsym = 0xFE00 | i;
  1014             break;
  1015         }
  1016     }
  1017 
  1018     xkey.keycode = XKeysymToKeycode(xkey.display, xsym);
  1019 
  1020     get_modifier_masks(SDL_Display);
  1021     if (modifiers & KMOD_SHIFT)
  1022         xkey.state |= ShiftMask;
  1023     if (modifiers & KMOD_CAPS)
  1024         xkey.state |= LockMask;
  1025     if (modifiers & KMOD_CTRL)
  1026         xkey.state |= ControlMask;
  1027     if (modifiers & KMOD_MODE)
  1028         xkey.state |= mode_switch_mask;
  1029     if (modifiers & KMOD_LALT)
  1030         xkey.state |= alt_l_mask;
  1031     if (modifiers & KMOD_RALT)
  1032         xkey.state |= alt_r_mask;
  1033     if (modifiers & KMOD_LMETA)
  1034         xkey.state |= meta_l_mask;
  1035     if (modifiers & KMOD_RMETA)
  1036         xkey.state |= meta_r_mask;
  1037     if (modifiers & KMOD_NUM)
  1038         xkey.state |= num_mask;
  1039 
  1040     unicode = 0;
  1041     if (XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL))
  1042         unicode = (unsigned char) keybuf[0];
  1043     return (unicode);
  1044 }
  1045 
  1046 
  1047 /*
  1048  * Called when focus is regained, to read the keyboard state and generate
  1049  * synthetic keypress/release events.
  1050  * key_vec is a bit vector of keycodes (256 bits)
  1051  */
  1052 void
  1053 X11_SetKeyboardState(Display * display, const char *key_vec)
  1054 {
  1055     char keys_return[32];
  1056     int i;
  1057     Uint8 *kstate = SDL_GetKeyState(NULL);
  1058     SDLMod modstate;
  1059     Window junk_window;
  1060     int x, y;
  1061     unsigned int mask;
  1062 
  1063     /* The first time the window is mapped, we initialize key state */
  1064     if (!key_vec) {
  1065         XQueryKeymap(display, keys_return);
  1066         key_vec = keys_return;
  1067     }
  1068 
  1069     /* Get the keyboard modifier state */
  1070     modstate = 0;
  1071     get_modifier_masks(display);
  1072     if (XQueryPointer(display, DefaultRootWindow(display),
  1073                       &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
  1074         if (mask & LockMask) {
  1075             modstate |= KMOD_CAPS;
  1076         }
  1077         if (mask & mode_switch_mask) {
  1078             modstate |= KMOD_MODE;
  1079         }
  1080         if (mask & num_mask) {
  1081             modstate |= KMOD_NUM;
  1082         }
  1083     }
  1084 
  1085     /* Zero the new keyboard state and generate it */
  1086     SDL_memset(kstate, 0, SDLK_LAST);
  1087     /*
  1088      * An obvious optimisation is to check entire longwords at a time in
  1089      * both loops, but we can't be sure the arrays are aligned so it's not
  1090      * worth the extra complexity
  1091      */
  1092     for (i = 0; i < 32; i++) {
  1093         int j;
  1094         if (!key_vec[i])
  1095             continue;
  1096         for (j = 0; j < 8; j++) {
  1097             if (key_vec[i] & (1 << j)) {
  1098                 SDLKey key;
  1099                 KeyCode kc = (i << 3 | j);
  1100                 key = X11_TranslateKeycode(display, kc);
  1101                 if (key == SDLK_UNKNOWN) {
  1102                     continue;
  1103                 }
  1104                 kstate[key] = SDL_PRESSED;
  1105                 switch (key) {
  1106                 case SDLK_LSHIFT:
  1107                     modstate |= KMOD_LSHIFT;
  1108                     break;
  1109                 case SDLK_RSHIFT:
  1110                     modstate |= KMOD_RSHIFT;
  1111                     break;
  1112                 case SDLK_LCTRL:
  1113                     modstate |= KMOD_LCTRL;
  1114                     break;
  1115                 case SDLK_RCTRL:
  1116                     modstate |= KMOD_RCTRL;
  1117                     break;
  1118                 case SDLK_LALT:
  1119                     modstate |= KMOD_LALT;
  1120                     break;
  1121                 case SDLK_RALT:
  1122                     modstate |= KMOD_RALT;
  1123                     break;
  1124                 case SDLK_LMETA:
  1125                     modstate |= KMOD_LMETA;
  1126                     break;
  1127                 case SDLK_RMETA:
  1128                     modstate |= KMOD_RMETA;
  1129                     break;
  1130                 default:
  1131                     break;
  1132                 }
  1133             }
  1134         }
  1135     }
  1136 
  1137     /* Hack - set toggle key state */
  1138     if (modstate & KMOD_CAPS) {
  1139         kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
  1140     } else {
  1141         kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
  1142     }
  1143     if (modstate & KMOD_NUM) {
  1144         kstate[SDLK_NUMLOCK] = SDL_PRESSED;
  1145     } else {
  1146         kstate[SDLK_NUMLOCK] = SDL_RELEASED;
  1147     }
  1148 
  1149     /* Set the final modifier state */
  1150     SDL_SetModState(modstate);
  1151 }
  1152 
  1153 void
  1154 X11_InitOSKeymap(_THIS)
  1155 {
  1156     X11_InitKeymap();
  1157 }
  1158 
  1159 void
  1160 X11_SaveScreenSaver(Display * display, int *saved_timeout, BOOL * dpms)
  1161 {
  1162     int timeout, interval, prefer_blank, allow_exp;
  1163     XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
  1164     *saved_timeout = timeout;
  1165 
  1166 #if SDL_VIDEO_DRIVER_X11_DPMS
  1167     if (SDL_X11_HAVE_DPMS) {
  1168         int dummy;
  1169         if (DPMSQueryExtension(display, &dummy, &dummy)) {
  1170             CARD16 state;
  1171             DPMSInfo(display, &state, dpms);
  1172         }
  1173     }
  1174 #else
  1175     *dpms = 0;
  1176 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
  1177 }
  1178 
  1179 void
  1180 X11_DisableScreenSaver(Display * display)
  1181 {
  1182     int timeout, interval, prefer_blank, allow_exp;
  1183     XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
  1184     timeout = 0;
  1185     XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
  1186 
  1187 #if SDL_VIDEO_DRIVER_X11_DPMS
  1188     if (SDL_X11_HAVE_DPMS) {
  1189         int dummy;
  1190         if (DPMSQueryExtension(display, &dummy, &dummy)) {
  1191             DPMSDisable(display);
  1192         }
  1193     }
  1194 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
  1195 }
  1196 
  1197 void
  1198 X11_RestoreScreenSaver(Display * display, int saved_timeout, BOOL dpms)
  1199 {
  1200     int timeout, interval, prefer_blank, allow_exp;
  1201     XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
  1202     timeout = saved_timeout;
  1203     XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
  1204 
  1205 #if SDL_VIDEO_DRIVER_X11_DPMS
  1206     if (SDL_X11_HAVE_DPMS) {
  1207         int dummy;
  1208         if (DPMSQueryExtension(display, &dummy, &dummy)) {
  1209             if (dpms) {
  1210                 DPMSEnable(display);
  1211             }
  1212         }
  1213     }
  1214 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
  1215 }
  1216 
  1217 /* vi: set ts=4 sw=4 expandtab: */