src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 27 Sep 2009 23:22:57 +0000
branchSDL-1.2
changeset 4255 5a203e2b0162
parent 4159 a1b03ba2fcd0
child 4264 d6f4cc9a5bf6
permissions -rw-r--r--
Fixed bug #716

Armin Burgmeier 2009-03-15 04:35:45 PDT

When I hold a mouse button down on another (non-SDL) window, then move the
mouse over an SDL window and releasing the mouse button there, then the
application does not receive an SDL_ACTIVEEVENT with state SDL_APPMOUSEFOCUS
and gain 1.

Furthermore, SDL_GetAppState() reports the application not having mouse focus
until moving the mouse out of the window and back in again.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 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 Utf8ToUcs4(const Uint8 *utf8)
    63 {
    64 	Uint32 c;
    65 	int i = 1;
    66 	int noOctets = 0;
    67 	int firstOctetMask = 0;
    68 	unsigned char firstOctet = utf8[0];
    69 	if (firstOctet < 0x80) {
    70 		/*
    71 		  Characters in the range:
    72 		    00000000 to 01111111 (ASCII Range)
    73 		  are stored in one octet:
    74 		    0xxxxxxx (The same as its ASCII representation)
    75 		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
    76 		  of the UCS4 representation.
    77 		*/
    78 		noOctets = 1;
    79 		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
    80 	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
    81 	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
    82 		/*
    83 		  Characters in the range:
    84 		    00000000 10000000 to 00000111 11111111
    85 		  are stored in two octets:
    86 		    110xxxxx 10xxxxxx
    87 		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
    88 		  of the UCS4 representation.
    89 		*/
    90 		noOctets = 2;
    91 		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
    92 	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
    93 	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
    94 		/*
    95 		  Characters in the range:
    96 		    00001000 00000000 to 11111111 11111111
    97 		  are stored in three octets:
    98 		    1110xxxx 10xxxxxx 10xxxxxx
    99 		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
   100 		  of the UCS4 representation.
   101 		*/
   102 		noOctets = 3;
   103 		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
   104 	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
   105 	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
   106 		/*
   107 		  Characters in the range:
   108 		    00000001 00000000 00000000 to 00011111 11111111 11111111
   109 		  are stored in four octets:
   110 		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   111 		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
   112 		  of the UCS4 representation.
   113 		*/
   114 		noOctets = 4;
   115 		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
   116 	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
   117 	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
   118 		/*
   119 		  Characters in the range:
   120 		    00000000 00100000 00000000 00000000 to
   121 		    00000011 11111111 11111111 11111111
   122 		  are stored in five octets:
   123 		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   124 		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
   125 		  of the UCS4 representation.
   126 		*/
   127 		noOctets = 5;
   128 		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
   129 	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
   130 	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
   131 		/*
   132 		  Characters in the range:
   133 		    00000100 00000000 00000000 00000000 to
   134 		    01111111 11111111 11111111 11111111
   135 		  are stored in six octets:
   136 		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   137 		  The least significant bit of the first octet is the most significant nonzero bit
   138 		  of the UCS4 representation.
   139 		*/
   140 		noOctets = 6;
   141 		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
   142 	} else
   143 		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
   144 	
   145 	/*
   146 	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
   147 	  of the UCS4 representation.
   148 	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   149 	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   150 	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   151 	  number of continuing octets (if any) and leave only the free bits (the x's)
   152 	  Sample:
   153 	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   154 	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
   155 	*/
   156 	c = firstOctet & firstOctetMask;
   157 	
   158 	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   159 	for (i = 1; i < noOctets; i++) {
   160 		/* A valid continuing octet is of the form 10xxxxxx */
   161 		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
   162 		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   163 			/*The given chunk is a partial sequence at the end of a string that could
   164 			   begin a valid character */
   165 			return 0;
   166 		
   167 		/* Make room for the next 6-bits */
   168 		c <<= 6;
   169 		
   170 		/*
   171 		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   172 		  of c.ucs4 with them.
   173 		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   174 		*/
   175 		c |= utf8[i] & 0x3F;
   176 	}
   177 	return c;
   178 }
   179 
   180 /* Given a UTF-8 encoded string pointed to by utf8 of length length in
   181    bytes, returns the corresponding UTF-16 encoded string in the
   182    buffer pointed to by utf16.  The maximum number of UTF-16 encoding
   183    units (i.e., Unit16s) allowed in the buffer is specified in
   184    utf16_max_length.  The return value is the number of UTF-16
   185    encoding units placed in the output buffer pointed to by utf16.
   186 
   187    In case of an error, -1 is returned, leaving some unusable partial
   188    results in the output buffer.
   189 
   190    The caller must estimate the size of utf16 buffer by itself before
   191    calling this function.  Insufficient output buffer is considered as
   192    an error, and once an error occured, this function doesn't give any
   193    clue how large the result will be.
   194 
   195    The error cases include following:
   196 
   197    - Invalid byte sequences were in the input UTF-8 bytes.  The caller
   198      has no way to know what point in the input buffer was the
   199      errornous byte.
   200 
   201    - The input contained a character (a valid UTF-8 byte sequence)
   202      whose scalar value exceeded the range that UTF-16 can represent
   203      (i.e., characters whose Unicode scalar value above 0x110000).
   204 
   205    - The output buffer has no enough space to hold entire utf16 data.
   206 
   207    Please note:
   208 
   209    - '\0'-termination is not assumed both on the input UTF-8 string
   210      and on the output UTF-16 string; any legal zero byte in the input
   211      UTF-8 string will be converted to a 16-bit zero in output.  As a
   212      side effect, the last UTF-16 encoding unit stored in the output
   213      buffer will have a non-zero value if the input UTF-8 was not
   214      '\0'-terminated.
   215 
   216    - UTF-8 aliases are *not* considered as an error.  They are
   217      converted to UTF-16.  For example, 0xC0 0xA0, 0xE0 0x80 0xA0, 
   218      and 0xF0 0x80 0x80 0xA0 are all mapped to a single UTF-16
   219      encoding unit 0x0020.
   220 
   221    - Three byte UTF-8 sequences whose value corresponds to a surrogate
   222      code or other reserved scalar value are not considered as an
   223      error either.  They may cause an invalid UTF-16 data (e.g., those
   224      containing unpaired surrogates).
   225 
   226 */
   227 
   228 static int Utf8ToUtf16(const Uint8 *utf8, const int utf8_length, Uint16 *utf16, const int utf16_max_length) {
   229 
   230     /* p moves over the output buffer.  max_ptr points to the next to the last slot of the buffer.  */
   231     Uint16 *p = utf16;
   232     Uint16 const *const max_ptr = utf16 + utf16_max_length;
   233 
   234     /* end_of_input points to the last byte of input as opposed to the next to the last byte.  */
   235     Uint8 const *const end_of_input = utf8 + utf8_length - 1;
   236 
   237     while (utf8 <= end_of_input) {
   238 	Uint8 const c = *utf8;
   239 	if (p >= max_ptr) {
   240 	    /* No more output space.  */
   241 	    return -1;
   242 	}
   243 	if (c < 0x80) {
   244 	    /* One byte ASCII.  */
   245 	    *p++ = c;
   246 	    utf8 += 1;
   247 	} else if (c < 0xC0) {
   248 	    /* Follower byte without preceeding leader bytes.  */
   249 	    return -1;
   250 	} else if (c < 0xE0) {
   251 	    /* Two byte sequence.  We need one follower byte.  */
   252 	    if (end_of_input - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) {
   253 		return -1;
   254 	    }
   255 	    *p++ = (Uint16)(0xCF80 + (c << 6) + utf8[1]);
   256 	    utf8 += 2;
   257 	} else if (c < 0xF0) {
   258 	    /* Three byte sequence.  We need two follower byte.  */
   259 	    if (end_of_input - utf8 < 2 || (((utf8[1] ^ 0x80) | (utf8[2] ^ 0x80)) & 0xC0)) {
   260 		return -1;
   261 	    }
   262 	    *p++ = (Uint16)(0xDF80 + (c << 12) + (utf8[1] << 6) + utf8[2]);
   263 	    utf8 += 3;
   264 	} else if (c < 0xF8) {
   265 	    int plane;
   266 	    /* Four byte sequence.  We need three follower bytes.  */
   267 	    if (end_of_input - utf8 < 3 || (((utf8[1] ^ 0x80) | (utf8[2] ^0x80) | (utf8[3] ^ 0x80)) & 0xC0)) {
   268 		return -1;
   269 	    }
   270 	    plane = (-0xC8 + (c << 2) + (utf8[1] >> 4));
   271 	    if (plane == 0) {
   272 		/* This four byte sequence is an alias that
   273                    corresponds to a Unicode scalar value in BMP.
   274 		   It fits in an UTF-16 encoding unit.  */
   275 		*p++ = (Uint16)(0xDF80 + (utf8[1] << 12) + (utf8[2] << 6) + utf8[3]);
   276 	    } else if (plane <= 16) {
   277 		/* This is a legal four byte sequence that corresponds to a surrogate pair.  */
   278 		if (p + 1 >= max_ptr) {
   279 		    /* No enough space on the output buffer for the pair.  */
   280 		    return -1;
   281 		}
   282 		*p++ = (Uint16)(0xE5B8 + (c << 8) + (utf8[1] << 2) + (utf8[2] >> 4));
   283 		*p++ = (Uint16)(0xDB80 + ((utf8[2] & 0x0F) << 6) + utf8[3]);
   284 	    } else {
   285 		/* This four byte sequence is out of UTF-16 code space.  */
   286 		return -1;
   287 	    }
   288 	    utf8 += 4;
   289 	} else {
   290 	    /* Longer sequence or unused byte.  */
   291 	    return -1;
   292 	}
   293     }
   294     return p - utf16;
   295 }
   296 
   297 #endif
   298 
   299 /* Check to see if this is a repeated key.
   300    (idea shamelessly lifted from GII -- thanks guys! :)
   301  */
   302 static int X11_KeyRepeat(Display *display, XEvent *event)
   303 {
   304 	XEvent peekevent;
   305 	int repeated;
   306 
   307 	repeated = 0;
   308 	if ( XPending(display) ) {
   309 		XPeekEvent(display, &peekevent);
   310 		if ( (peekevent.type == KeyPress) &&
   311 		     (peekevent.xkey.keycode == event->xkey.keycode) &&
   312 		     ((peekevent.xkey.time-event->xkey.time) < 2) ) {
   313 			repeated = 1;
   314 			XNextEvent(display, &peekevent);
   315 		}
   316 	}
   317 	return(repeated);
   318 }
   319 
   320 /* Note:  The X server buffers and accumulates mouse motion events, so
   321    the motion event generated by the warp may not appear exactly as we
   322    expect it to.  We work around this (and improve performance) by only
   323    warping the pointer when it reaches the edge, and then wait for it.
   324 */
   325 #define MOUSE_FUDGE_FACTOR	8
   326 
   327 static __inline__ int X11_WarpedMotion(_THIS, XEvent *xevent)
   328 {
   329 	int w, h, i;
   330 	int deltax, deltay;
   331 	int posted;
   332 
   333 	w = SDL_VideoSurface->w;
   334 	h = SDL_VideoSurface->h;
   335 	deltax = xevent->xmotion.x - mouse_last.x;
   336 	deltay = xevent->xmotion.y - mouse_last.y;
   337 #ifdef DEBUG_MOTION
   338   printf("Warped mouse motion: %d,%d\n", deltax, deltay);
   339 #endif
   340 	mouse_last.x = xevent->xmotion.x;
   341 	mouse_last.y = xevent->xmotion.y;
   342 	posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   343 
   344 	if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
   345 	     (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) ||
   346 	     (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
   347 	     (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) {
   348 		/* Get the events that have accumulated */
   349 		while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) {
   350 			deltax = xevent->xmotion.x - mouse_last.x;
   351 			deltay = xevent->xmotion.y - mouse_last.y;
   352 #ifdef DEBUG_MOTION
   353   printf("Extra mouse motion: %d,%d\n", deltax, deltay);
   354 #endif
   355 			mouse_last.x = xevent->xmotion.x;
   356 			mouse_last.y = xevent->xmotion.y;
   357 			posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   358 		}
   359 		mouse_last.x = w/2;
   360 		mouse_last.y = h/2;
   361 		XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
   362 					mouse_last.x, mouse_last.y);
   363 		for ( i=0; i<10; ++i ) {
   364         		XMaskEvent(SDL_Display, PointerMotionMask, xevent);
   365 			if ( (xevent->xmotion.x >
   366 			          (mouse_last.x-MOUSE_FUDGE_FACTOR)) &&
   367 			     (xevent->xmotion.x <
   368 			          (mouse_last.x+MOUSE_FUDGE_FACTOR)) &&
   369 			     (xevent->xmotion.y >
   370 			          (mouse_last.y-MOUSE_FUDGE_FACTOR)) &&
   371 			     (xevent->xmotion.y <
   372 			          (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) {
   373 				break;
   374 			}
   375 #ifdef DEBUG_XEVENTS
   376   printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y);
   377 #endif
   378 		}
   379 #ifdef DEBUG_XEVENTS
   380 		if ( i == 10 ) {
   381 			printf("Warning: didn't detect mouse warp motion\n");
   382 		}
   383 #endif
   384 	}
   385 	return(posted);
   386 }
   387 
   388 static int X11_DispatchEvent(_THIS)
   389 {
   390 	int posted;
   391 	XEvent xevent;
   392 
   393 	SDL_memset(&xevent, '\0', sizeof (XEvent));  /* valgrind fix. --ryan. */
   394 	XNextEvent(SDL_Display, &xevent);
   395 
   396 	/* Discard KeyRelease and KeyPress events generated by auto-repeat.
   397 	   We need to do it before passing event to XFilterEvent.  Otherwise,
   398 	   KeyRelease aware IMs are confused...  */
   399 	if ( xevent.type == KeyRelease
   400 	     && X11_KeyRepeat(SDL_Display, &xevent) ) {
   401 		return 0;
   402 	}
   403 
   404 #ifdef X_HAVE_UTF8_STRING
   405 	/* If we are translating with IM, we need to pass all events
   406 	   to XFilterEvent, and discard those filtered events immediately.  */
   407 	if ( SDL_TranslateUNICODE
   408 	     && SDL_IM != NULL
   409 	     && XFilterEvent(&xevent, None) ) {
   410 		return 0;
   411 	}
   412 #endif
   413 
   414 	posted = 0;
   415 	switch (xevent.type) {
   416 
   417 	    /* Gaining mouse coverage? */
   418 	    case EnterNotify: {
   419 #ifdef DEBUG_XEVENTS
   420 printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y);
   421 if ( xevent.xcrossing.mode == NotifyGrab )
   422 printf("Mode: NotifyGrab\n");
   423 if ( xevent.xcrossing.mode == NotifyUngrab )
   424 printf("Mode: NotifyUngrab\n");
   425 #endif
   426 		if ( this->input_grab == SDL_GRAB_OFF ) {
   427 			posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   428 		}
   429 		posted = SDL_PrivateMouseMotion(0, 0,
   430 				xevent.xcrossing.x,
   431 				xevent.xcrossing.y);
   432 	    }
   433 	    break;
   434 
   435 	    /* Losing mouse coverage? */
   436 	    case LeaveNotify: {
   437 #ifdef DEBUG_XEVENTS
   438 printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y);
   439 if ( xevent.xcrossing.mode == NotifyGrab )
   440 printf("Mode: NotifyGrab\n");
   441 if ( xevent.xcrossing.mode == NotifyUngrab )
   442 printf("Mode: NotifyUngrab\n");
   443 #endif
   444 		if ( xevent.xcrossing.detail != NotifyInferior ) {
   445 			if ( this->input_grab == SDL_GRAB_OFF ) {
   446 				posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
   447 			} else {
   448 				posted = SDL_PrivateMouseMotion(0, 0,
   449 						xevent.xcrossing.x,
   450 						xevent.xcrossing.y);
   451 			}
   452 		}
   453 	    }
   454 	    break;
   455 
   456 	    /* Gaining input focus? */
   457 	    case FocusIn: {
   458 #ifdef DEBUG_XEVENTS
   459 printf("FocusIn!\n");
   460 #endif
   461 		posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   462 
   463 #ifdef X_HAVE_UTF8_STRING
   464 		if ( SDL_IC != NULL ) {
   465 			XSetICFocus(SDL_IC);
   466 		}
   467 #endif
   468 		/* Queue entry into fullscreen mode */
   469 		switch_waiting = 0x01 | SDL_FULLSCREEN;
   470 		switch_time = SDL_GetTicks() + 1500;
   471 	    }
   472 	    break;
   473 
   474 	    /* Losing input focus? */
   475 	    case FocusOut: {
   476 #ifdef DEBUG_XEVENTS
   477 printf("FocusOut!\n");
   478 #endif
   479 		posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
   480 
   481 #ifdef X_HAVE_UTF8_STRING
   482 		if ( SDL_IC != NULL ) {
   483 			XUnsetICFocus(SDL_IC);
   484 		}
   485 #endif
   486 		/* Queue leaving fullscreen mode */
   487 		switch_waiting = 0x01;
   488 		switch_time = SDL_GetTicks() + 200;
   489 	    }
   490 	    break;
   491 
   492 #ifdef X_HAVE_UTF8_STRING
   493 	    /* Some IM requires MappingNotify to be passed to
   494 	       XRefreshKeyboardMapping by the app.  */
   495 	    case MappingNotify: {
   496 		XRefreshKeyboardMapping(&xevent.xmapping);
   497 	    }
   498 	    break;
   499 #endif /* X_HAVE_UTF8_STRING */
   500 
   501 	    /* Generated upon EnterWindow and FocusIn */
   502 	    case KeymapNotify: {
   503 #ifdef DEBUG_XEVENTS
   504 printf("KeymapNotify!\n");
   505 #endif
   506 		X11_SetKeyboardState(SDL_Display,  xevent.xkeymap.key_vector);
   507 	    }
   508 	    break;
   509 
   510 	    /* Mouse motion? */
   511 	    case MotionNotify: {
   512 		if ( SDL_VideoSurface ) {
   513 			if ( mouse_relative ) {
   514 				if ( using_dga & DGA_MOUSE ) {
   515 #ifdef DEBUG_MOTION
   516   printf("DGA motion: %d,%d\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
   517 #endif
   518 					posted = SDL_PrivateMouseMotion(0, 1,
   519 							xevent.xmotion.x_root,
   520 							xevent.xmotion.y_root);
   521 				} else {
   522 					posted = X11_WarpedMotion(this,&xevent);
   523 				}
   524 			} else {
   525 #ifdef DEBUG_MOTION
   526   printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   527 #endif
   528 				posted = SDL_PrivateMouseMotion(0, 0,
   529 						xevent.xmotion.x,
   530 						xevent.xmotion.y);
   531 			}
   532 		}
   533 	    }
   534 	    break;
   535 
   536 	    /* Mouse button press? */
   537 	    case ButtonPress: {
   538 		posted = SDL_PrivateMouseButton(SDL_PRESSED, 
   539 					xevent.xbutton.button, 0, 0);
   540 	    }
   541 	    break;
   542 
   543 	    /* Mouse button release? */
   544 	    case ButtonRelease: {
   545 		posted = SDL_PrivateMouseButton(SDL_RELEASED, 
   546 					xevent.xbutton.button, 0, 0);
   547 	    }
   548 	    break;
   549 
   550 	    /* Key press? */
   551 	    case KeyPress: {
   552 		SDL_keysym keysym;
   553 		KeyCode keycode = xevent.xkey.keycode;
   554 
   555 #ifdef DEBUG_XEVENTS
   556 printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   557 #endif
   558 		/* If we're not doing translation, we're done! */
   559 		if ( !SDL_TranslateUNICODE ) {
   560 			/* Get the translated SDL virtual keysym and put it on the queue.*/
   561 			keysym.scancode = keycode;
   562 			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   563 			keysym.mod = KMOD_NONE;
   564 			keysym.unicode = 0;
   565 			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   566 			break;
   567 		}
   568 
   569 		/* Look up the translated value for the key event */
   570 #ifdef X_HAVE_UTF8_STRING
   571 		if ( SDL_IC != NULL ) {
   572 			Status status;
   573 			KeySym xkeysym;
   574 			int i;
   575 			/* A UTF-8 character can be at most 6 bytes */
   576 			/* ... It's true, but Xutf8LookupString can
   577 			   return more than one characters.  Moreover,
   578 			   the spec. put no upper bound, so we should
   579 			   be ready for longer strings.  */
   580 			char keybuf[32];
   581 			char *keydata = keybuf;
   582 			int count;
   583 			Uint16 utf16buf[32];
   584 			Uint16 *utf16data = utf16buf;
   585 			int utf16size;
   586 			int utf16length;
   587 
   588 			count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, sizeof(keybuf), &xkeysym, &status);
   589 			if (XBufferOverflow == status) {
   590 			  /* The IM has just generated somewhat long
   591 			     string.  We need a longer buffer in this
   592 			     case.  */
   593 			  keydata = SDL_malloc(count);
   594 			  if ( keydata == NULL ) {
   595 			    SDL_OutOfMemory();
   596 			    break;
   597 			  }
   598 			  count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, count, &xkeysym, &status);
   599 			}
   600 
   601 			switch (status) {
   602 
   603 			case XBufferOverflow: {
   604 			  /* Oops!  We have allocated the bytes as
   605 			     requested by Xutf8LookupString, so the
   606 			     length of the buffer must be
   607 			     sufficient.  This case should never
   608 			     happen! */
   609 			  SDL_SetError("Xutf8LookupString indicated a double buffer overflow!");
   610 			  break;
   611 			}
   612 
   613 			case XLookupChars:
   614 			case XLookupBoth: {
   615 			  if (0 == count) {
   616 			    break;
   617 			  }
   618 
   619 			  /* We got a converted string from IM.  Make
   620 			     sure to deliver all characters to the
   621 			     application as SDL events.  Note that
   622 			     an SDL event can only carry one UTF-16
   623 			     encoding unit, and a surrogate pair is
   624 			     delivered as two SDL events.  I guess
   625 			     this behaviour is probably _imported_
   626 			     from Windows or MacOS.  To do so, we need
   627 			     to convert the UTF-8 data into UTF-16
   628 			     data (not UCS4/UTF-32!).  We need an
   629 			     estimate of the number of UTF-16 encoding
   630 			     units here.  The worst case is pure ASCII
   631 			     string.  Assume so. */
   632 			  /* In 1.3 SDL may have a text event instead, that
   633 			     carries the whole UTF-8 string with it. */
   634 			  utf16size = count * sizeof(Uint16);
   635 			  if (utf16size > sizeof(utf16buf)) {
   636 			    utf16data = (Uint16 *) SDL_malloc(utf16size);
   637 			    if (utf16data == NULL) {
   638 			      SDL_OutOfMemory();
   639 			      break;
   640 			    }
   641 			  }
   642 			  utf16length = Utf8ToUtf16((Uint8 *)keydata, count, utf16data, utf16size);
   643 			  if (utf16length < 0) {
   644 			    /* The keydata contained an invalid byte
   645 			       sequence.  It should be a bug of the IM
   646 			       or Xlib... */
   647 			    SDL_SetError("Oops! Xutf8LookupString returned an invalid UTF-8 sequence!");
   648 			    break;
   649 			  }
   650 
   651 			  /* Deliver all UTF-16 encoding units.  At
   652 			     this moment, SDL event queue has a
   653 			     fixed size (128 events), and an SDL
   654 			     event can hold just one UTF-16 encoding
   655 			     unit.  So, if we receive more than 128
   656 			     UTF-16 encoding units from a commit,
   657 			     exceeded characters will be lost.  */
   658 			  for (i = 0; i < utf16length - 1; i++) {
   659 			    keysym.scancode = 0;
   660 			    keysym.sym = SDLK_UNKNOWN;
   661 			    keysym.mod = KMOD_NONE;
   662 			    keysym.unicode = utf16data[i];
   663 			    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   664 			  }
   665 			  /* The keysym for the last character carries the
   666 			     scancode and symbol that corresponds to the X11
   667 			     keycode.  */
   668 			  if (utf16length > 0) {			       
   669 			    keysym.scancode = keycode;
   670 			    keysym.sym = (keycode ? X11_TranslateKeycode(SDL_Display, keycode) : 0);
   671 			    keysym.mod = KMOD_NONE;
   672 			    keysym.unicode = utf16data[utf16length - 1];
   673 			    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   674 			  }
   675 			  break;
   676 			}
   677 
   678 			case XLookupKeySym: {
   679 			  /* I'm not sure whether it is possible that
   680 			     a zero keycode makes XLookupKeySym
   681 			     status.  What I'm sure is that a
   682 			     combination of a zero scan code and a non
   683 			     zero sym makes SDL_PrivateKeyboard
   684 			     strange state...  So, just discard it.
   685 			     If this doesn't work, I'm receiving bug
   686 			     reports, and I can know under what
   687 			     condition this case happens.  */
   688 			  if (keycode) {
   689 			    keysym.scancode = keycode;
   690 			    keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   691 			    keysym.mod = KMOD_NONE;
   692 			    keysym.unicode = 0;
   693 			    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   694 			  }
   695 			  break;
   696 			}
   697 
   698 			case XLookupNone: {
   699 			  /* IM has eaten the event.  */
   700 			  break;
   701 			}
   702 
   703 			default:
   704 			  /* An unknown status from Xutf8LookupString.  */
   705 			  SDL_SetError("Oops! Xutf8LookupStringreturned an unknown status");
   706 			}
   707 
   708 			/* Release dynamic buffers if allocated.  */
   709 			if (keydata != NULL && keybuf != keydata) {
   710 			  SDL_free(keydata);
   711 			}
   712 			if (utf16data != NULL && utf16buf != utf16data) {
   713 			  SDL_free(utf16data);
   714 			}
   715 		}
   716 		else
   717 #endif
   718 		{
   719 			static XComposeStatus state;
   720 			char keybuf[32];
   721 
   722 			keysym.scancode = keycode;
   723 			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   724 			keysym.mod = KMOD_NONE;
   725 			keysym.unicode = 0;
   726 			if ( XLookupString(&xevent.xkey,
   727 			                    keybuf, sizeof(keybuf),
   728 			                    NULL, &state) ) {
   729 				/*
   730 				* FIXME: XLookupString() may yield more than one
   731 				* character, so we need a mechanism to allow for
   732 				* this (perhaps null keypress events with a
   733 				* unicode value)
   734 				*/
   735 				keysym.unicode = (Uint8)keybuf[0];
   736 			}
   737 
   738 			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   739 		}
   740 	    }
   741 	    break;
   742 
   743 	    /* Key release? */
   744 	    case KeyRelease: {
   745 		SDL_keysym keysym;
   746 		KeyCode keycode = xevent.xkey.keycode;
   747 
   748 		if (keycode == 0) {
   749 		  /* There should be no KeyRelease for keycode == 0,
   750 		     since it is a notification from IM but a real
   751 		     keystroke.  */
   752 		  /* We need to emit some diagnostic message here.  */
   753 		  break;
   754 		}
   755 
   756 #ifdef DEBUG_XEVENTS
   757 printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   758 #endif
   759 
   760 		/* Get the translated SDL virtual keysym */
   761 		keysym.scancode = keycode;
   762 		keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   763 		keysym.mod = KMOD_NONE;
   764 		keysym.unicode = 0;
   765 
   766 		posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
   767 	    }
   768 	    break;
   769 
   770 	    /* Have we been iconified? */
   771 	    case UnmapNotify: {
   772 #ifdef DEBUG_XEVENTS
   773 printf("UnmapNotify!\n");
   774 #endif
   775 		/* If we're active, make ourselves inactive */
   776 		if ( SDL_GetAppState() & SDL_APPACTIVE ) {
   777 			/* Swap out the gamma before we go inactive */
   778 			X11_SwapVidModeGamma(this);
   779 
   780 			/* Send an internal deactivate event */
   781 			posted = SDL_PrivateAppActive(0,
   782 					SDL_APPACTIVE|SDL_APPINPUTFOCUS);
   783 		}
   784 	    }
   785 	    break;
   786 
   787 	    /* Have we been restored? */
   788 	    case MapNotify: {
   789 #ifdef DEBUG_XEVENTS
   790 printf("MapNotify!\n");
   791 #endif
   792 		/* If we're not active, make ourselves active */
   793 		if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) {
   794 			/* Send an internal activate event */
   795 			posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
   796 
   797 			/* Now that we're active, swap the gamma back */
   798 			X11_SwapVidModeGamma(this);
   799 		}
   800 
   801 		if ( SDL_VideoSurface &&
   802 		     (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
   803 			X11_EnterFullScreen(this);
   804 		} else {
   805 			X11_GrabInputNoLock(this, this->input_grab);
   806 		}
   807 		X11_CheckMouseModeNoLock(this);
   808 
   809 		if ( SDL_VideoSurface ) {
   810 			X11_RefreshDisplay(this);
   811 		}
   812 	    }
   813 	    break;
   814 
   815 	    /* Have we been resized or moved? */
   816 	    case ConfigureNotify: {
   817 #ifdef DEBUG_XEVENTS
   818 printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height);
   819 #endif
   820 		if ( SDL_VideoSurface ) {
   821 		    if ((xevent.xconfigure.width != SDL_VideoSurface->w) ||
   822 		        (xevent.xconfigure.height != SDL_VideoSurface->h)) {
   823 			/* FIXME: Find a better fix for the bug with KDE 1.2 */
   824 			if ( ! ((xevent.xconfigure.width == 32) &&
   825 			        (xevent.xconfigure.height == 32)) ) {
   826 				SDL_PrivateResize(xevent.xconfigure.width,
   827 				                  xevent.xconfigure.height);
   828 			}
   829 		    } else {
   830 			/* OpenGL windows need to know about the change */
   831 			if ( SDL_VideoSurface->flags & SDL_OPENGL ) {
   832 				SDL_PrivateExpose();
   833 			}
   834 		    }
   835 		}
   836 	    }
   837 	    break;
   838 
   839 	    /* Have we been requested to quit (or another client message?) */
   840 	    case ClientMessage: {
   841 		if ( (xevent.xclient.format == 32) &&
   842 		     (xevent.xclient.data.l[0] == WM_DELETE_WINDOW) )
   843 		{
   844 			posted = SDL_PrivateQuit();
   845 		} else
   846 		if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
   847 			SDL_SysWMmsg wmmsg;
   848 
   849 			SDL_VERSION(&wmmsg.version);
   850 			wmmsg.subsystem = SDL_SYSWM_X11;
   851 			wmmsg.event.xevent = xevent;
   852 			posted = SDL_PrivateSysWMEvent(&wmmsg);
   853 		}
   854 	    }
   855 	    break;
   856 
   857 	    /* Do we need to refresh ourselves? */
   858 	    case Expose: {
   859 #ifdef DEBUG_XEVENTS
   860 printf("Expose (count = %d)\n", xevent.xexpose.count);
   861 #endif
   862 		if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) {
   863 			X11_RefreshDisplay(this);
   864 		}
   865 	    }
   866 	    break;
   867 
   868 	    default: {
   869 #ifdef DEBUG_XEVENTS
   870 printf("Unhandled event %d\n", xevent.type);
   871 #endif
   872 		/* Only post the event if we're watching for it */
   873 		if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
   874 			SDL_SysWMmsg wmmsg;
   875 
   876 			SDL_VERSION(&wmmsg.version);
   877 			wmmsg.subsystem = SDL_SYSWM_X11;
   878 			wmmsg.event.xevent = xevent;
   879 			posted = SDL_PrivateSysWMEvent(&wmmsg);
   880 		}
   881 	    }
   882 	    break;
   883 	}
   884 	return(posted);
   885 }
   886 
   887 /* Ack!  XPending() actually performs a blocking read if no events available */
   888 int X11_Pending(Display *display)
   889 {
   890 	/* Flush the display connection and look to see if events are queued */
   891 	XFlush(display);
   892 	if ( XEventsQueued(display, QueuedAlready) ) {
   893 		return(1);
   894 	}
   895 
   896 	/* More drastic measures are required -- see if X is ready to talk */
   897 	{
   898 		static struct timeval zero_time;	/* static == 0 */
   899 		int x11_fd;
   900 		fd_set fdset;
   901 
   902 		x11_fd = ConnectionNumber(display);
   903 		FD_ZERO(&fdset);
   904 		FD_SET(x11_fd, &fdset);
   905 		if ( select(x11_fd+1, &fdset, NULL, NULL, &zero_time) == 1 ) {
   906 			return(XPending(display));
   907 		}
   908 	}
   909 
   910 	/* Oh well, nothing is ready .. */
   911 	return(0);
   912 }
   913 
   914 void X11_PumpEvents(_THIS)
   915 {
   916 	int pending;
   917 
   918 	/* Update activity every five seconds to prevent screensaver. --ryan. */
   919 	if (!allow_screensaver) {
   920 		static Uint32 screensaverTicks;
   921 		Uint32 nowTicks = SDL_GetTicks();
   922 		if ((nowTicks - screensaverTicks) > 5000) {
   923 			XResetScreenSaver(SDL_Display);
   924 			screensaverTicks = nowTicks;
   925 		}
   926 	}
   927 
   928 	/* Keep processing pending events */
   929 	pending = 0;
   930 	while ( X11_Pending(SDL_Display) ) {
   931 		X11_DispatchEvent(this);
   932 		++pending;
   933 	}
   934 	if ( switch_waiting ) {
   935 		Uint32 now;
   936 
   937 		now  = SDL_GetTicks();
   938 		if ( pending || !SDL_VideoSurface ) {
   939 			/* Try again later... */
   940 			if ( switch_waiting & SDL_FULLSCREEN ) {
   941 				switch_time = now + 1500;
   942 			} else {
   943 				switch_time = now + 200;
   944 			}
   945 		} else if ( (int)(switch_time-now) <= 0 ) {
   946 			Uint32 go_fullscreen;
   947 
   948 			go_fullscreen = switch_waiting & SDL_FULLSCREEN;
   949 			switch_waiting = 0;
   950 			if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
   951 				if ( go_fullscreen ) {
   952 					X11_EnterFullScreen(this);
   953 				} else {
   954 					X11_LeaveFullScreen(this);
   955 				}
   956 			}
   957 			/* Handle focus in/out when grabbed */
   958 			if ( go_fullscreen ) {
   959 				X11_GrabInputNoLock(this, this->input_grab);
   960 			} else {
   961 				X11_GrabInputNoLock(this, SDL_GRAB_OFF);
   962 			}
   963 			X11_CheckMouseModeNoLock(this);
   964 		}
   965 	}
   966 }
   967 
   968 void X11_InitKeymap(void)
   969 {
   970 	int i;
   971 
   972 	/* Odd keys used in international keyboards */
   973 	for ( i=0; i<SDL_arraysize(ODD_keymap); ++i )
   974 		ODD_keymap[i] = SDLK_UNKNOWN;
   975 
   976  	/* Some of these might be mappable to an existing SDLK_ code */
   977  	ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
   978  	ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE;
   979  	ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE;
   980  	ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE;
   981  	ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE;
   982  	ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE;
   983  	ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE;
   984  	ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE;
   985  	ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE;
   986  	ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE;
   987  	ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE;
   988  	ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE;
   989  	ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE;
   990  	ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE;
   991  	ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE;
   992  	ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE;
   993 #ifdef XK_dead_hook
   994  	ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE;
   995 #endif
   996 #ifdef XK_dead_horn
   997  	ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE;
   998 #endif
   999 
  1000 #ifdef XK_dead_circumflex
  1001 	/* These X keysyms have 0xFE as the high byte */
  1002 	ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
  1003 #endif
  1004 #ifdef XK_ISO_Level3_Shift
  1005 	ODD_keymap[XK_ISO_Level3_Shift&0xFF] = SDLK_MODE; /* "Alt Gr" key */
  1006 #endif
  1007 
  1008 	/* Map the miscellaneous keys */
  1009 	for ( i=0; i<SDL_arraysize(MISC_keymap); ++i )
  1010 		MISC_keymap[i] = SDLK_UNKNOWN;
  1011 
  1012 	/* These X keysyms have 0xFF as the high byte */
  1013 	MISC_keymap[XK_BackSpace&0xFF] = SDLK_BACKSPACE;
  1014 	MISC_keymap[XK_Tab&0xFF] = SDLK_TAB;
  1015 	MISC_keymap[XK_Clear&0xFF] = SDLK_CLEAR;
  1016 	MISC_keymap[XK_Return&0xFF] = SDLK_RETURN;
  1017 	MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE;
  1018 	MISC_keymap[XK_Escape&0xFF] = SDLK_ESCAPE;
  1019 	MISC_keymap[XK_Delete&0xFF] = SDLK_DELETE;
  1020 
  1021 	MISC_keymap[XK_KP_0&0xFF] = SDLK_KP0;		/* Keypad 0-9 */
  1022 	MISC_keymap[XK_KP_1&0xFF] = SDLK_KP1;
  1023 	MISC_keymap[XK_KP_2&0xFF] = SDLK_KP2;
  1024 	MISC_keymap[XK_KP_3&0xFF] = SDLK_KP3;
  1025 	MISC_keymap[XK_KP_4&0xFF] = SDLK_KP4;
  1026 	MISC_keymap[XK_KP_5&0xFF] = SDLK_KP5;
  1027 	MISC_keymap[XK_KP_6&0xFF] = SDLK_KP6;
  1028 	MISC_keymap[XK_KP_7&0xFF] = SDLK_KP7;
  1029 	MISC_keymap[XK_KP_8&0xFF] = SDLK_KP8;
  1030 	MISC_keymap[XK_KP_9&0xFF] = SDLK_KP9;
  1031 	MISC_keymap[XK_KP_Insert&0xFF] = SDLK_KP0;
  1032 	MISC_keymap[XK_KP_End&0xFF] = SDLK_KP1;	
  1033 	MISC_keymap[XK_KP_Down&0xFF] = SDLK_KP2;
  1034 	MISC_keymap[XK_KP_Page_Down&0xFF] = SDLK_KP3;
  1035 	MISC_keymap[XK_KP_Left&0xFF] = SDLK_KP4;
  1036 	MISC_keymap[XK_KP_Begin&0xFF] = SDLK_KP5;
  1037 	MISC_keymap[XK_KP_Right&0xFF] = SDLK_KP6;
  1038 	MISC_keymap[XK_KP_Home&0xFF] = SDLK_KP7;
  1039 	MISC_keymap[XK_KP_Up&0xFF] = SDLK_KP8;
  1040 	MISC_keymap[XK_KP_Page_Up&0xFF] = SDLK_KP9;
  1041 	MISC_keymap[XK_KP_Delete&0xFF] = SDLK_KP_PERIOD;
  1042 	MISC_keymap[XK_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
  1043 	MISC_keymap[XK_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
  1044 	MISC_keymap[XK_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
  1045 	MISC_keymap[XK_KP_Subtract&0xFF] = SDLK_KP_MINUS;
  1046 	MISC_keymap[XK_KP_Add&0xFF] = SDLK_KP_PLUS;
  1047 	MISC_keymap[XK_KP_Enter&0xFF] = SDLK_KP_ENTER;
  1048 	MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS;
  1049 
  1050 	MISC_keymap[XK_Up&0xFF] = SDLK_UP;
  1051 	MISC_keymap[XK_Down&0xFF] = SDLK_DOWN;
  1052 	MISC_keymap[XK_Right&0xFF] = SDLK_RIGHT;
  1053 	MISC_keymap[XK_Left&0xFF] = SDLK_LEFT;
  1054 	MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT;
  1055 	MISC_keymap[XK_Home&0xFF] = SDLK_HOME;
  1056 	MISC_keymap[XK_End&0xFF] = SDLK_END;
  1057 	MISC_keymap[XK_Page_Up&0xFF] = SDLK_PAGEUP;
  1058 	MISC_keymap[XK_Page_Down&0xFF] = SDLK_PAGEDOWN;
  1059 
  1060 	MISC_keymap[XK_F1&0xFF] = SDLK_F1;
  1061 	MISC_keymap[XK_F2&0xFF] = SDLK_F2;
  1062 	MISC_keymap[XK_F3&0xFF] = SDLK_F3;
  1063 	MISC_keymap[XK_F4&0xFF] = SDLK_F4;
  1064 	MISC_keymap[XK_F5&0xFF] = SDLK_F5;
  1065 	MISC_keymap[XK_F6&0xFF] = SDLK_F6;
  1066 	MISC_keymap[XK_F7&0xFF] = SDLK_F7;
  1067 	MISC_keymap[XK_F8&0xFF] = SDLK_F8;
  1068 	MISC_keymap[XK_F9&0xFF] = SDLK_F9;
  1069 	MISC_keymap[XK_F10&0xFF] = SDLK_F10;
  1070 	MISC_keymap[XK_F11&0xFF] = SDLK_F11;
  1071 	MISC_keymap[XK_F12&0xFF] = SDLK_F12;
  1072 	MISC_keymap[XK_F13&0xFF] = SDLK_F13;
  1073 	MISC_keymap[XK_F14&0xFF] = SDLK_F14;
  1074 	MISC_keymap[XK_F15&0xFF] = SDLK_F15;
  1075 
  1076 	MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK;
  1077 	MISC_keymap[XK_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
  1078 	MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
  1079 	MISC_keymap[XK_Shift_R&0xFF] = SDLK_RSHIFT;
  1080 	MISC_keymap[XK_Shift_L&0xFF] = SDLK_LSHIFT;
  1081 	MISC_keymap[XK_Control_R&0xFF] = SDLK_RCTRL;
  1082 	MISC_keymap[XK_Control_L&0xFF] = SDLK_LCTRL;
  1083 	MISC_keymap[XK_Alt_R&0xFF] = SDLK_RALT;
  1084 	MISC_keymap[XK_Alt_L&0xFF] = SDLK_LALT;
  1085 	MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA;
  1086 	MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA;
  1087 	MISC_keymap[XK_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
  1088 	MISC_keymap[XK_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
  1089 	MISC_keymap[XK_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
  1090 	MISC_keymap[XK_Multi_key&0xFF] = SDLK_COMPOSE; /* Multi-key compose */
  1091 
  1092 	MISC_keymap[XK_Help&0xFF] = SDLK_HELP;
  1093 	MISC_keymap[XK_Print&0xFF] = SDLK_PRINT;
  1094 	MISC_keymap[XK_Sys_Req&0xFF] = SDLK_SYSREQ;
  1095 	MISC_keymap[XK_Break&0xFF] = SDLK_BREAK;
  1096 	MISC_keymap[XK_Menu&0xFF] = SDLK_MENU;
  1097 	MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
  1098 }
  1099 
  1100 /* Get the translated SDL virtual keysym */
  1101 SDLKey X11_TranslateKeycode(Display *display, KeyCode kc)
  1102 {
  1103 	KeySym xsym;
  1104 	SDLKey key;
  1105 
  1106 	xsym = XKeycodeToKeysym(display, kc, 0);
  1107 #ifdef DEBUG_KEYS
  1108 	fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
  1109 #endif
  1110 	key = SDLK_UNKNOWN;
  1111 	if ( xsym ) {
  1112 		switch (xsym>>8) {
  1113 		    case 0x1005FF:
  1114 #ifdef SunXK_F36
  1115 			if ( xsym == SunXK_F36 )
  1116 				key = SDLK_F11;
  1117 #endif
  1118 #ifdef SunXK_F37
  1119 			if ( xsym == SunXK_F37 )
  1120 				key = SDLK_F12;
  1121 #endif
  1122 			break;
  1123 		    case 0x00:	/* Latin 1 */
  1124 			key = (SDLKey)(xsym & 0xFF);
  1125 			break;
  1126 		    case 0x01:	/* Latin 2 */
  1127 		    case 0x02:	/* Latin 3 */
  1128 		    case 0x03:	/* Latin 4 */
  1129 		    case 0x04:	/* Katakana */
  1130 		    case 0x05:	/* Arabic */
  1131 		    case 0x06:	/* Cyrillic */
  1132 		    case 0x07:	/* Greek */
  1133 		    case 0x08:	/* Technical */
  1134 		    case 0x0A:	/* Publishing */
  1135 		    case 0x0C:	/* Hebrew */
  1136 		    case 0x0D:	/* Thai */
  1137 			/* These are wrong, but it's better than nothing */
  1138 			key = (SDLKey)(xsym & 0xFF);
  1139 			break;
  1140 		    case 0xFE:
  1141 			key = ODD_keymap[xsym&0xFF];
  1142 			break;
  1143 		    case 0xFF:
  1144 			key = MISC_keymap[xsym&0xFF];
  1145 			break;
  1146 		    default:
  1147 			/*
  1148 			fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
  1149 					(unsigned int)xsym);
  1150 			*/
  1151 			break;
  1152 		}
  1153 	} else {
  1154 		/* X11 doesn't know how to translate the key! */
  1155 		switch (kc) {
  1156 		    /* Caution:
  1157 		       These keycodes are from the Microsoft Keyboard
  1158 		     */
  1159 		    case 115:
  1160 			key = SDLK_LSUPER;
  1161 			break;
  1162 		    case 116:
  1163 			key = SDLK_RSUPER;
  1164 			break;
  1165 		    case 117:
  1166 			key = SDLK_MENU;
  1167 			break;
  1168 		    default:
  1169 			/*
  1170 			 * no point in an error message; happens for
  1171 			 * several keys when we get a keymap notify
  1172 			 */
  1173 			break;
  1174 		}
  1175 	}
  1176 	return key;
  1177 }
  1178 
  1179 /* X11 modifier masks for various keys */
  1180 static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
  1181 static unsigned num_mask, mode_switch_mask;
  1182 
  1183 static void get_modifier_masks(Display *display)
  1184 {
  1185 	static unsigned got_masks;
  1186 	int i, j;
  1187 	XModifierKeymap *xmods;
  1188 	unsigned n;
  1189 
  1190 	if(got_masks)
  1191 		return;
  1192 
  1193 	xmods = XGetModifierMapping(display);
  1194 	n = xmods->max_keypermod;
  1195 	for(i = 3; i < 8; i++) {
  1196 		for(j = 0; j < n; j++) {
  1197 			KeyCode kc = xmods->modifiermap[i * n + j];
  1198 			KeySym ks = XKeycodeToKeysym(display, kc, 0);
  1199 			unsigned mask = 1 << i;
  1200 			switch(ks) {
  1201 			case XK_Num_Lock:
  1202 				num_mask = mask; break;
  1203 			case XK_Alt_L:
  1204 				alt_l_mask = mask; break;
  1205 			case XK_Alt_R:
  1206 				alt_r_mask = mask; break;
  1207 			case XK_Meta_L:
  1208 				meta_l_mask = mask; break;
  1209 			case XK_Meta_R:
  1210 				meta_r_mask = mask; break;
  1211 			case XK_Mode_switch:
  1212 				mode_switch_mask = mask; break;
  1213 			}
  1214 		}
  1215 	}
  1216 	XFreeModifiermap(xmods);
  1217 	got_masks = 1;
  1218 }
  1219 
  1220 
  1221 /*
  1222  * This function is semi-official; it is not officially exported and should
  1223  * not be considered part of the SDL API, but may be used by client code
  1224  * that *really* needs it (including legacy code).
  1225  * It is slow, though, and should be avoided if possible.
  1226  *
  1227  * Note that it isn't completely accurate either; in particular, multi-key
  1228  * sequences (dead accents, compose key sequences) will not work since the
  1229  * state has been irrevocably lost.
  1230  */
  1231 Uint16 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers)
  1232 {
  1233 	struct SDL_VideoDevice *this = current_video;
  1234 	char keybuf[32];
  1235 	int i;
  1236 	KeySym xsym = 0;
  1237 	XKeyEvent xkey;
  1238 	Uint16 unicode;
  1239 
  1240 	if ( !this || !SDL_Display ) {
  1241 		return 0;
  1242 	}
  1243 
  1244 	SDL_memset(&xkey, 0, sizeof(xkey));
  1245 	xkey.display = SDL_Display;
  1246 
  1247 	xsym = keysym;		/* last resort if not found */
  1248 	for (i = 0; i < 256; ++i) {
  1249 		if ( MISC_keymap[i] == keysym ) {
  1250 			xsym = 0xFF00 | i;
  1251 			break;
  1252 		} else if ( ODD_keymap[i] == keysym ) {
  1253 			xsym = 0xFE00 | i;
  1254 			break;
  1255 		}
  1256 	}
  1257 
  1258 	xkey.keycode = XKeysymToKeycode(xkey.display, xsym);
  1259 
  1260 	get_modifier_masks(SDL_Display);
  1261 	if(modifiers & KMOD_SHIFT)
  1262 		xkey.state |= ShiftMask;
  1263 	if(modifiers & KMOD_CAPS)
  1264 		xkey.state |= LockMask;
  1265 	if(modifiers & KMOD_CTRL)
  1266 		xkey.state |= ControlMask;
  1267 	if(modifiers & KMOD_MODE)
  1268 		xkey.state |= mode_switch_mask;
  1269 	if(modifiers & KMOD_LALT)
  1270 		xkey.state |= alt_l_mask;
  1271 	if(modifiers & KMOD_RALT)
  1272 		xkey.state |= alt_r_mask;
  1273 	if(modifiers & KMOD_LMETA)
  1274 		xkey.state |= meta_l_mask;
  1275 	if(modifiers & KMOD_RMETA)
  1276 		xkey.state |= meta_r_mask;
  1277 	if(modifiers & KMOD_NUM)
  1278 		xkey.state |= num_mask;
  1279 
  1280 	unicode = 0;
  1281 	if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) )
  1282 		unicode = (unsigned char)keybuf[0];
  1283 	return(unicode);
  1284 }
  1285 
  1286 
  1287 /*
  1288  * Called when focus is regained, to read the keyboard state and generate
  1289  * synthetic keypress/release events.
  1290  * key_vec is a bit vector of keycodes (256 bits)
  1291  */
  1292 void X11_SetKeyboardState(Display *display, const char *key_vec)
  1293 {
  1294 	char keys_return[32];
  1295 	int i;
  1296 	Uint8 *kstate = SDL_GetKeyState(NULL);
  1297 	SDLMod modstate;
  1298 	Window junk_window;
  1299 	int x, y;
  1300 	unsigned int mask;
  1301 
  1302 	/* The first time the window is mapped, we initialize key state */
  1303 	if ( ! key_vec ) {
  1304 		XQueryKeymap(display, keys_return);
  1305 		key_vec = keys_return;
  1306 	}
  1307 
  1308 	/* Get the keyboard modifier state */
  1309 	modstate = 0;
  1310 	get_modifier_masks(display);
  1311 	if ( XQueryPointer(display, DefaultRootWindow(display),
  1312 		&junk_window, &junk_window, &x, &y, &x, &y, &mask) ) {
  1313 		if ( mask & LockMask ) {
  1314 			modstate |= KMOD_CAPS;
  1315 		}
  1316 		if ( mask & mode_switch_mask ) {
  1317 			modstate |= KMOD_MODE;
  1318 		}
  1319 		if ( mask & num_mask ) {
  1320 			modstate |= KMOD_NUM;
  1321 		}
  1322 	}
  1323 
  1324 	/* Zero the new keyboard state and generate it */
  1325 	SDL_memset(kstate, 0, SDLK_LAST);
  1326 	/*
  1327 	 * An obvious optimisation is to check entire longwords at a time in
  1328 	 * both loops, but we can't be sure the arrays are aligned so it's not
  1329 	 * worth the extra complexity
  1330 	 */
  1331 	for ( i = 0; i < 32; i++ ) {
  1332 		int j;
  1333 		if ( !key_vec[i] )
  1334 			continue;
  1335 		for ( j = 0; j < 8; j++ ) {
  1336 			if ( key_vec[i] & (1 << j) ) {
  1337 				SDLKey key;
  1338 				KeyCode kc = (i << 3 | j);
  1339 				key = X11_TranslateKeycode(display, kc);
  1340 				if ( key == SDLK_UNKNOWN ) {
  1341 					continue;
  1342 				}
  1343 				kstate[key] = SDL_PRESSED;
  1344 				switch (key) {
  1345 				    case SDLK_LSHIFT:
  1346 					modstate |= KMOD_LSHIFT;
  1347 					break;
  1348 				    case SDLK_RSHIFT:
  1349 					modstate |= KMOD_RSHIFT;
  1350 					break;
  1351 				    case SDLK_LCTRL:
  1352 					modstate |= KMOD_LCTRL;
  1353 					break;
  1354 				    case SDLK_RCTRL:
  1355 					modstate |= KMOD_RCTRL;
  1356 					break;
  1357 				    case SDLK_LALT:
  1358 					modstate |= KMOD_LALT;
  1359 					break;
  1360 				    case SDLK_RALT:
  1361 					modstate |= KMOD_RALT;
  1362 					break;
  1363 				    case SDLK_LMETA:
  1364 					modstate |= KMOD_LMETA;
  1365 					break;
  1366 				    case SDLK_RMETA:
  1367 					modstate |= KMOD_RMETA;
  1368 					break;
  1369 				    default:
  1370 					break;
  1371 				}
  1372 			}
  1373 		}
  1374 	}
  1375 
  1376 	/* Hack - set toggle key state */
  1377 	if ( modstate & KMOD_CAPS ) {
  1378 		kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
  1379 	} else {
  1380 		kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
  1381 	}
  1382 	if ( modstate & KMOD_NUM ) {
  1383 		kstate[SDLK_NUMLOCK] = SDL_PRESSED;
  1384 	} else {
  1385 		kstate[SDLK_NUMLOCK] = SDL_RELEASED;
  1386 	}
  1387 
  1388 	/* Set the final modifier state */
  1389 	SDL_SetModState(modstate);
  1390 }
  1391 
  1392 void X11_InitOSKeymap(_THIS)
  1393 {
  1394 	X11_InitKeymap();
  1395 }
  1396