symbian-qemu-0.9.1-12/libsdl-trunk/src/video/x11/SDL_x11events.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 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 ( (xevent.xcrossing.mode != NotifyGrab) &&
       
   427 		     (xevent.xcrossing.mode != NotifyUngrab) ) {
       
   428 			if ( this->input_grab == SDL_GRAB_OFF ) {
       
   429 				posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
       
   430 			}
       
   431 			posted = SDL_PrivateMouseMotion(0, 0,
       
   432 					xevent.xcrossing.x,
       
   433 					xevent.xcrossing.y);
       
   434 		}
       
   435 	    }
       
   436 	    break;
       
   437 
       
   438 	    /* Losing mouse coverage? */
       
   439 	    case LeaveNotify: {
       
   440 #ifdef DEBUG_XEVENTS
       
   441 printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y);
       
   442 if ( xevent.xcrossing.mode == NotifyGrab )
       
   443 printf("Mode: NotifyGrab\n");
       
   444 if ( xevent.xcrossing.mode == NotifyUngrab )
       
   445 printf("Mode: NotifyUngrab\n");
       
   446 #endif
       
   447 		if ( (xevent.xcrossing.mode != NotifyGrab) &&
       
   448 		     (xevent.xcrossing.mode != NotifyUngrab) &&
       
   449 		     (xevent.xcrossing.detail != NotifyInferior) ) {
       
   450 			if ( this->input_grab == SDL_GRAB_OFF ) {
       
   451 				posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
       
   452 			} else {
       
   453 				posted = SDL_PrivateMouseMotion(0, 0,
       
   454 						xevent.xcrossing.x,
       
   455 						xevent.xcrossing.y);
       
   456 			}
       
   457 		}
       
   458 	    }
       
   459 	    break;
       
   460 
       
   461 	    /* Gaining input focus? */
       
   462 	    case FocusIn: {
       
   463 #ifdef DEBUG_XEVENTS
       
   464 printf("FocusIn!\n");
       
   465 #endif
       
   466 		posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
       
   467 
       
   468 #ifdef X_HAVE_UTF8_STRING
       
   469 		if ( SDL_IC != NULL ) {
       
   470 			XSetICFocus(SDL_IC);
       
   471 		}
       
   472 #endif
       
   473 		/* Queue entry into fullscreen mode */
       
   474 		switch_waiting = 0x01 | SDL_FULLSCREEN;
       
   475 		switch_time = SDL_GetTicks() + 1500;
       
   476 	    }
       
   477 	    break;
       
   478 
       
   479 	    /* Losing input focus? */
       
   480 	    case FocusOut: {
       
   481 #ifdef DEBUG_XEVENTS
       
   482 printf("FocusOut!\n");
       
   483 #endif
       
   484 		posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
       
   485 
       
   486 #ifdef X_HAVE_UTF8_STRING
       
   487 		if ( SDL_IC != NULL ) {
       
   488 			XUnsetICFocus(SDL_IC);
       
   489 		}
       
   490 #endif
       
   491 		/* Queue leaving fullscreen mode */
       
   492 		switch_waiting = 0x01;
       
   493 		switch_time = SDL_GetTicks() + 200;
       
   494 	    }
       
   495 	    break;
       
   496 
       
   497 #ifdef X_HAVE_UTF8_STRING
       
   498 	    /* Some IM requires MappingNotify to be passed to
       
   499 	       XRefreshKeyboardMapping by the app.  */
       
   500 	    case MappingNotify: {
       
   501 		XRefreshKeyboardMapping(&xevent.xmapping);
       
   502 	    }
       
   503 	    break;
       
   504 #endif /* X_HAVE_UTF8_STRING */
       
   505 
       
   506 	    /* Generated upon EnterWindow and FocusIn */
       
   507 	    case KeymapNotify: {
       
   508 #ifdef DEBUG_XEVENTS
       
   509 printf("KeymapNotify!\n");
       
   510 #endif
       
   511 		X11_SetKeyboardState(SDL_Display,  xevent.xkeymap.key_vector);
       
   512 	    }
       
   513 	    break;
       
   514 
       
   515 	    /* Mouse motion? */
       
   516 	    case MotionNotify: {
       
   517 		if ( SDL_VideoSurface ) {
       
   518 			if ( mouse_relative ) {
       
   519 				if ( using_dga & DGA_MOUSE ) {
       
   520 #ifdef DEBUG_MOTION
       
   521   printf("DGA motion: %d,%d\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
       
   522 #endif
       
   523 					posted = SDL_PrivateMouseMotion(0, 1,
       
   524 							xevent.xmotion.x_root,
       
   525 							xevent.xmotion.y_root);
       
   526 				} else {
       
   527 					posted = X11_WarpedMotion(this,&xevent);
       
   528 				}
       
   529 			} else {
       
   530 #ifdef DEBUG_MOTION
       
   531   printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
       
   532 #endif
       
   533 				posted = SDL_PrivateMouseMotion(0, 0,
       
   534 						xevent.xmotion.x,
       
   535 						xevent.xmotion.y);
       
   536 			}
       
   537 		}
       
   538 	    }
       
   539 	    break;
       
   540 
       
   541 	    /* Mouse button press? */
       
   542 	    case ButtonPress: {
       
   543 		posted = SDL_PrivateMouseButton(SDL_PRESSED, 
       
   544 					xevent.xbutton.button, 0, 0);
       
   545 	    }
       
   546 	    break;
       
   547 
       
   548 	    /* Mouse button release? */
       
   549 	    case ButtonRelease: {
       
   550 		posted = SDL_PrivateMouseButton(SDL_RELEASED, 
       
   551 					xevent.xbutton.button, 0, 0);
       
   552 	    }
       
   553 	    break;
       
   554 
       
   555 	    /* Key press? */
       
   556 	    case KeyPress: {
       
   557 		SDL_keysym keysym;
       
   558 		KeyCode keycode = xevent.xkey.keycode;
       
   559 
       
   560 #ifdef DEBUG_XEVENTS
       
   561 printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
       
   562 #endif
       
   563 		/* If we're not doing translation, we're done! */
       
   564 		if ( !SDL_TranslateUNICODE ) {
       
   565 			/* Get the translated SDL virtual keysym and put it on the queue.*/
       
   566 			keysym.scancode = keycode;
       
   567 			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
       
   568 			keysym.mod = KMOD_NONE;
       
   569 			keysym.unicode = 0;
       
   570 			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
       
   571 			break;
       
   572 		}
       
   573 
       
   574 		/* Look up the translated value for the key event */
       
   575 #ifdef X_HAVE_UTF8_STRING
       
   576 		if ( SDL_IC != NULL ) {
       
   577 			Status status;
       
   578 			KeySym xkeysym;
       
   579 			int i;
       
   580 			/* A UTF-8 character can be at most 6 bytes */
       
   581 			/* ... It's true, but Xutf8LookupString can
       
   582 			   return more than one characters.  Moreover,
       
   583 			   the spec. put no upper bound, so we should
       
   584 			   be ready for longer strings.  */
       
   585 			char keybuf[32];
       
   586 			char *keydata = keybuf;
       
   587 			int count;
       
   588 			Uint16 utf16buf[32];
       
   589 			Uint16 *utf16data = utf16buf;
       
   590 			int utf16size;
       
   591 			int utf16length;
       
   592 
       
   593 			count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, sizeof(keybuf), &xkeysym, &status);
       
   594 			if (XBufferOverflow == status) {
       
   595 			  /* The IM has just generated somewhat long
       
   596 			     string.  We need a longer buffer in this
       
   597 			     case.  */
       
   598 			  keydata = SDL_malloc(count);
       
   599 			  if ( keydata == NULL ) {
       
   600 			    SDL_OutOfMemory();
       
   601 			    break;
       
   602 			  }
       
   603 			  count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, count, &xkeysym, &status);
       
   604 			}
       
   605 
       
   606 			switch (status) {
       
   607 
       
   608 			case XBufferOverflow: {
       
   609 			  /* Oops!  We have allocated the bytes as
       
   610 			     requested by Xutf8LookupString, so the
       
   611 			     length of the buffer must be
       
   612 			     sufficient.  This case should never
       
   613 			     happen! */
       
   614 			  SDL_SetError("Xutf8LookupString indicated a double buffer overflow!");
       
   615 			  break;
       
   616 			}
       
   617 
       
   618 			case XLookupChars:
       
   619 			case XLookupBoth: {
       
   620 			  if (0 == count) {
       
   621 			    break;
       
   622 			  }
       
   623 
       
   624 			  /* We got a converted string from IM.  Make
       
   625 			     sure to deliver all characters to the
       
   626 			     application as SDL events.  Note that
       
   627 			     an SDL event can only carry one UTF-16
       
   628 			     encoding unit, and a surrogate pair is
       
   629 			     delivered as two SDL events.  I guess
       
   630 			     this behaviour is probably _imported_
       
   631 			     from Windows or MacOS.  To do so, we need
       
   632 			     to convert the UTF-8 data into UTF-16
       
   633 			     data (not UCS4/UTF-32!).  We need an
       
   634 			     estimate of the number of UTF-16 encoding
       
   635 			     units here.  The worst case is pure ASCII
       
   636 			     string.  Assume so. */
       
   637 			  /* In 1.3 SDL may have a text event instead, that
       
   638 			     carries the whole UTF-8 string with it. */
       
   639 			  utf16size = count * sizeof(Uint16);
       
   640 			  if (utf16size > sizeof(utf16buf)) {
       
   641 			    utf16data = (Uint16 *) SDL_malloc(utf16size);
       
   642 			    if (utf16data == NULL) {
       
   643 			      SDL_OutOfMemory();
       
   644 			      break;
       
   645 			    }
       
   646 			  }
       
   647 			  utf16length = Utf8ToUtf16((Uint8 *)keydata, count, utf16data, utf16size);
       
   648 			  if (utf16length < 0) {
       
   649 			    /* The keydata contained an invalid byte
       
   650 			       sequence.  It should be a bug of the IM
       
   651 			       or Xlib... */
       
   652 			    SDL_SetError("Oops! Xutf8LookupString returned an invalid UTF-8 sequence!");
       
   653 			    break;
       
   654 			  }
       
   655 
       
   656 			  /* Deliver all UTF-16 encoding units.  At
       
   657 			     this moment, SDL event queue has a
       
   658 			     fixed size (128 events), and an SDL
       
   659 			     event can hold just one UTF-16 encoding
       
   660 			     unit.  So, if we receive more than 128
       
   661 			     UTF-16 encoding units from a commit,
       
   662 			     exceeded characters will be lost.  */
       
   663 			  for (i = 0; i < utf16length - 1; i++) {
       
   664 			    keysym.scancode = 0;
       
   665 			    keysym.sym = SDLK_UNKNOWN;
       
   666 			    keysym.mod = KMOD_NONE;
       
   667 			    keysym.unicode = utf16data[i];
       
   668 			    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
       
   669 			  }
       
   670 			  /* The keysym for the last character carries the
       
   671 			     scancode and symbol that corresponds to the X11
       
   672 			     keycode.  */
       
   673 			  if (utf16length > 0) {			       
       
   674 			    keysym.scancode = keycode;
       
   675 			    keysym.sym = (keycode ? X11_TranslateKeycode(SDL_Display, keycode) : 0);
       
   676 			    keysym.mod = KMOD_NONE;
       
   677 			    keysym.unicode = utf16data[utf16length - 1];
       
   678 			    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
       
   679 			  }
       
   680 			  break;
       
   681 			}
       
   682 
       
   683 			case XLookupKeySym: {
       
   684 			  /* I'm not sure whether it is possible that
       
   685 			     a zero keycode makes XLookupKeySym
       
   686 			     status.  What I'm sure is that a
       
   687 			     combination of a zero scan code and a non
       
   688 			     zero sym makes SDL_PrivateKeyboard
       
   689 			     strange state...  So, just discard it.
       
   690 			     If this doesn't work, I'm receiving bug
       
   691 			     reports, and I can know under what
       
   692 			     condition this case happens.  */
       
   693 			  if (keycode) {
       
   694 			    keysym.scancode = keycode;
       
   695 			    keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
       
   696 			    keysym.mod = KMOD_NONE;
       
   697 			    keysym.unicode = 0;
       
   698 			    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
       
   699 			  }
       
   700 			  break;
       
   701 			}
       
   702 
       
   703 			case XLookupNone: {
       
   704 			  /* IM has eaten the event.  */
       
   705 			  break;
       
   706 			}
       
   707 
       
   708 			default:
       
   709 			  /* An unknown status from Xutf8LookupString.  */
       
   710 			  SDL_SetError("Oops! Xutf8LookupStringreturned an unknown status");
       
   711 			}
       
   712 
       
   713 			/* Release dynamic buffers if allocated.  */
       
   714 			if (keydata != NULL && keybuf != keydata) {
       
   715 			  SDL_free(keydata);
       
   716 			}
       
   717 			if (utf16data != NULL && utf16buf != utf16data) {
       
   718 			  SDL_free(utf16data);
       
   719 			}
       
   720 		}
       
   721 		else
       
   722 #endif
       
   723 		{
       
   724 			static XComposeStatus state;
       
   725 			char keybuf[32];
       
   726 
       
   727 			keysym.scancode = keycode;
       
   728 			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
       
   729 			keysym.mod = KMOD_NONE;
       
   730 			keysym.unicode = 0;
       
   731 			if ( XLookupString(&xevent.xkey,
       
   732 			                    keybuf, sizeof(keybuf),
       
   733 			                    NULL, &state) ) {
       
   734 				/*
       
   735 				* FIXME: XLookupString() may yield more than one
       
   736 				* character, so we need a mechanism to allow for
       
   737 				* this (perhaps null keypress events with a
       
   738 				* unicode value)
       
   739 				*/
       
   740 				keysym.unicode = (Uint8)keybuf[0];
       
   741 			}
       
   742 
       
   743 			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
       
   744 		}
       
   745 	    }
       
   746 	    break;
       
   747 
       
   748 	    /* Key release? */
       
   749 	    case KeyRelease: {
       
   750 		SDL_keysym keysym;
       
   751 		KeyCode keycode = xevent.xkey.keycode;
       
   752 
       
   753 		if (keycode == 0) {
       
   754 		  /* There should be no KeyRelease for keycode == 0,
       
   755 		     since it is a notification from IM but a real
       
   756 		     keystroke.  */
       
   757 		  /* We need to emit some diagnostic message here.  */
       
   758 		  break;
       
   759 		}
       
   760 
       
   761 #ifdef DEBUG_XEVENTS
       
   762 printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
       
   763 #endif
       
   764 
       
   765 		/* Get the translated SDL virtual keysym */
       
   766 		keysym.scancode = keycode;
       
   767 		keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
       
   768 		keysym.mod = KMOD_NONE;
       
   769 		keysym.unicode = 0;
       
   770 
       
   771 		posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
       
   772 	    }
       
   773 	    break;
       
   774 
       
   775 	    /* Have we been iconified? */
       
   776 	    case UnmapNotify: {
       
   777 #ifdef DEBUG_XEVENTS
       
   778 printf("UnmapNotify!\n");
       
   779 #endif
       
   780 		/* If we're active, make ourselves inactive */
       
   781 		if ( SDL_GetAppState() & SDL_APPACTIVE ) {
       
   782 			/* Swap out the gamma before we go inactive */
       
   783 			X11_SwapVidModeGamma(this);
       
   784 
       
   785 			/* Send an internal deactivate event */
       
   786 			posted = SDL_PrivateAppActive(0,
       
   787 					SDL_APPACTIVE|SDL_APPINPUTFOCUS);
       
   788 		}
       
   789 	    }
       
   790 	    break;
       
   791 
       
   792 	    /* Have we been restored? */
       
   793 	    case MapNotify: {
       
   794 #ifdef DEBUG_XEVENTS
       
   795 printf("MapNotify!\n");
       
   796 #endif
       
   797 		/* If we're not active, make ourselves active */
       
   798 		if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) {
       
   799 			/* Send an internal activate event */
       
   800 			posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
       
   801 
       
   802 			/* Now that we're active, swap the gamma back */
       
   803 			X11_SwapVidModeGamma(this);
       
   804 		}
       
   805 
       
   806 		if ( SDL_VideoSurface &&
       
   807 		     (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
       
   808 			X11_EnterFullScreen(this);
       
   809 		} else {
       
   810 			X11_GrabInputNoLock(this, this->input_grab);
       
   811 		}
       
   812 		X11_CheckMouseModeNoLock(this);
       
   813 
       
   814 		if ( SDL_VideoSurface ) {
       
   815 			X11_RefreshDisplay(this);
       
   816 		}
       
   817 	    }
       
   818 	    break;
       
   819 
       
   820 	    /* Have we been resized or moved? */
       
   821 	    case ConfigureNotify: {
       
   822 #ifdef DEBUG_XEVENTS
       
   823 printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height);
       
   824 #endif
       
   825 		if ( SDL_VideoSurface ) {
       
   826 		    if ((xevent.xconfigure.width != SDL_VideoSurface->w) ||
       
   827 		        (xevent.xconfigure.height != SDL_VideoSurface->h)) {
       
   828 			/* FIXME: Find a better fix for the bug with KDE 1.2 */
       
   829 			if ( ! ((xevent.xconfigure.width == 32) &&
       
   830 			        (xevent.xconfigure.height == 32)) ) {
       
   831 				SDL_PrivateResize(xevent.xconfigure.width,
       
   832 				                  xevent.xconfigure.height);
       
   833 			}
       
   834 		    } else {
       
   835 			/* OpenGL windows need to know about the change */
       
   836 			if ( SDL_VideoSurface->flags & SDL_OPENGL ) {
       
   837 				SDL_PrivateExpose();
       
   838 			}
       
   839 		    }
       
   840 		}
       
   841 	    }
       
   842 	    break;
       
   843 
       
   844 	    /* Have we been requested to quit (or another client message?) */
       
   845 	    case ClientMessage: {
       
   846 		if ( (xevent.xclient.format == 32) &&
       
   847 		     (xevent.xclient.data.l[0] == WM_DELETE_WINDOW) )
       
   848 		{
       
   849 			posted = SDL_PrivateQuit();
       
   850 		} else
       
   851 		if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
       
   852 			SDL_SysWMmsg wmmsg;
       
   853 
       
   854 			SDL_VERSION(&wmmsg.version);
       
   855 			wmmsg.subsystem = SDL_SYSWM_X11;
       
   856 			wmmsg.event.xevent = xevent;
       
   857 			posted = SDL_PrivateSysWMEvent(&wmmsg);
       
   858 		}
       
   859 	    }
       
   860 	    break;
       
   861 
       
   862 	    /* Do we need to refresh ourselves? */
       
   863 	    case Expose: {
       
   864 #ifdef DEBUG_XEVENTS
       
   865 printf("Expose (count = %d)\n", xevent.xexpose.count);
       
   866 #endif
       
   867 		if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) {
       
   868 			X11_RefreshDisplay(this);
       
   869 		}
       
   870 	    }
       
   871 	    break;
       
   872 
       
   873 	    default: {
       
   874 #ifdef DEBUG_XEVENTS
       
   875 printf("Unhandled event %d\n", xevent.type);
       
   876 #endif
       
   877 		/* Only post the event if we're watching for it */
       
   878 		if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
       
   879 			SDL_SysWMmsg wmmsg;
       
   880 
       
   881 			SDL_VERSION(&wmmsg.version);
       
   882 			wmmsg.subsystem = SDL_SYSWM_X11;
       
   883 			wmmsg.event.xevent = xevent;
       
   884 			posted = SDL_PrivateSysWMEvent(&wmmsg);
       
   885 		}
       
   886 	    }
       
   887 	    break;
       
   888 	}
       
   889 	return(posted);
       
   890 }
       
   891 
       
   892 /* Ack!  XPending() actually performs a blocking read if no events available */
       
   893 int X11_Pending(Display *display)
       
   894 {
       
   895 	/* Flush the display connection and look to see if events are queued */
       
   896 	XFlush(display);
       
   897 	if ( XEventsQueued(display, QueuedAlready) ) {
       
   898 		return(1);
       
   899 	}
       
   900 
       
   901 	/* More drastic measures are required -- see if X is ready to talk */
       
   902 	{
       
   903 		static struct timeval zero_time;	/* static == 0 */
       
   904 		int x11_fd;
       
   905 		fd_set fdset;
       
   906 
       
   907 		x11_fd = ConnectionNumber(display);
       
   908 		FD_ZERO(&fdset);
       
   909 		FD_SET(x11_fd, &fdset);
       
   910 		if ( select(x11_fd+1, &fdset, NULL, NULL, &zero_time) == 1 ) {
       
   911 			return(XPending(display));
       
   912 		}
       
   913 	}
       
   914 
       
   915 	/* Oh well, nothing is ready .. */
       
   916 	return(0);
       
   917 }
       
   918 
       
   919 void X11_PumpEvents(_THIS)
       
   920 {
       
   921 	int pending;
       
   922 
       
   923 	/* Keep processing pending events */
       
   924 	pending = 0;
       
   925 	while ( X11_Pending(SDL_Display) ) {
       
   926 		X11_DispatchEvent(this);
       
   927 		++pending;
       
   928 	}
       
   929 	if ( switch_waiting ) {
       
   930 		Uint32 now;
       
   931 
       
   932 		now  = SDL_GetTicks();
       
   933 		if ( pending || !SDL_VideoSurface ) {
       
   934 			/* Try again later... */
       
   935 			if ( switch_waiting & SDL_FULLSCREEN ) {
       
   936 				switch_time = now + 1500;
       
   937 			} else {
       
   938 				switch_time = now + 200;
       
   939 			}
       
   940 		} else if ( (int)(switch_time-now) <= 0 ) {
       
   941 			Uint32 go_fullscreen;
       
   942 
       
   943 			go_fullscreen = switch_waiting & SDL_FULLSCREEN;
       
   944 			switch_waiting = 0;
       
   945 			if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
       
   946 				if ( go_fullscreen ) {
       
   947 					X11_EnterFullScreen(this);
       
   948 				} else {
       
   949 					X11_LeaveFullScreen(this);
       
   950 				}
       
   951 			}
       
   952 			/* Handle focus in/out when grabbed */
       
   953 			if ( go_fullscreen ) {
       
   954 				X11_GrabInputNoLock(this, this->input_grab);
       
   955 			} else {
       
   956 				X11_GrabInputNoLock(this, SDL_GRAB_OFF);
       
   957 			}
       
   958 			X11_CheckMouseModeNoLock(this);
       
   959 		}
       
   960 	}
       
   961 }
       
   962 
       
   963 void X11_InitKeymap(void)
       
   964 {
       
   965 	int i;
       
   966 
       
   967 	/* Odd keys used in international keyboards */
       
   968 	for ( i=0; i<SDL_arraysize(ODD_keymap); ++i )
       
   969 		ODD_keymap[i] = SDLK_UNKNOWN;
       
   970 
       
   971  	/* Some of these might be mappable to an existing SDLK_ code */
       
   972  	ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
       
   973  	ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE;
       
   974  	ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE;
       
   975  	ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE;
       
   976  	ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE;
       
   977  	ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE;
       
   978  	ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE;
       
   979  	ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE;
       
   980  	ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE;
       
   981  	ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE;
       
   982  	ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE;
       
   983  	ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE;
       
   984  	ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE;
       
   985  	ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE;
       
   986  	ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE;
       
   987  	ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE;
       
   988 #ifdef XK_dead_hook
       
   989  	ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE;
       
   990 #endif
       
   991 #ifdef XK_dead_horn
       
   992  	ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE;
       
   993 #endif
       
   994 
       
   995 #ifdef XK_dead_circumflex
       
   996 	/* These X keysyms have 0xFE as the high byte */
       
   997 	ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
       
   998 #endif
       
   999 #ifdef XK_ISO_Level3_Shift
       
  1000 	ODD_keymap[XK_ISO_Level3_Shift&0xFF] = SDLK_MODE; /* "Alt Gr" key */
       
  1001 #endif
       
  1002 
       
  1003 	/* Map the miscellaneous keys */
       
  1004 	for ( i=0; i<SDL_arraysize(MISC_keymap); ++i )
       
  1005 		MISC_keymap[i] = SDLK_UNKNOWN;
       
  1006 
       
  1007 	/* These X keysyms have 0xFF as the high byte */
       
  1008 	MISC_keymap[XK_BackSpace&0xFF] = SDLK_BACKSPACE;
       
  1009 	MISC_keymap[XK_Tab&0xFF] = SDLK_TAB;
       
  1010 	MISC_keymap[XK_Clear&0xFF] = SDLK_CLEAR;
       
  1011 	MISC_keymap[XK_Return&0xFF] = SDLK_RETURN;
       
  1012 	MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE;
       
  1013 	MISC_keymap[XK_Escape&0xFF] = SDLK_ESCAPE;
       
  1014 	MISC_keymap[XK_Delete&0xFF] = SDLK_DELETE;
       
  1015 
       
  1016 	MISC_keymap[XK_KP_0&0xFF] = SDLK_KP0;		/* Keypad 0-9 */
       
  1017 	MISC_keymap[XK_KP_1&0xFF] = SDLK_KP1;
       
  1018 	MISC_keymap[XK_KP_2&0xFF] = SDLK_KP2;
       
  1019 	MISC_keymap[XK_KP_3&0xFF] = SDLK_KP3;
       
  1020 	MISC_keymap[XK_KP_4&0xFF] = SDLK_KP4;
       
  1021 	MISC_keymap[XK_KP_5&0xFF] = SDLK_KP5;
       
  1022 	MISC_keymap[XK_KP_6&0xFF] = SDLK_KP6;
       
  1023 	MISC_keymap[XK_KP_7&0xFF] = SDLK_KP7;
       
  1024 	MISC_keymap[XK_KP_8&0xFF] = SDLK_KP8;
       
  1025 	MISC_keymap[XK_KP_9&0xFF] = SDLK_KP9;
       
  1026 	MISC_keymap[XK_KP_Insert&0xFF] = SDLK_KP0;
       
  1027 	MISC_keymap[XK_KP_End&0xFF] = SDLK_KP1;	
       
  1028 	MISC_keymap[XK_KP_Down&0xFF] = SDLK_KP2;
       
  1029 	MISC_keymap[XK_KP_Page_Down&0xFF] = SDLK_KP3;
       
  1030 	MISC_keymap[XK_KP_Left&0xFF] = SDLK_KP4;
       
  1031 	MISC_keymap[XK_KP_Begin&0xFF] = SDLK_KP5;
       
  1032 	MISC_keymap[XK_KP_Right&0xFF] = SDLK_KP6;
       
  1033 	MISC_keymap[XK_KP_Home&0xFF] = SDLK_KP7;
       
  1034 	MISC_keymap[XK_KP_Up&0xFF] = SDLK_KP8;
       
  1035 	MISC_keymap[XK_KP_Page_Up&0xFF] = SDLK_KP9;
       
  1036 	MISC_keymap[XK_KP_Delete&0xFF] = SDLK_KP_PERIOD;
       
  1037 	MISC_keymap[XK_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
       
  1038 	MISC_keymap[XK_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
       
  1039 	MISC_keymap[XK_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
       
  1040 	MISC_keymap[XK_KP_Subtract&0xFF] = SDLK_KP_MINUS;
       
  1041 	MISC_keymap[XK_KP_Add&0xFF] = SDLK_KP_PLUS;
       
  1042 	MISC_keymap[XK_KP_Enter&0xFF] = SDLK_KP_ENTER;
       
  1043 	MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS;
       
  1044 
       
  1045 	MISC_keymap[XK_Up&0xFF] = SDLK_UP;
       
  1046 	MISC_keymap[XK_Down&0xFF] = SDLK_DOWN;
       
  1047 	MISC_keymap[XK_Right&0xFF] = SDLK_RIGHT;
       
  1048 	MISC_keymap[XK_Left&0xFF] = SDLK_LEFT;
       
  1049 	MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT;
       
  1050 	MISC_keymap[XK_Home&0xFF] = SDLK_HOME;
       
  1051 	MISC_keymap[XK_End&0xFF] = SDLK_END;
       
  1052 	MISC_keymap[XK_Page_Up&0xFF] = SDLK_PAGEUP;
       
  1053 	MISC_keymap[XK_Page_Down&0xFF] = SDLK_PAGEDOWN;
       
  1054 
       
  1055 	MISC_keymap[XK_F1&0xFF] = SDLK_F1;
       
  1056 	MISC_keymap[XK_F2&0xFF] = SDLK_F2;
       
  1057 	MISC_keymap[XK_F3&0xFF] = SDLK_F3;
       
  1058 	MISC_keymap[XK_F4&0xFF] = SDLK_F4;
       
  1059 	MISC_keymap[XK_F5&0xFF] = SDLK_F5;
       
  1060 	MISC_keymap[XK_F6&0xFF] = SDLK_F6;
       
  1061 	MISC_keymap[XK_F7&0xFF] = SDLK_F7;
       
  1062 	MISC_keymap[XK_F8&0xFF] = SDLK_F8;
       
  1063 	MISC_keymap[XK_F9&0xFF] = SDLK_F9;
       
  1064 	MISC_keymap[XK_F10&0xFF] = SDLK_F10;
       
  1065 	MISC_keymap[XK_F11&0xFF] = SDLK_F11;
       
  1066 	MISC_keymap[XK_F12&0xFF] = SDLK_F12;
       
  1067 	MISC_keymap[XK_F13&0xFF] = SDLK_F13;
       
  1068 	MISC_keymap[XK_F14&0xFF] = SDLK_F14;
       
  1069 	MISC_keymap[XK_F15&0xFF] = SDLK_F15;
       
  1070 
       
  1071 	MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK;
       
  1072 	MISC_keymap[XK_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
       
  1073 	MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
       
  1074 	MISC_keymap[XK_Shift_R&0xFF] = SDLK_RSHIFT;
       
  1075 	MISC_keymap[XK_Shift_L&0xFF] = SDLK_LSHIFT;
       
  1076 	MISC_keymap[XK_Control_R&0xFF] = SDLK_RCTRL;
       
  1077 	MISC_keymap[XK_Control_L&0xFF] = SDLK_LCTRL;
       
  1078 	MISC_keymap[XK_Alt_R&0xFF] = SDLK_RALT;
       
  1079 	MISC_keymap[XK_Alt_L&0xFF] = SDLK_LALT;
       
  1080 	MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA;
       
  1081 	MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA;
       
  1082 	MISC_keymap[XK_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
       
  1083 	MISC_keymap[XK_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
       
  1084 	MISC_keymap[XK_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
       
  1085 	MISC_keymap[XK_Multi_key&0xFF] = SDLK_COMPOSE; /* Multi-key compose */
       
  1086 
       
  1087 	MISC_keymap[XK_Help&0xFF] = SDLK_HELP;
       
  1088 	MISC_keymap[XK_Print&0xFF] = SDLK_PRINT;
       
  1089 	MISC_keymap[XK_Sys_Req&0xFF] = SDLK_SYSREQ;
       
  1090 	MISC_keymap[XK_Break&0xFF] = SDLK_BREAK;
       
  1091 	MISC_keymap[XK_Menu&0xFF] = SDLK_MENU;
       
  1092 	MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
       
  1093 }
       
  1094 
       
  1095 /* Get the translated SDL virtual keysym */
       
  1096 SDLKey X11_TranslateKeycode(Display *display, KeyCode kc)
       
  1097 {
       
  1098 	KeySym xsym;
       
  1099 	SDLKey key;
       
  1100 
       
  1101 	xsym = XKeycodeToKeysym(display, kc, 0);
       
  1102 #ifdef DEBUG_KEYS
       
  1103 	fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
       
  1104 #endif
       
  1105 	key = SDLK_UNKNOWN;
       
  1106 	if ( xsym ) {
       
  1107 		switch (xsym>>8) {
       
  1108 		    case 0x1005FF:
       
  1109 #ifdef SunXK_F36
       
  1110 			if ( xsym == SunXK_F36 )
       
  1111 				key = SDLK_F11;
       
  1112 #endif
       
  1113 #ifdef SunXK_F37
       
  1114 			if ( xsym == SunXK_F37 )
       
  1115 				key = SDLK_F12;
       
  1116 #endif
       
  1117 			break;
       
  1118 		    case 0x00:	/* Latin 1 */
       
  1119 			key = (SDLKey)(xsym & 0xFF);
       
  1120 			break;
       
  1121 		    case 0x01:	/* Latin 2 */
       
  1122 		    case 0x02:	/* Latin 3 */
       
  1123 		    case 0x03:	/* Latin 4 */
       
  1124 		    case 0x04:	/* Katakana */
       
  1125 		    case 0x05:	/* Arabic */
       
  1126 		    case 0x06:	/* Cyrillic */
       
  1127 		    case 0x07:	/* Greek */
       
  1128 		    case 0x08:	/* Technical */
       
  1129 		    case 0x0A:	/* Publishing */
       
  1130 		    case 0x0C:	/* Hebrew */
       
  1131 		    case 0x0D:	/* Thai */
       
  1132 			/* These are wrong, but it's better than nothing */
       
  1133 			key = (SDLKey)(xsym & 0xFF);
       
  1134 			break;
       
  1135 		    case 0xFE:
       
  1136 			key = ODD_keymap[xsym&0xFF];
       
  1137 			break;
       
  1138 		    case 0xFF:
       
  1139 			key = MISC_keymap[xsym&0xFF];
       
  1140 			break;
       
  1141 		    default:
       
  1142 			/*
       
  1143 			fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
       
  1144 					(unsigned int)xsym);
       
  1145 			*/
       
  1146 			break;
       
  1147 		}
       
  1148 	} else {
       
  1149 		/* X11 doesn't know how to translate the key! */
       
  1150 		switch (kc) {
       
  1151 		    /* Caution:
       
  1152 		       These keycodes are from the Microsoft Keyboard
       
  1153 		     */
       
  1154 		    case 115:
       
  1155 			key = SDLK_LSUPER;
       
  1156 			break;
       
  1157 		    case 116:
       
  1158 			key = SDLK_RSUPER;
       
  1159 			break;
       
  1160 		    case 117:
       
  1161 			key = SDLK_MENU;
       
  1162 			break;
       
  1163 		    default:
       
  1164 			/*
       
  1165 			 * no point in an error message; happens for
       
  1166 			 * several keys when we get a keymap notify
       
  1167 			 */
       
  1168 			break;
       
  1169 		}
       
  1170 	}
       
  1171 	return key;
       
  1172 }
       
  1173 
       
  1174 /* X11 modifier masks for various keys */
       
  1175 static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
       
  1176 static unsigned num_mask, mode_switch_mask;
       
  1177 
       
  1178 static void get_modifier_masks(Display *display)
       
  1179 {
       
  1180 	static unsigned got_masks;
       
  1181 	int i, j;
       
  1182 	XModifierKeymap *xmods;
       
  1183 	unsigned n;
       
  1184 
       
  1185 	if(got_masks)
       
  1186 		return;
       
  1187 
       
  1188 	xmods = XGetModifierMapping(display);
       
  1189 	n = xmods->max_keypermod;
       
  1190 	for(i = 3; i < 8; i++) {
       
  1191 		for(j = 0; j < n; j++) {
       
  1192 			KeyCode kc = xmods->modifiermap[i * n + j];
       
  1193 			KeySym ks = XKeycodeToKeysym(display, kc, 0);
       
  1194 			unsigned mask = 1 << i;
       
  1195 			switch(ks) {
       
  1196 			case XK_Num_Lock:
       
  1197 				num_mask = mask; break;
       
  1198 			case XK_Alt_L:
       
  1199 				alt_l_mask = mask; break;
       
  1200 			case XK_Alt_R:
       
  1201 				alt_r_mask = mask; break;
       
  1202 			case XK_Meta_L:
       
  1203 				meta_l_mask = mask; break;
       
  1204 			case XK_Meta_R:
       
  1205 				meta_r_mask = mask; break;
       
  1206 			case XK_Mode_switch:
       
  1207 				mode_switch_mask = mask; break;
       
  1208 			}
       
  1209 		}
       
  1210 	}
       
  1211 	XFreeModifiermap(xmods);
       
  1212 	got_masks = 1;
       
  1213 }
       
  1214 
       
  1215 
       
  1216 /*
       
  1217  * This function is semi-official; it is not officially exported and should
       
  1218  * not be considered part of the SDL API, but may be used by client code
       
  1219  * that *really* needs it (including legacy code).
       
  1220  * It is slow, though, and should be avoided if possible.
       
  1221  *
       
  1222  * Note that it isn't completely accurate either; in particular, multi-key
       
  1223  * sequences (dead accents, compose key sequences) will not work since the
       
  1224  * state has been irrevocably lost.
       
  1225  */
       
  1226 Uint16 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers)
       
  1227 {
       
  1228 	struct SDL_VideoDevice *this = current_video;
       
  1229 	char keybuf[32];
       
  1230 	int i;
       
  1231 	KeySym xsym = 0;
       
  1232 	XKeyEvent xkey;
       
  1233 	Uint16 unicode;
       
  1234 
       
  1235 	if ( !this || !SDL_Display ) {
       
  1236 		return 0;
       
  1237 	}
       
  1238 
       
  1239 	SDL_memset(&xkey, 0, sizeof(xkey));
       
  1240 	xkey.display = SDL_Display;
       
  1241 
       
  1242 	xsym = keysym;		/* last resort if not found */
       
  1243 	for (i = 0; i < 256; ++i) {
       
  1244 		if ( MISC_keymap[i] == keysym ) {
       
  1245 			xsym = 0xFF00 | i;
       
  1246 			break;
       
  1247 		} else if ( ODD_keymap[i] == keysym ) {
       
  1248 			xsym = 0xFE00 | i;
       
  1249 			break;
       
  1250 		}
       
  1251 	}
       
  1252 
       
  1253 	xkey.keycode = XKeysymToKeycode(xkey.display, xsym);
       
  1254 
       
  1255 	get_modifier_masks(SDL_Display);
       
  1256 	if(modifiers & KMOD_SHIFT)
       
  1257 		xkey.state |= ShiftMask;
       
  1258 	if(modifiers & KMOD_CAPS)
       
  1259 		xkey.state |= LockMask;
       
  1260 	if(modifiers & KMOD_CTRL)
       
  1261 		xkey.state |= ControlMask;
       
  1262 	if(modifiers & KMOD_MODE)
       
  1263 		xkey.state |= mode_switch_mask;
       
  1264 	if(modifiers & KMOD_LALT)
       
  1265 		xkey.state |= alt_l_mask;
       
  1266 	if(modifiers & KMOD_RALT)
       
  1267 		xkey.state |= alt_r_mask;
       
  1268 	if(modifiers & KMOD_LMETA)
       
  1269 		xkey.state |= meta_l_mask;
       
  1270 	if(modifiers & KMOD_RMETA)
       
  1271 		xkey.state |= meta_r_mask;
       
  1272 	if(modifiers & KMOD_NUM)
       
  1273 		xkey.state |= num_mask;
       
  1274 
       
  1275 	unicode = 0;
       
  1276 	if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) )
       
  1277 		unicode = (unsigned char)keybuf[0];
       
  1278 	return(unicode);
       
  1279 }
       
  1280 
       
  1281 
       
  1282 /*
       
  1283  * Called when focus is regained, to read the keyboard state and generate
       
  1284  * synthetic keypress/release events.
       
  1285  * key_vec is a bit vector of keycodes (256 bits)
       
  1286  */
       
  1287 void X11_SetKeyboardState(Display *display, const char *key_vec)
       
  1288 {
       
  1289 	char keys_return[32];
       
  1290 	int i;
       
  1291 	Uint8 *kstate = SDL_GetKeyState(NULL);
       
  1292 	SDLMod modstate;
       
  1293 	Window junk_window;
       
  1294 	int x, y;
       
  1295 	unsigned int mask;
       
  1296 
       
  1297 	/* The first time the window is mapped, we initialize key state */
       
  1298 	if ( ! key_vec ) {
       
  1299 		XQueryKeymap(display, keys_return);
       
  1300 		key_vec = keys_return;
       
  1301 	}
       
  1302 
       
  1303 	/* Get the keyboard modifier state */
       
  1304 	modstate = 0;
       
  1305 	get_modifier_masks(display);
       
  1306 	if ( XQueryPointer(display, DefaultRootWindow(display),
       
  1307 		&junk_window, &junk_window, &x, &y, &x, &y, &mask) ) {
       
  1308 		if ( mask & LockMask ) {
       
  1309 			modstate |= KMOD_CAPS;
       
  1310 		}
       
  1311 		if ( mask & mode_switch_mask ) {
       
  1312 			modstate |= KMOD_MODE;
       
  1313 		}
       
  1314 		if ( mask & num_mask ) {
       
  1315 			modstate |= KMOD_NUM;
       
  1316 		}
       
  1317 	}
       
  1318 
       
  1319 	/* Zero the new keyboard state and generate it */
       
  1320 	SDL_memset(kstate, 0, SDLK_LAST);
       
  1321 	/*
       
  1322 	 * An obvious optimisation is to check entire longwords at a time in
       
  1323 	 * both loops, but we can't be sure the arrays are aligned so it's not
       
  1324 	 * worth the extra complexity
       
  1325 	 */
       
  1326 	for ( i = 0; i < 32; i++ ) {
       
  1327 		int j;
       
  1328 		if ( !key_vec[i] )
       
  1329 			continue;
       
  1330 		for ( j = 0; j < 8; j++ ) {
       
  1331 			if ( key_vec[i] & (1 << j) ) {
       
  1332 				SDLKey key;
       
  1333 				KeyCode kc = (i << 3 | j);
       
  1334 				key = X11_TranslateKeycode(display, kc);
       
  1335 				if ( key == SDLK_UNKNOWN ) {
       
  1336 					continue;
       
  1337 				}
       
  1338 				kstate[key] = SDL_PRESSED;
       
  1339 				switch (key) {
       
  1340 				    case SDLK_LSHIFT:
       
  1341 					modstate |= KMOD_LSHIFT;
       
  1342 					break;
       
  1343 				    case SDLK_RSHIFT:
       
  1344 					modstate |= KMOD_RSHIFT;
       
  1345 					break;
       
  1346 				    case SDLK_LCTRL:
       
  1347 					modstate |= KMOD_LCTRL;
       
  1348 					break;
       
  1349 				    case SDLK_RCTRL:
       
  1350 					modstate |= KMOD_RCTRL;
       
  1351 					break;
       
  1352 				    case SDLK_LALT:
       
  1353 					modstate |= KMOD_LALT;
       
  1354 					break;
       
  1355 				    case SDLK_RALT:
       
  1356 					modstate |= KMOD_RALT;
       
  1357 					break;
       
  1358 				    case SDLK_LMETA:
       
  1359 					modstate |= KMOD_LMETA;
       
  1360 					break;
       
  1361 				    case SDLK_RMETA:
       
  1362 					modstate |= KMOD_RMETA;
       
  1363 					break;
       
  1364 				    default:
       
  1365 					break;
       
  1366 				}
       
  1367 			}
       
  1368 		}
       
  1369 	}
       
  1370 
       
  1371 	/* Hack - set toggle key state */
       
  1372 	if ( modstate & KMOD_CAPS ) {
       
  1373 		kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
       
  1374 	} else {
       
  1375 		kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
       
  1376 	}
       
  1377 	if ( modstate & KMOD_NUM ) {
       
  1378 		kstate[SDLK_NUMLOCK] = SDL_PRESSED;
       
  1379 	} else {
       
  1380 		kstate[SDLK_NUMLOCK] = SDL_RELEASED;
       
  1381 	}
       
  1382 
       
  1383 	/* Set the final modifier state */
       
  1384 	SDL_SetModState(modstate);
       
  1385 }
       
  1386 
       
  1387 void X11_InitOSKeymap(_THIS)
       
  1388 {
       
  1389 	X11_InitKeymap();
       
  1390 }
       
  1391 
       
  1392 void X11_SaveScreenSaver(Display *display, int *saved_timeout, BOOL *dpms)
       
  1393 {
       
  1394 	int timeout, interval, prefer_blank, allow_exp;
       
  1395 	XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
       
  1396 	*saved_timeout = timeout;
       
  1397 
       
  1398 #if SDL_VIDEO_DRIVER_X11_DPMS
       
  1399 	if ( SDL_X11_HAVE_DPMS ) {
       
  1400 		int dummy;
       
  1401 	  	if ( DPMSQueryExtension(display, &dummy, &dummy) ) {
       
  1402 			CARD16 state;
       
  1403 			DPMSInfo(display, &state, dpms);
       
  1404 		}
       
  1405 	}
       
  1406 #else
       
  1407 	*dpms = 0;
       
  1408 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
       
  1409 }
       
  1410 
       
  1411 void X11_DisableScreenSaver(_THIS, Display *display)
       
  1412 {
       
  1413 	int timeout, interval, prefer_blank, allow_exp;
       
  1414 
       
  1415 	if (this->hidden->allow_screensaver) {
       
  1416 		return;
       
  1417 	}
       
  1418 
       
  1419 	XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
       
  1420 	timeout = 0;
       
  1421 	XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
       
  1422 
       
  1423 #if SDL_VIDEO_DRIVER_X11_DPMS
       
  1424 	if ( SDL_X11_HAVE_DPMS ) {
       
  1425 		int dummy;
       
  1426 	  	if ( DPMSQueryExtension(display, &dummy, &dummy) ) {
       
  1427 			DPMSDisable(display);
       
  1428 		}
       
  1429 	}
       
  1430 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
       
  1431 }
       
  1432 
       
  1433 void X11_RestoreScreenSaver(_THIS, Display *display, int saved_timeout, BOOL dpms)
       
  1434 {
       
  1435 	int timeout, interval, prefer_blank, allow_exp;
       
  1436 
       
  1437 	if (this->hidden->allow_screensaver) {
       
  1438 		return;
       
  1439 	}
       
  1440 
       
  1441 	XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
       
  1442 	timeout = saved_timeout;
       
  1443 	XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
       
  1444 
       
  1445 #if SDL_VIDEO_DRIVER_X11_DPMS
       
  1446 	if ( SDL_X11_HAVE_DPMS ) {
       
  1447 		int dummy;
       
  1448 	  	if ( DPMSQueryExtension(display, &dummy, &dummy) ) {
       
  1449 			if ( dpms ) {
       
  1450 				DPMSEnable(display);
       
  1451 			}
       
  1452 		}
       
  1453 	}
       
  1454 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
       
  1455 }