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