src/video/x11/SDL_x11dyn.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 25 Jun 2007 19:58:32 +0000
branchSDL-1.2
changeset 3978 b966761fef6c
parent 3958 85b6fb6a5e3c
child 4159 a1b03ba2fcd0
permissions -rw-r--r--
Significantly improved XIM support.

Fixes Bugzilla #429.


Selected notes from the patch's README:

= FIXES =

This patch fixes the above issues as follows.

== X11 events ==

Moved XFilterEvent just after XNextEvent so that all events are passed
to it. Also, XFilterEvent will receive masks indicated by IM through
XNFilterEvents IC value as well as masks surpplied by SDL.

X11_KeyRepeat is called between XNextEvent and XFilterEvent, after
testing an event is a KeyRelease. I'm not 100% comfortable to do so,
but I couldn't find a better timing to call it, and use of the
function is inevitable.

== Xutf8LookupString ==

Used a longer buffer to receive UTF-8 string. If it is insufficient,
a dynamic storage of the requested size will be allocated. The
initial size of the buffer is set to 32, because the Japanese text
converted from the most widely used benchmark key sequence for
Japanese IM, "WATASHINONAMAEHANAKANODESU." has ten Japanese characters
in it, that occupies 30 bytes when encoded in UTF-8.

== SDL_keysym.unicode ==

On Windows version of SDL implementation, SDL_keysym.unicode stores
UTF-16 encoded unicode characters, one UTF-16 encoding unit per an SDL
event. A Unicode supplementary characters are sent to an application
as two events. (One with a high surrogate and another with a low
surrogate.) The behavior seems reasonable since it is upward
compatible with existing handling of BMP characters.

I wrote a UTF-8 to UTF-16 conversion function for the purpose. It is
designed with the execution speed in mind, having a minimum set of
features that my patch requires.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2004 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 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     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #define DEBUG_DYNAMIC_X11 0
    25 
    26 #include "SDL_x11dyn.h"
    27 
    28 #if DEBUG_DYNAMIC_X11
    29 #include <stdio.h>
    30 #endif
    31 
    32 #ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
    33 
    34 #include "SDL_name.h"
    35 #include "SDL_loadso.h"
    36 
    37 typedef struct
    38 {
    39     void *lib;
    40     const char *libname;
    41 } x11dynlib;
    42 
    43 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC
    44 #define SDL_VIDEO_DRIVER_X11_DYNAMIC NULL
    45 #endif
    46 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
    47 #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT NULL
    48 #endif
    49 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER
    50 #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER NULL
    51 #endif
    52 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
    53 #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR NULL
    54 #endif
    55 
    56 static x11dynlib x11libs[] =
    57 {
    58     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC },
    59     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT },
    60     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER },
    61     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR },
    62 };
    63 
    64 static void X11_GetSym(const char *fnname, int *rc, void **fn)
    65 {
    66 	int i;
    67 	for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
    68 		if (x11libs[i].lib != NULL)
    69 		{
    70 			*fn = SDL_LoadFunction(x11libs[i].lib, fnname);
    71 			if (*fn != NULL)
    72 				break;
    73 		}
    74 	}
    75 
    76 	#if DEBUG_DYNAMIC_X11
    77 	if (*fn != NULL)
    78 		printf("X11: Found '%s' in %s (%p)\n", fnname, x11libs[i].libname, *fn);
    79 	else
    80 		printf("X11: Symbol '%s' NOT FOUND!\n", fnname);
    81 	#endif
    82 
    83 	if (*fn == NULL)
    84 		*rc = 0;  /* kill this module. */
    85 }
    86 
    87 
    88 /* Define all the function pointers and wrappers... */
    89 #define SDL_X11_MODULE(modname)
    90 #define SDL_X11_SYM(rc,fn,params,args,ret) \
    91 	static rc (*p##fn) params = NULL; \
    92 	rc fn params { ret p##fn args ; }
    93 #include "SDL_x11sym.h"
    94 #undef SDL_X11_MODULE
    95 #undef SDL_X11_SYM
    96 #endif  /* SDL_VIDEO_DRIVER_X11_DYNAMIC */
    97 
    98 /* Annoying varargs entry point... */
    99 #ifdef X_HAVE_UTF8_STRING
   100 XIC (*pXCreateIC)(XIM,...) = NULL;
   101 char *(*pXGetICValues)(XIC, ...) = NULL;
   102 #endif
   103 
   104 /* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
   105 #define SDL_X11_MODULE(modname) int SDL_X11_HAVE_##modname = 1;
   106 #define SDL_X11_SYM(rc,fn,params,args,ret)
   107 #include "SDL_x11sym.h"
   108 #undef SDL_X11_MODULE
   109 #undef SDL_X11_SYM
   110 
   111 
   112 static int x11_load_refcount = 0;
   113 
   114 void SDL_X11_UnloadSymbols(void)
   115 {
   116 	#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
   117 	/* Don't actually unload if more than one module is using the libs... */
   118 	if (x11_load_refcount > 0) {
   119 		if (--x11_load_refcount == 0) {
   120 			int i;
   121 
   122 			/* set all the function pointers to NULL. */
   123 			#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1;
   124 			#define SDL_X11_SYM(rc,fn,params,args,ret) p##fn = NULL;
   125 			#include "SDL_x11sym.h"
   126 			#undef SDL_X11_MODULE
   127 			#undef SDL_X11_SYM
   128 
   129 			#ifdef X_HAVE_UTF8_STRING
   130 			pXCreateIC = NULL;
   131 			pXGetICValues = NULL;
   132 			#endif
   133 
   134 			for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
   135 				if (x11libs[i].lib != NULL) {
   136 					SDL_UnloadObject(x11libs[i].lib);
   137 					x11libs[i].lib = NULL;
   138 				}
   139 			}
   140 		}
   141 	}
   142 	#endif
   143 }
   144 
   145 /* returns non-zero if all needed symbols were loaded. */
   146 int SDL_X11_LoadSymbols(void)
   147 {
   148 	int rc = 1;  /* always succeed if not using Dynamic X11 stuff. */
   149 
   150 	#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
   151 	/* deal with multiple modules (dga, x11, etc) needing these symbols... */
   152 	if (x11_load_refcount++ == 0) {
   153 		int i;
   154 		int *thismod = NULL;
   155 		for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
   156 			if (x11libs[i].libname != NULL) {
   157 				x11libs[i].lib = SDL_LoadObject(x11libs[i].libname);
   158 			}
   159 		}
   160 		#define SDL_X11_MODULE(modname) thismod = &SDL_X11_HAVE_##modname;
   161 		#define SDL_X11_SYM(a,fn,x,y,z) X11_GetSym(#fn,thismod,(void**)&p##fn);
   162 		#include "SDL_x11sym.h"
   163 		#undef SDL_X11_MODULE
   164 		#undef SDL_X11_SYM
   165 
   166 		#ifdef X_HAVE_UTF8_STRING
   167 		X11_GetSym("XCreateIC",&SDL_X11_HAVE_UTF8,(void **)&pXCreateIC);
   168 		X11_GetSym("XGetICValues",&SDL_X11_HAVE_UTF8,(void **)&pXGetICValues);
   169 		#endif
   170 
   171 		if (SDL_X11_HAVE_BASEXLIB) {  /* all required symbols loaded. */
   172 			SDL_ClearError();
   173 		} else {
   174 			SDL_X11_UnloadSymbols();  /* in case something got loaded... */
   175 			rc = 0;
   176 		}
   177 	}
   178 	#else
   179 		#if DEBUG_DYNAMIC_X11
   180 		printf("X11: No dynamic X11 support in this build of SDL.\n");
   181 		#endif
   182 		#ifdef X_HAVE_UTF8_STRING
   183 		pXCreateIC = XCreateIC;
   184 		pXGetICValues = XGetICValues;
   185 		#endif
   186 	#endif
   187 
   188 	return rc;
   189 }
   190 
   191 /* end of SDL_x11dyn.c ... */
   192