mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-10-14 02:17:36 +08:00
support system IME for Windows SDL1 builds
This commit is contained in:
@@ -347,6 +347,13 @@ extern DECLSPEC SDL_EventFilter SDLCALL SDL_GetEventFilter(void);
|
||||
*/
|
||||
extern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint8 type, int state);
|
||||
|
||||
extern DECLSPEC int SDL_SetIMPosition( int x, int y );
|
||||
extern DECLSPEC char *SDL_SetIMValues(SDL_imvalue value, ...);
|
||||
extern DECLSPEC char *SDL_GetIMValues(SDL_imvalue value, ...);
|
||||
extern DECLSPEC int SDL_FlushIMString(void *buffer);
|
||||
|
||||
extern DECLSPEC void SDL_SetCompositionFontName(const char *name);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -105,6 +105,7 @@
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#undef __WIN32__
|
||||
#define __WIN32__ 1
|
||||
#define ENABLE_IM_EVENT 1
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_platform_h */
|
||||
|
@@ -115,6 +115,13 @@ typedef struct {
|
||||
} Uint64, Sint64;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SDL_IM_ENABLE = 1,
|
||||
SDL_IM_FLIP,
|
||||
SDL_IM_ONOFF,
|
||||
SDL_IM_FONT_SIZE
|
||||
} SDL_imvalue;
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name Make sure the types really have the right sizes */
|
||||
|
@@ -46,6 +46,9 @@ extern "C" {
|
||||
#ifdef SDL_PROTOTYPES_ONLY
|
||||
struct SDL_SysWMinfo;
|
||||
typedef struct SDL_SysWMinfo SDL_SysWMinfo;
|
||||
|
||||
struct SDL_SysIMinfo;
|
||||
typedef struct SDL_SysIMinfo SDL_SysIMinfo;
|
||||
#else
|
||||
|
||||
/* This is the structure for custom window manager events */
|
||||
@@ -84,6 +87,8 @@ struct SDL_SysWMmsg {
|
||||
typedef struct SDL_SysWMinfo {
|
||||
SDL_version version;
|
||||
SDL_SYSWM_TYPE subsystem;
|
||||
HWND ime; /* The Win32 input method window */
|
||||
HIMC imc; /* The Win32 input method context */
|
||||
union {
|
||||
struct {
|
||||
Display *display; /**< The X11 display */
|
||||
@@ -113,6 +118,13 @@ typedef struct SDL_SysWMinfo {
|
||||
} info;
|
||||
} SDL_SysWMinfo;
|
||||
|
||||
/* The UNIX custom input method information structure */
|
||||
typedef struct SDL_SysIMinfo {
|
||||
SDL_version version;
|
||||
XIM xim; /* The X11 input mathod */
|
||||
XIC *xic; /* The X11 input mathod context */
|
||||
} SDL_SysIMinfo;
|
||||
|
||||
#elif defined(SDL_VIDEO_DRIVER_NANOX)
|
||||
#include <microwin/nano-X.h>
|
||||
|
||||
@@ -149,6 +161,19 @@ typedef struct SDL_SysWMinfo {
|
||||
HGLRC hglrc; /**< The OpenGL context, if any */
|
||||
} SDL_SysWMinfo;
|
||||
|
||||
/* The windows custom input method information structure */
|
||||
typedef struct SDL_SysIMinfo {
|
||||
SDL_version version;
|
||||
HWND ime; /* The Win32 input method window */
|
||||
HIMC imc; /* The Win32 input method context */
|
||||
union {
|
||||
struct {
|
||||
void **notify_data;
|
||||
void (**notify_func)(void*);
|
||||
} win;
|
||||
} info;
|
||||
} SDL_SysIMinfo;
|
||||
|
||||
#elif defined(SDL_VIDEO_DRIVER_RISCOS)
|
||||
|
||||
/** RISC OS custom event structure */
|
||||
@@ -217,6 +242,10 @@ typedef struct SDL_SysWMinfo {
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetWMInfo(SDL_SysWMinfo *info);
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
/* This function gives you custom hooks into the input method information. */
|
||||
extern DECLSPEC int SDLCALL SDL_GetIMInfo(SDL_SysIMinfo *info);
|
||||
#endif
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
|
@@ -32,6 +32,10 @@
|
||||
#include "../joystick/SDL_joystick_c.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
/* Public data -- the event filter */
|
||||
SDL_EventFilter SDL_EventOK = NULL;
|
||||
Uint8 SDL_ProcessEvents[SDL_NUMEVENTS];
|
||||
@@ -500,3 +504,107 @@ int SDL_PrivateSysWMEvent(SDL_SysWMmsg *message)
|
||||
/* Update internal event state */
|
||||
return(posted);
|
||||
}
|
||||
|
||||
int SDL_SetIMPosition( int x, int y )
|
||||
{
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
SDL_VideoDevice *video = current_video;
|
||||
SDL_VideoDevice *this = current_video;
|
||||
|
||||
if ( video ) {
|
||||
return video->SetIMPosition(this, x, y);
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
char *SDL_SetIMValues(SDL_imvalue value, ...)
|
||||
{
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
va_list ap;
|
||||
SDL_imvalue t1;
|
||||
static char *ret = 0;
|
||||
int t2;
|
||||
SDL_VideoDevice *video = current_video;
|
||||
SDL_VideoDevice *this = current_video;
|
||||
if (video && value) {
|
||||
va_start(ap, value);
|
||||
t2 = va_arg(ap, int);
|
||||
ret = video->SetIMValues(this, value, t2);
|
||||
if (ret)
|
||||
return ret;
|
||||
while ((t1 = va_arg(ap, SDL_imvalue)) != 0) {
|
||||
t2 = va_arg(ap, int);
|
||||
ret = video->SetIMValues(this, t1, t2);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_SetError("video or argument is NULL");
|
||||
return "video or argument is NULL";
|
||||
}
|
||||
va_end(ap);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_GetIMValues(SDL_imvalue value, ...)
|
||||
{
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
va_list ap;
|
||||
SDL_imvalue t1;
|
||||
static char *ret = 0;
|
||||
static int *t2;
|
||||
SDL_VideoDevice *video = current_video;
|
||||
SDL_VideoDevice *this = current_video;
|
||||
|
||||
if (video && value) {
|
||||
va_start(ap, value);
|
||||
t2 = va_arg(ap, int*);
|
||||
ret = video->GetIMValues(this, value, t2);
|
||||
if (ret)
|
||||
return ret;
|
||||
while ((t1 = va_arg(ap, SDL_imvalue)) != 0) {
|
||||
t2 = va_arg(ap, int*);
|
||||
ret = video->GetIMValues(this, t1, t2);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_SetError("video or argument is NULL");
|
||||
return "video or argument is NULL";
|
||||
}
|
||||
va_end(ap);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SDL_FlushIMString(void *buffer)
|
||||
{
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
SDL_VideoDevice *video = current_video;
|
||||
SDL_VideoDevice *this = current_video;
|
||||
|
||||
if ( video ) {
|
||||
return video->FlushIMString(this, buffer);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
wchar_t CompositionFontName[LF_FACESIZE];
|
||||
#endif
|
||||
|
||||
void SDL_SetCompositionFontName(const char *name)
|
||||
{
|
||||
#ifdef WIN32
|
||||
int len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
|
||||
if(len < LF_FACESIZE) {
|
||||
MultiByteToWideChar(CP_ACP, 0, name, -1, CompositionFontName, len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@@ -258,6 +258,26 @@ struct SDL_VideoDevice {
|
||||
/* Handle any queued OS events */
|
||||
void (*PumpEvents)(_THIS);
|
||||
|
||||
/* * * */
|
||||
/* IM manager function */
|
||||
|
||||
/* set im position to (x,y) */
|
||||
int (*SetIMPosition)(_THIS, int x, int y);
|
||||
|
||||
/* set im value */
|
||||
char *(*SetIMValues)(_THIS, SDL_imvalue value, int alt);
|
||||
|
||||
/* get im value */
|
||||
char *(*GetIMValues)(_THIS, SDL_imvalue value, int *alt);
|
||||
|
||||
/* get im string */
|
||||
int (*FlushIMString)(_THIS, void *buffer);
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
/* get im handle information */
|
||||
int (*GetIMInfo)(_THIS, SDL_SysIMinfo *info);
|
||||
#endif
|
||||
|
||||
/* * * */
|
||||
/* Data common to all drivers */
|
||||
SDL_Surface *screen;
|
||||
|
@@ -88,6 +88,26 @@ extern HINSTANCE SDL_Instance;
|
||||
extern HWND SDL_Window;
|
||||
extern BOOL SDL_windowid;
|
||||
|
||||
typedef struct {
|
||||
HIMC SDL_IMC;
|
||||
union {
|
||||
char *im_multi_byte_buffer;
|
||||
wchar_t *im_wide_char_buffer;
|
||||
}string;
|
||||
int im_buffer_sz;
|
||||
int im_compose_sz;
|
||||
|
||||
Uint32 video_flags;
|
||||
int bFlip;
|
||||
int bEnable;
|
||||
int bCompos;
|
||||
|
||||
void *notify_data;
|
||||
void (*notify_func)(void*);
|
||||
} _IM_Context;
|
||||
|
||||
extern _IM_Context IM_Context;
|
||||
|
||||
/* Variables and functions exported to other parts of the native video
|
||||
subsystem (SDL_sysevents.c)
|
||||
*/
|
||||
|
@@ -96,6 +96,7 @@ DEVMODE SDL_fullscreen_mode;
|
||||
#endif
|
||||
WORD *gamma_saved = NULL;
|
||||
|
||||
_IM_Context IM_Context; /* patched */
|
||||
|
||||
/* Functions called by the message processing function */
|
||||
LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)=NULL;
|
||||
|
@@ -304,3 +304,30 @@ int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info)
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int WIN_GetIMInfo(_THIS, SDL_SysIMinfo *info)
|
||||
{
|
||||
if ( info->version.major <= SDL_MAJOR_VERSION ) {
|
||||
if ( SDL_VERSIONNUM(info->version.major,
|
||||
info->version.minor,
|
||||
info->version.patch) >=
|
||||
SDL_VERSIONNUM(1, 2, 8) ) {
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
info->ime = ImmGetDefaultIMEWnd(SDL_Window);
|
||||
info->imc = IM_Context.SDL_IMC;
|
||||
info->info.win.notify_data = &IM_Context.notify_data;
|
||||
info->info.win.notify_func = &IM_Context.notify_func;
|
||||
#else
|
||||
info->ime = NULL;
|
||||
info->imc = NULL;
|
||||
info->info.win.notify_data = NULL;
|
||||
info->info.win.notify_func = NULL;
|
||||
#endif
|
||||
}
|
||||
return(1);
|
||||
} else {
|
||||
SDL_SetError("Application not compiled with SDL %d.%d\n",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
@@ -33,3 +33,5 @@ extern int WIN_IconifyWindow(_THIS);
|
||||
extern SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode);
|
||||
extern int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info);
|
||||
|
||||
/* Functions to IM */
|
||||
extern int WIN_GetIMInfo(_THIS, SDL_SysIMinfo *info);
|
||||
|
@@ -91,6 +91,14 @@ static SDLKey Arrows_keymap[4];
|
||||
#endif
|
||||
static WNDPROCTYPE userWindowProc = NULL;
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
#include <imm.h>
|
||||
int DIB_HandleComposition(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
/* data field required by DIB_HandleComposition */
|
||||
static COMPOSITIONFORM form;
|
||||
extern wchar_t CompositionFontName[LF_FACESIZE];
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_GAPI
|
||||
|
||||
@@ -176,6 +184,17 @@ int Win32_ShouldPassMessageToSysWMEvent(UINT msg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
#define FLIP_BREAK \
|
||||
if (IM_Context.bFlip) { \
|
||||
break; \
|
||||
} else { \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
SDL_Event event_keydown;
|
||||
#endif
|
||||
|
||||
/* The main Win32 event handler */
|
||||
LRESULT DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@@ -385,6 +404,60 @@ LRESULT DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar
|
||||
/* Fall through to default processing */
|
||||
#endif /* SC_SCREENSAVE && SC_MONITORPOWER */
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
case WM_INPUTLANGCHANGE:
|
||||
SendMessage(hwnd, WM_IME_NOTIFY, wParam, lParam);
|
||||
FLIP_BREAK;
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
//if (!IM_Context.SDL_IMC)
|
||||
// IM_Context.SDL_IMC = ImmGetContext(hwnd);
|
||||
{
|
||||
HIMC imc = ImmGetContext(hwnd);
|
||||
IM_Context.bCompos = 1;
|
||||
form.dwStyle = CFS_POINT;
|
||||
ImmSetCompositionWindow(imc, &form);
|
||||
ImmReleaseContext(hwnd, imc);
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
//FLIP_BREAK;
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
IM_Context.bCompos = 0;
|
||||
FLIP_BREAK;
|
||||
case WM_IME_NOTIFY:
|
||||
if (IM_Context.notify_func)/* && IM_Context.bEnable && ImmIsIME(GetKeyboardLayout(0)))*/
|
||||
IM_Context.notify_func(IM_Context.notify_data);
|
||||
|
||||
// To flip state window in fullscreen mode
|
||||
if (IM_Context.bFlip && IM_Context.bEnable) {
|
||||
DefWindowProc(hwnd, WM_IME_NOTIFY, IMN_OPENSTATUSWINDOW, lParam);
|
||||
}
|
||||
FLIP_BREAK;
|
||||
case WM_IME_SETCONTEXT:
|
||||
// To show the composition window in fullscreen mode
|
||||
if (IM_Context.bFlip && IM_Context.bEnable)
|
||||
{
|
||||
lParam |= ISC_SHOWUICOMPOSITIONWINDOW;
|
||||
return DefWindowProc(hwnd, WM_IME_SETCONTEXT, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
|
||||
//if (IM_Context.bFlip)
|
||||
return DefWindowProc(hwnd, WM_IME_SETCONTEXT, wParam, lParam);
|
||||
}
|
||||
FLIP_BREAK;
|
||||
case WM_IME_COMPOSITION:
|
||||
DIB_HandleComposition(hwnd, msg, wParam, lParam);
|
||||
|
||||
if (lParam & GCS_RESULTSTR) {
|
||||
/* Send KEYDOWN event to fix some IME that doesn't sent key down event
|
||||
after composition. */
|
||||
event_keydown.type = SDL_KEYDOWN;
|
||||
SDL_PushEvent(&event_keydown);
|
||||
FLIP_BREAK;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: {
|
||||
/* Only post the event if we're watching for it */
|
||||
if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
|
||||
@@ -1159,3 +1232,248 @@ void DIB_DestroyWindow(_THIS)
|
||||
*/
|
||||
WIN_FlushMessageQueue();
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
|
||||
int DIB_HandleComposition(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (lParam & GCS_RESULTSTR) {
|
||||
HIMC imc = ImmGetContext(hWnd);
|
||||
|
||||
if (!imc) {
|
||||
IM_Context.im_compose_sz = 0;
|
||||
SDL_SetError("ERROR_NULLCONTEXT");
|
||||
}
|
||||
|
||||
/* Get the size of the result string. */
|
||||
if (SDL_TranslateUNICODE) {
|
||||
IM_Context.im_compose_sz = ImmGetCompositionStringW(imc, GCS_RESULTSTR, NULL, 0);
|
||||
} else {
|
||||
IM_Context.im_compose_sz = ImmGetCompositionStringA(imc, GCS_RESULTSTR, NULL, 0);
|
||||
}
|
||||
if (!IM_Context.im_compose_sz) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (IM_Context.im_compose_sz >= IM_Context.im_buffer_sz) {
|
||||
IM_Context.im_buffer_sz = IM_Context.im_compose_sz + 1*sizeof(wchar_t);
|
||||
IM_Context.string.im_multi_byte_buffer =
|
||||
(char*)realloc(IM_Context.string.im_multi_byte_buffer,
|
||||
IM_Context.im_buffer_sz);
|
||||
}
|
||||
IM_Context.string.im_wide_char_buffer[0] = '\0';
|
||||
}
|
||||
|
||||
if (IM_Context.string.im_multi_byte_buffer) {
|
||||
/* Get the result strings that is generated by IME into lpstr. */
|
||||
if (SDL_TranslateUNICODE) {
|
||||
ImmGetCompositionStringW(imc, GCS_RESULTSTR,
|
||||
IM_Context.string.im_wide_char_buffer, IM_Context.im_buffer_sz);
|
||||
IM_Context.string.im_wide_char_buffer[IM_Context.im_compose_sz/2] = '\0';
|
||||
}
|
||||
else {
|
||||
ImmGetCompositionStringA(imc, GCS_RESULTSTR,
|
||||
IM_Context.string.im_multi_byte_buffer, IM_Context.im_buffer_sz);
|
||||
IM_Context.string.im_multi_byte_buffer[IM_Context.im_compose_sz] = '\0';
|
||||
}
|
||||
ImmReleaseContext(hWnd, imc);
|
||||
}
|
||||
else {
|
||||
IM_Context.im_compose_sz = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (lParam & GCS_COMPSTR) {
|
||||
HIMC imc = ImmGetContext(hWnd);
|
||||
if (!ImmSetCompositionWindow(imc, &form)) {
|
||||
SDL_SetError("ImmSetCompositionWindow: fail to set composition form.\n");
|
||||
}
|
||||
ImmReleaseContext(hWnd, imc);
|
||||
}
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DIB_SetIMPosition(_THIS, int x, int y)
|
||||
{
|
||||
form.dwStyle = CFS_POINT;;
|
||||
form.ptCurrentPos.x = x;
|
||||
form.ptCurrentPos.y = y;
|
||||
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
// if (!IM_Context.SDL_IMC)
|
||||
// IM_Context.SDL_IMC = ImmGetContext(SDL_Window);
|
||||
|
||||
// if (!IM_Context.SDL_IMC)
|
||||
// return 0;
|
||||
|
||||
// if (ImmSetCompositionWindow(IM_Context.SDL_IMC, &form)) {
|
||||
if (ImmSetCompositionWindow(imc, &form)) {
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
return 1;
|
||||
}
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *DIB_SetIMValues(_THIS, SDL_imvalue value, int alt)
|
||||
{
|
||||
switch (value) {
|
||||
case SDL_IM_ENABLE:
|
||||
if (alt) {
|
||||
if(!IM_Context.bEnable) {
|
||||
ImmAssociateContext(SDL_Window, IM_Context.SDL_IMC);
|
||||
IM_Context.bEnable = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if(IM_Context.bEnable) {
|
||||
IM_Context.SDL_IMC = ImmAssociateContext(SDL_Window, 0);
|
||||
IM_Context.bEnable = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_FLIP:
|
||||
if (alt) {
|
||||
IM_Context.bFlip = 1;
|
||||
SendMessage(SDL_Window, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
IM_Context.bFlip = 0;
|
||||
SendMessage(SDL_Window, WM_IME_SETCONTEXT, TRUE, 0);
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_ONOFF:
|
||||
{
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
ImmSetOpenStatus(imc, alt ? TRUE : FALSE);
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
}
|
||||
return NULL;
|
||||
case SDL_IM_FONT_SIZE:
|
||||
{
|
||||
LOGFONTW lf;
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
HDC hc = GetDC(SDL_Window);
|
||||
HFONT hf = (HFONT)GetCurrentObject(hc, OBJ_FONT);
|
||||
GetObjectW(hf, sizeof(lf), &lf);
|
||||
ReleaseDC(SDL_Window, hc);
|
||||
if(CompositionFontName[0]) {
|
||||
wcscpy(lf.lfFaceName, CompositionFontName);
|
||||
}
|
||||
lf.lfHeight = -alt;
|
||||
lf.lfWidth = alt / 2;
|
||||
ImmSetCompositionFontW(imc, &lf);
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
}
|
||||
return NULL;
|
||||
default:
|
||||
SDL_SetError("SDL_SetIMValues: unknow enum type: %d", value);
|
||||
return "SDL_SetIMValues: unknow enum type";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *DIB_GetIMValues(_THIS, SDL_imvalue value, int *alt)
|
||||
{
|
||||
switch (value) {
|
||||
case SDL_IM_ENABLE:
|
||||
if (IM_Context.bEnable) {
|
||||
*alt = 1;
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
*alt = 0;
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_FLIP:
|
||||
if (IM_Context.bFlip) {
|
||||
*alt = 1;
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
*alt = 0;
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_ONOFF:
|
||||
{
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
if(ImmGetOpenStatus(imc)) {
|
||||
*alt = 1;
|
||||
} else {
|
||||
*alt = 0;
|
||||
}
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_FONT_SIZE:
|
||||
{
|
||||
LOGFONTW lf;
|
||||
HDC hc = GetDC(SDL_Window);
|
||||
HFONT hf = (HFONT)GetCurrentObject(hc, OBJ_FONT);
|
||||
GetObjectW(hf, sizeof(lf), &lf);
|
||||
ReleaseDC(SDL_Window, hc);
|
||||
*alt = abs(lf.lfHeight);
|
||||
}
|
||||
return NULL;
|
||||
default:
|
||||
SDL_SetError("DIB_GetIMValues: unknown enum type %d", value);
|
||||
return "DIB_GetIMValues: unknown enum type";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int DIB_FlushIMString(_THIS, void *buffer)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (buffer && IM_Context.im_compose_sz) {
|
||||
int len;
|
||||
if (SDL_TranslateUNICODE) {
|
||||
int i;
|
||||
Uint16 *b = (Uint16*)buffer;
|
||||
len = IM_Context.im_compose_sz / 2;
|
||||
for (i = 0; i < len; ++i)
|
||||
b[i] = IM_Context.string.im_wide_char_buffer[i];
|
||||
}
|
||||
else {
|
||||
len = IM_Context.im_compose_sz;
|
||||
memcpy(buffer, IM_Context.string.im_multi_byte_buffer, len);
|
||||
}
|
||||
|
||||
result = len;
|
||||
IM_Context.im_compose_sz = 0;
|
||||
}
|
||||
else {
|
||||
if (SDL_TranslateUNICODE)
|
||||
result = IM_Context.im_compose_sz/2;
|
||||
else
|
||||
result = IM_Context.im_compose_sz;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else /* !ENABLE_IM_EVENT */
|
||||
/* Fill with null implementation */
|
||||
|
||||
int DIB_SetIMPosition(_THIS, int x, int y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
char *DIB_SetIMValues(_THIS, SDL_imvalue value, int alt)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
char *DIB_GetIMValues(_THIS, SDL_imvalue value, int *alt)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
int DIB_FlushIMString(_THIS, void *buffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@@ -33,3 +33,8 @@ extern void DIB_DestroyWindow(_THIS);
|
||||
|
||||
extern void DIB_PumpEvents(_THIS);
|
||||
extern void DIB_InitOSKeymap(_THIS);
|
||||
|
||||
extern int DIB_SetIMPosition(_THIS, int x, int y);
|
||||
extern char *DIB_SetIMValues(_THIS, SDL_imvalue value, int alt);
|
||||
extern char *DIB_GetIMValues(_THIS, SDL_imvalue value, int *alt);
|
||||
extern int DIB_FlushIMString(_THIS, void *buffer);
|
||||
|
@@ -94,6 +94,14 @@ extern HWND ParentWindowHWND;
|
||||
extern HINSTANCE aygshell;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
|
||||
static void init_ime();
|
||||
static void free_ime();
|
||||
static int setup_ime(_THIS, Uint32 flags);
|
||||
|
||||
#endif
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat);
|
||||
static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
|
||||
@@ -225,6 +233,11 @@ static SDL_VideoDevice *DIB_CreateDevice(int devindex)
|
||||
WIN_WinPAINT = DIB_WinPAINT;
|
||||
HandleMessage = DIB_HandleMessage;
|
||||
|
||||
device->SetIMPosition = DIB_SetIMPosition;
|
||||
device->SetIMValues = DIB_SetIMValues;
|
||||
device->GetIMValues = DIB_GetIMValues;
|
||||
device->FlushIMString = DIB_FlushIMString;
|
||||
device->GetIMInfo = WIN_GetIMInfo;
|
||||
device->free = DIB_DeleteDevice;
|
||||
|
||||
/* We're finally ready */
|
||||
@@ -1056,6 +1069,10 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
|
||||
video->flags |= SDL_OPENGL;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
if (!setup_ime(this, flags))
|
||||
SDL_SetError("setup_ime fail.");
|
||||
#endif
|
||||
/* JC 14 Mar 2006
|
||||
Flush the message loop or this can cause big problems later
|
||||
Especially if the user decides to use dialog boxes or assert()!
|
||||
@@ -1461,3 +1478,39 @@ void DX5_SoundFocus(HWND hwnd)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
|
||||
static void init_ime()
|
||||
{
|
||||
IM_Context.im_buffer_sz = 0;
|
||||
IM_Context.im_compose_sz = 0;
|
||||
IM_Context.string.im_multi_byte_buffer = 0;
|
||||
|
||||
IM_Context.bFlip = 1;
|
||||
IM_Context.bEnable = 1;
|
||||
|
||||
IM_Context.notify_data = NULL;
|
||||
IM_Context.notify_func = NULL;
|
||||
}
|
||||
|
||||
static void free_ime()
|
||||
{
|
||||
if (IM_Context.string.im_wide_char_buffer) {
|
||||
free(IM_Context.string.im_wide_char_buffer);
|
||||
IM_Context.string.im_wide_char_buffer = 0;
|
||||
IM_Context.im_buffer_sz = 0;
|
||||
IM_Context.im_compose_sz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int setup_ime(_THIS, Uint32 flags)
|
||||
{
|
||||
init_ime();
|
||||
|
||||
IM_Context.video_flags = flags;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_IM_EVENT */
|
||||
|
@@ -68,6 +68,17 @@ static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed);
|
||||
#endif
|
||||
static WNDPROCTYPE userWindowProc = NULL;
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
#include <imm.h>
|
||||
int DX5_HandleComposition(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
/* data field required by DX5_HandleComposition */
|
||||
static COMPOSITIONFORM form;
|
||||
static DWORD end_ticks;
|
||||
extern wchar_t CompositionFontName[LF_FACESIZE];
|
||||
#define IME_MESSAGE_WAIT 1
|
||||
#define IME_END_CR_WAIT 50
|
||||
#endif
|
||||
|
||||
static HWND GetTopLevelParent(HWND hWnd)
|
||||
{
|
||||
HWND hParentWnd;
|
||||
@@ -280,12 +291,31 @@ static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *keybuf)
|
||||
{
|
||||
int i;
|
||||
SDL_keysym keysym;
|
||||
MSG msg;
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
Sleep(IME_MESSAGE_WAIT);
|
||||
#endif
|
||||
|
||||
while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
||||
if(GetMessage(&msg, NULL, 0, 0) > 0) {
|
||||
if(msg.message != WM_SYSKEYDOWN && msg.message != WM_SYSKEYUP) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Translate keyboard messages */
|
||||
for ( i=0; i<numevents; ++i ) {
|
||||
if ( keybuf[i].dwData & 0x80 ) {
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
if (!IM_Context.bCompos && (GetTickCount() - end_ticks > IME_END_CR_WAIT || keybuf[i].dwOfs != 0x1c))
|
||||
#endif
|
||||
{
|
||||
posted = SDL_PrivateKeyboard(SDL_PRESSED,
|
||||
TranslateKey(keybuf[i].dwOfs, &keysym, 1));
|
||||
}
|
||||
} else {
|
||||
posted = SDL_PrivateKeyboard(SDL_RELEASED,
|
||||
TranslateKey(keybuf[i].dwOfs, &keysym, 0));
|
||||
@@ -550,6 +580,17 @@ static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
#define FLIP_BREAK \
|
||||
if (IM_Context.bFlip) { \
|
||||
break; \
|
||||
} else { \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
SDL_Event event_keydown;
|
||||
#endif
|
||||
|
||||
/* The main Win32 event handler */
|
||||
LRESULT DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@@ -595,10 +636,91 @@ LRESULT DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar
|
||||
case WM_SYSKEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_KEYDOWN: {
|
||||
case WM_KEYDOWN:
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
// To ensure the shift of IME.
|
||||
/*if (IM_Context.bFlip && IM_Context.bEnable)*/
|
||||
/* 2019/4/16
|
||||
if (IM_Context.bEnable)
|
||||
SendMessage(hwnd, WM_IME_NOTIFY, wParam, lParam);
|
||||
*/
|
||||
if((lParam & 0xff0000) == 0x360000) {
|
||||
SDL_keysym keysym;
|
||||
if(msg == WM_KEYDOWN) {
|
||||
SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey((lParam >> 16) & 0xff, &keysym, 1));
|
||||
} else if(msg == WM_KEYUP) {
|
||||
SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey((lParam >> 16) & 0xff, &keysym, 0));
|
||||
}
|
||||
}
|
||||
if (msg == WM_KEYDOWN) {
|
||||
if(wParam == VK_PROCESSKEY) {
|
||||
WPARAM vkey = ImmGetVirtualKey(hwnd);
|
||||
if(vkey != VK_PROCESSKEY) {
|
||||
keybd_event(vkey, (lParam >> 16) & 0xff, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//FLIP_BREAK;
|
||||
/* add for im */
|
||||
case WM_INPUTLANGCHANGE:
|
||||
SendMessage(hwnd, WM_IME_NOTIFY, wParam, lParam);
|
||||
FLIP_BREAK;
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
//if (!IM_Context.SDL_IMC)
|
||||
// IM_Context.SDL_IMC = ImmGetContext(hwnd);
|
||||
{
|
||||
HIMC imc = ImmGetContext(hwnd);
|
||||
IM_Context.bCompos = 1;
|
||||
form.dwStyle = CFS_POINT;
|
||||
ImmSetCompositionWindow(imc, &form);
|
||||
ImmReleaseContext(hwnd, imc);
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
//FLIP_BREAK;
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
end_ticks = GetTickCount();
|
||||
IM_Context.bCompos = 0;
|
||||
FLIP_BREAK;
|
||||
case WM_IME_NOTIFY:
|
||||
if (IM_Context.notify_func)/* && IM_Context.bEnable && ImmIsIME(GetKeyboardLayout(0)))*/
|
||||
IM_Context.notify_func(IM_Context.notify_data);
|
||||
|
||||
// To flip state window in fullscreen mode
|
||||
if (IM_Context.bFlip && IM_Context.bEnable) {
|
||||
DefWindowProc(hwnd, WM_IME_NOTIFY, IMN_OPENSTATUSWINDOW, lParam);
|
||||
}
|
||||
FLIP_BREAK;
|
||||
case WM_IME_SETCONTEXT:
|
||||
// To show the composition window in fullscreen mode
|
||||
if (IM_Context.bFlip && IM_Context.bEnable)
|
||||
{
|
||||
lParam |= ISC_SHOWUICOMPOSITIONWINDOW;
|
||||
return DefWindowProc(hwnd, WM_IME_SETCONTEXT, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
|
||||
//if (IM_Context.bFlip)
|
||||
return DefWindowProc(hwnd, WM_IME_SETCONTEXT, wParam, lParam);
|
||||
}
|
||||
FLIP_BREAK;
|
||||
case WM_IME_COMPOSITION:
|
||||
DX5_HandleComposition(hwnd, msg, wParam, lParam);
|
||||
|
||||
if (lParam & GCS_RESULTSTR) {
|
||||
/* Send KEYDOWN event to fix some IME that doesn't sent key down event
|
||||
after composition. */
|
||||
event_keydown.type = SDL_KEYDOWN;
|
||||
SDL_PushEvent(&event_keydown);
|
||||
FLIP_BREAK;
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Ignore windows keyboard messages */;
|
||||
}
|
||||
return(0);
|
||||
#endif
|
||||
|
||||
#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
|
||||
/* Don't allow screen savers or monitor power downs.
|
||||
@@ -642,6 +764,10 @@ LRESULT DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar
|
||||
return(DefWindowProc(hwnd, msg, wParam, lParam));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
#undef FLIP_BREAK
|
||||
#endif
|
||||
|
||||
/* This function checks the windows message queue and DirectInput and returns
|
||||
1 if there was input, 0 if there was no input, or -1 if the application has
|
||||
posted a quit message.
|
||||
@@ -658,6 +784,13 @@ static int DX5_CheckInput(_THIS, int timeout, BOOL processInput)
|
||||
while ( ! posted &&
|
||||
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) {
|
||||
if ( GetMessage(&msg, NULL, 0, 0) > 0 ) {
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
if (IM_Context.bEnable) {
|
||||
if(msg.message != WM_SYSKEYDOWN && msg.message != WM_SYSKEYUP) {
|
||||
TranslateMessage( &msg ); /* for IME */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DispatchMessage(&msg);
|
||||
} else {
|
||||
return(-1);
|
||||
@@ -1003,3 +1136,247 @@ void DX5_DestroyWindow(_THIS)
|
||||
*/
|
||||
WIN_FlushMessageQueue();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
|
||||
int DX5_HandleComposition(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (lParam & GCS_RESULTSTR) {
|
||||
HIMC imc = ImmGetContext(hWnd);
|
||||
|
||||
if (!imc) {
|
||||
IM_Context.im_compose_sz = 0;
|
||||
SDL_SetError("ERROR_NULLCONTEXT");
|
||||
}
|
||||
|
||||
/* Get the size of the result string. */
|
||||
if (SDL_TranslateUNICODE) {
|
||||
IM_Context.im_compose_sz = ImmGetCompositionStringW(imc, GCS_RESULTSTR, NULL, 0);
|
||||
} else {
|
||||
IM_Context.im_compose_sz = ImmGetCompositionStringA(imc, GCS_RESULTSTR, NULL, 0);
|
||||
}
|
||||
if (!IM_Context.im_compose_sz) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (IM_Context.im_compose_sz >= IM_Context.im_buffer_sz) {
|
||||
IM_Context.im_buffer_sz = IM_Context.im_compose_sz + 1*sizeof(wchar_t);
|
||||
IM_Context.string.im_multi_byte_buffer =
|
||||
(char*)realloc(IM_Context.string.im_multi_byte_buffer,
|
||||
IM_Context.im_buffer_sz);
|
||||
}
|
||||
IM_Context.string.im_wide_char_buffer[0] = '\0';
|
||||
}
|
||||
|
||||
if (IM_Context.string.im_multi_byte_buffer) {
|
||||
/* Get the result strings that is generated by IME into lpstr. */
|
||||
if (SDL_TranslateUNICODE) {
|
||||
ImmGetCompositionStringW(imc, GCS_RESULTSTR,
|
||||
IM_Context.string.im_wide_char_buffer, IM_Context.im_buffer_sz);
|
||||
IM_Context.string.im_wide_char_buffer[IM_Context.im_compose_sz/2] = '\0';
|
||||
}
|
||||
else {
|
||||
ImmGetCompositionStringA(imc, GCS_RESULTSTR,
|
||||
IM_Context.string.im_multi_byte_buffer, IM_Context.im_buffer_sz);
|
||||
IM_Context.string.im_multi_byte_buffer[IM_Context.im_compose_sz] = '\0';
|
||||
}
|
||||
ImmReleaseContext(hWnd, imc);
|
||||
}
|
||||
else {
|
||||
IM_Context.im_compose_sz = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (lParam & GCS_COMPSTR) {
|
||||
HIMC imc = ImmGetContext(hWnd);
|
||||
if (!ImmSetCompositionWindow(imc, &form)) {
|
||||
SDL_SetError("ImmSetCompositionWindow: fail to set composition form.\n");
|
||||
}
|
||||
ImmReleaseContext(hWnd, imc);
|
||||
}
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DX5_SetIMPosition(_THIS, int x, int y)
|
||||
{
|
||||
form.dwStyle = CFS_POINT;;
|
||||
form.ptCurrentPos.x = x;
|
||||
form.ptCurrentPos.y = y;
|
||||
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
// if (!IM_Context.SDL_IMC)
|
||||
// IM_Context.SDL_IMC = ImmGetContext(SDL_Window);
|
||||
|
||||
// if (!IM_Context.SDL_IMC)
|
||||
// return 0;
|
||||
|
||||
// if (ImmSetCompositionWindow(IM_Context.SDL_IMC, &form)) {
|
||||
if (ImmSetCompositionWindow(imc, &form)) {
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
return 1;
|
||||
}
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *DX5_SetIMValues(_THIS, SDL_imvalue value, int alt)
|
||||
{
|
||||
switch (value) {
|
||||
case SDL_IM_ENABLE:
|
||||
if (alt) {
|
||||
if(!IM_Context.bEnable) {
|
||||
ImmAssociateContext(SDL_Window, IM_Context.SDL_IMC);
|
||||
IM_Context.bEnable = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if(IM_Context.bEnable) {
|
||||
IM_Context.SDL_IMC = ImmAssociateContext(SDL_Window, 0);
|
||||
IM_Context.bEnable = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_FLIP:
|
||||
if (alt) {
|
||||
IM_Context.bFlip = 1;
|
||||
SendMessage(SDL_Window, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
IM_Context.bFlip = 0;
|
||||
SendMessage(SDL_Window, WM_IME_SETCONTEXT, TRUE, 0);
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_ONOFF:
|
||||
{
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
ImmSetOpenStatus(imc, alt ? TRUE : FALSE);
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
}
|
||||
return NULL;
|
||||
case SDL_IM_FONT_SIZE:
|
||||
{
|
||||
LOGFONTW lf;
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
HDC hc = GetDC(SDL_Window);
|
||||
HFONT hf = (HFONT)GetCurrentObject(hc, OBJ_FONT);
|
||||
GetObjectW(hf, sizeof(lf), &lf);
|
||||
ReleaseDC(SDL_Window, hc);
|
||||
if(CompositionFontName[0]) {
|
||||
wcscpy(lf.lfFaceName, CompositionFontName);
|
||||
}
|
||||
lf.lfHeight = -alt;
|
||||
lf.lfWidth = alt / 2;
|
||||
ImmSetCompositionFontW(imc, &lf);
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
}
|
||||
return NULL;
|
||||
default:
|
||||
SDL_SetError("SDL_SetIMValues: unknow enum type: %d", value);
|
||||
return "SDL_SetIMValues: unknow enum type";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *DX5_GetIMValues(_THIS, SDL_imvalue value, int *alt)
|
||||
{
|
||||
switch (value) {
|
||||
case SDL_IM_ENABLE:
|
||||
if (IM_Context.bEnable) {
|
||||
*alt = 1;
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
*alt = 0;
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_FLIP:
|
||||
if (IM_Context.bFlip) {
|
||||
*alt = 1;
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
*alt = 0;
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_ONOFF:
|
||||
{
|
||||
HIMC imc = ImmGetContext(SDL_Window);
|
||||
if(ImmGetOpenStatus(imc)) {
|
||||
*alt = 1;
|
||||
} else {
|
||||
*alt = 0;
|
||||
}
|
||||
ImmReleaseContext(SDL_Window, imc);
|
||||
return NULL;
|
||||
}
|
||||
case SDL_IM_FONT_SIZE:
|
||||
{
|
||||
LOGFONTW lf;
|
||||
HDC hc = GetDC(SDL_Window);
|
||||
HFONT hf = (HFONT)GetCurrentObject(hc, OBJ_FONT);
|
||||
GetObjectW(hf, sizeof(lf), &lf);
|
||||
ReleaseDC(SDL_Window, hc);
|
||||
*alt = abs(lf.lfHeight);
|
||||
}
|
||||
return NULL;
|
||||
default:
|
||||
SDL_SetError("DX5_GetIMValues: nuknown enum type %d", value);
|
||||
return "DX5_GetIMValues: nuknown enum type";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int DX5_FlushIMString(_THIS, void *buffer)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (buffer && IM_Context.im_compose_sz) {
|
||||
int len;
|
||||
if (SDL_TranslateUNICODE) {
|
||||
int i;
|
||||
Uint16 *b = (Uint16*)buffer;
|
||||
len = IM_Context.im_compose_sz / 2;
|
||||
for (i = 0; i < len; ++i)
|
||||
b[i] = IM_Context.string.im_wide_char_buffer[i];
|
||||
}
|
||||
else {
|
||||
len = IM_Context.im_compose_sz;
|
||||
memcpy(buffer, IM_Context.string.im_multi_byte_buffer, len);
|
||||
}
|
||||
|
||||
result = len;
|
||||
IM_Context.im_compose_sz = 0;
|
||||
}
|
||||
else {
|
||||
if (SDL_TranslateUNICODE)
|
||||
result = IM_Context.im_compose_sz/2;
|
||||
else
|
||||
result = IM_Context.im_compose_sz;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else /* !ENABLE_IM_EVENT */
|
||||
/* Fill with null implementation */
|
||||
|
||||
int DX5_SetIMPosition(_THIS, int x, int y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
char *DX5_SetIMValues(_THIS, SDL_imvalue value, int alt)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
char *DX5_GetIMValues(_THIS, SDL_imvalue value, int *alt)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
int DX5_FlushIMString(_THIS, void *buffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@@ -35,3 +35,7 @@ extern void DX5_PumpEvents(_THIS);
|
||||
extern void DX5_InitOSKeymap(_THIS);
|
||||
extern void DX5_DInputReset(_THIS, int fullscreen);
|
||||
|
||||
extern int DX5_SetIMPosition(_THIS, int x, int y);
|
||||
extern char *DX5_SetIMValues(_THIS, SDL_imvalue value, int alt);
|
||||
extern char *DX5_GetIMValues(_THIS, SDL_imvalue value, int *alt);
|
||||
extern int DX5_FlushIMString(_THIS, void *buffer);
|
||||
|
@@ -417,6 +417,28 @@ static DIOBJECTDATAFORMAT JOY_fmt[] = {
|
||||
|
||||
const DIDATAFORMAT c_dfDIJoystick = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000001, 80, 44, JOY_fmt };
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
|
||||
static void init_ime();
|
||||
static void free_ime();
|
||||
static int setup_ime(_THIS, LPDIRECTDRAWSURFACE3 lpFrontBuffer, Uint32 flags);
|
||||
int _FSIM_Init(HWND hwndApp, IDirectDraw *dd, IDirectDrawSurface *FrontBuffer,
|
||||
IDirectDrawSurface *BackBuffer);
|
||||
HWND _FSIM_Begin(HWND hwnd);
|
||||
void _FSIM_End(void);
|
||||
HRESULT _FSIM_Update(void);
|
||||
int _FSIM_IsActive(void);
|
||||
|
||||
/**
|
||||
* Local definitions specific to IM
|
||||
*/
|
||||
static IDirectDraw *ddObject = NULL;
|
||||
static IDirectDrawSurface3 *ddFrontBuffer = NULL;
|
||||
static IDirectDrawSurface3 *ddBackBuffer = NULL;
|
||||
static IDirectDrawClipper *ddClipper = NULL;
|
||||
static HWND hFSIME = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat);
|
||||
@@ -643,6 +665,11 @@ static SDL_VideoDevice *DX5_CreateDevice(int devindex)
|
||||
WIN_WinPAINT = DX5_WinPAINT;
|
||||
HandleMessage = DX5_HandleMessage;
|
||||
|
||||
device->SetIMPosition = DX5_SetIMPosition;
|
||||
device->SetIMValues = DX5_SetIMValues;
|
||||
device->GetIMValues = DX5_GetIMValues;
|
||||
device->FlushIMString = DX5_FlushIMString;
|
||||
device->GetIMInfo = WIN_GetIMInfo;
|
||||
device->free = DX5_DeleteDevice;
|
||||
|
||||
/* We're finally ready */
|
||||
@@ -1247,6 +1274,11 @@ SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
|
||||
}
|
||||
SDL_resizing = 0;
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
if (!setup_ime(this, SDL_primary, flags))
|
||||
SDL_SetError("setup_ime fail.");
|
||||
#endif
|
||||
|
||||
/* Set up for OpenGL */
|
||||
if ( WIN_GL_SetupWindow(this) < 0 ) {
|
||||
return(NULL);
|
||||
@@ -1645,6 +1677,10 @@ SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
|
||||
SetForegroundWindow(SDL_Window);
|
||||
SDL_resizing = 0;
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
if (!setup_ime(this, SDL_primary, flags))
|
||||
SDL_SetError("setup_ime fail.");
|
||||
#endif
|
||||
/* JC 14 Mar 2006
|
||||
Flush the message loop or this can cause big problems later
|
||||
Especially if the user decides to use dialog boxes or assert()!
|
||||
@@ -2103,8 +2139,36 @@ static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
|
||||
|
||||
/* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */
|
||||
/* Dmitry Yakimov (ftech@tula.net) */
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
while(IDirectDrawSurface3_GetFlipStatus(ddFrontBuffer, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
|
||||
#else
|
||||
while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
if (_FSIM_IsActive()) {
|
||||
result = _FSIM_Update();
|
||||
if (result == DDERR_SURFACELOST) {
|
||||
result = IDirectDrawSurface3_Restore(ddFrontBuffer);
|
||||
while(IDirectDrawSurface3_GetFlipStatus(ddFrontBuffer, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
|
||||
result = _FSIM_Update();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (IM_Context.video_flags & SDL_DOUBLEBUF) {
|
||||
IDirectDrawSurface3_SetClipper(ddFrontBuffer, NULL);
|
||||
result = IDirectDrawSurface3_Blt(
|
||||
ddFrontBuffer, NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);
|
||||
if ( result == DDERR_SURFACELOST ) {
|
||||
result = IDirectDrawSurface3_Restore(ddFrontBuffer);
|
||||
while(IDirectDrawSurface3_GetFlipStatus(
|
||||
ddFrontBuffer, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING)
|
||||
;
|
||||
result = IDirectDrawSurface3_Blt(ddFrontBuffer, NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
|
||||
if ( result == DDERR_SURFACELOST ) {
|
||||
result = IDirectDrawSurface3_Restore(
|
||||
@@ -2112,6 +2176,12 @@ static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
|
||||
while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
|
||||
result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( result != DD_OK ) {
|
||||
SetDDerror("DirectDrawSurface3::Flip", result);
|
||||
return(-1);
|
||||
@@ -2412,6 +2482,10 @@ void DX5_VideoQuit(_THIS)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
free_ime();
|
||||
#endif
|
||||
|
||||
/* Free any palettes we used */
|
||||
if ( SDL_palette != NULL ) {
|
||||
IDirectDrawPalette_Release(SDL_palette);
|
||||
@@ -2535,3 +2609,155 @@ void DX5_WinPAINT(_THIS, HDC hdc)
|
||||
{
|
||||
SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IM_EVENT
|
||||
|
||||
static void init_ime()
|
||||
{
|
||||
// IM_Context.SDL_IMC = ImmGetContext(SDL_Window);
|
||||
|
||||
IM_Context.im_buffer_sz = 0;
|
||||
IM_Context.im_compose_sz = 0;
|
||||
IM_Context.string.im_multi_byte_buffer = 0;
|
||||
|
||||
IM_Context.bFlip = 1;
|
||||
IM_Context.bEnable = 1;
|
||||
|
||||
IM_Context.notify_data = NULL;
|
||||
IM_Context.notify_func = NULL;
|
||||
}
|
||||
|
||||
static void free_ime()
|
||||
{
|
||||
if (IM_Context.string.im_wide_char_buffer) {
|
||||
free(IM_Context.string.im_wide_char_buffer);
|
||||
IM_Context.string.im_wide_char_buffer = 0;
|
||||
IM_Context.im_buffer_sz = 0;
|
||||
IM_Context.im_compose_sz = 0;
|
||||
}
|
||||
_FSIM_End();
|
||||
}
|
||||
|
||||
static int setup_ime(_THIS, LPDIRECTDRAWSURFACE3 lpFrontBuffer, Uint32 flags)
|
||||
{
|
||||
/*DDSCAPS2 ddscaps;*/
|
||||
DDSCAPS ddscaps;
|
||||
LPDIRECTDRAW2 _ddraw2 = NULL;
|
||||
static IDirectDrawSurface3 *ddFrontBuffer = NULL;
|
||||
static IDirectDrawSurface3 *ddBackBuffer = NULL;
|
||||
|
||||
int i;
|
||||
|
||||
init_ime();
|
||||
IM_Context.video_flags = flags;
|
||||
|
||||
SendMessage(SDL_Window, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
|
||||
|
||||
if ((flags & SDL_FULLSCREEN) && (flags & SDL_DOUBLEBUF)) {
|
||||
if(i = IDirectDrawSurface3_QueryInterface(lpFrontBuffer, &IID_IDirectDrawSurface3,
|
||||
(LPVOID *)&ddFrontBuffer) != DD_OK) {
|
||||
SetDDerror("IDirectDrawSurface3_QueryInterface", i);
|
||||
printf("%s\n", SDL_GetError());
|
||||
}
|
||||
|
||||
if(i = IDirectDrawSurface3_GetDDInterface(ddFrontBuffer, &_ddraw2) != DD_OK) {
|
||||
SetDDerror("IDirectDrawSurface3_GetDDInterface", i);
|
||||
printf("%s\n", SDL_GetError());
|
||||
}
|
||||
|
||||
memset(&ddscaps, 0, sizeof(ddscaps));
|
||||
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
if (i = IDirectDrawSurface3_GetAttachedSurface(ddFrontBuffer,
|
||||
(LPDDSCAPS)&ddscaps, &ddBackBuffer) != DD_OK) {
|
||||
SetDDerror("IDirectDrawSurface3_GetAttachedSurface", i);
|
||||
printf("%s\n", SDL_GetError());
|
||||
}
|
||||
else {
|
||||
if (!_FSIM_Init(SDL_Window, (IDirectDraw*)_ddraw2, (IDirectDrawSurface*)ddFrontBuffer, (IDirectDrawSurface*)ddBackBuffer))
|
||||
return 0;
|
||||
_FSIM_Begin(ImmGetDefaultIMEWnd(SDL_Window));
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _FSIM_Init(HWND hwndApp, IDirectDraw *dd, IDirectDrawSurface *FrontBuffer,
|
||||
IDirectDrawSurface *BackBuffer)
|
||||
{
|
||||
/*DDSURFACEDESC2 ddsd;*/
|
||||
DDSURFACEDESC ddsd;
|
||||
DDCAPS ddcaps;
|
||||
|
||||
memset(&ddcaps, 0, sizeof(ddcaps));
|
||||
ddcaps.dwSize = sizeof(ddcaps);
|
||||
IDirectDraw2_GetCaps(dd,&ddcaps, NULL);
|
||||
/*
|
||||
if (!(ddcaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED))
|
||||
return 0;*/
|
||||
|
||||
/* Save DirectDraw object passed in */
|
||||
ddObject = dd;
|
||||
|
||||
/* Save buffers passed in */
|
||||
ddFrontBuffer = (IDirectDrawSurface3*)FrontBuffer;
|
||||
ddBackBuffer = (IDirectDrawSurface3*)BackBuffer;
|
||||
|
||||
/* Get DirectDraw surface dimensions */
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
|
||||
IDirectDrawSurface3_GetSurfaceDesc(ddBackBuffer, (LPDDSURFACEDESC)&ddsd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
HWND _FSIM_Begin(HWND hwnd)
|
||||
{
|
||||
/* If no handle passed in, assume existing content window */
|
||||
if (hwnd == NULL)
|
||||
hwnd = SDL_Window;
|
||||
|
||||
if (hwnd == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Create a clipper (used in IDirectDrawSurface::Blt call) */
|
||||
if (IDirectDraw_CreateClipper(ddObject, 0, &ddClipper, NULL) == DD_OK)
|
||||
IDirectDrawClipper_SetHWnd(ddClipper, 0, SDL_Window);
|
||||
|
||||
/* Normal GDI device, so just flip to GDI so content window can be seen */
|
||||
IDirectDraw_FlipToGDISurface(ddObject);
|
||||
|
||||
hFSIME = hwnd;
|
||||
return hFSIME;
|
||||
}
|
||||
|
||||
void _FSIM_End(void)
|
||||
{
|
||||
if (hFSIME)
|
||||
hFSIME = NULL;
|
||||
|
||||
/* Get rid of clipper object */
|
||||
if (ddClipper) {
|
||||
IDirectDrawClipper_Release(ddClipper);
|
||||
ddClipper = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT _FSIM_Update(void)
|
||||
{
|
||||
/**
|
||||
* GDI hardware
|
||||
* Update the surface with a blt
|
||||
*/
|
||||
IDirectDrawSurface3_SetClipper(ddFrontBuffer, ddClipper);
|
||||
return IDirectDrawSurface3_Blt(ddFrontBuffer, NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);
|
||||
}
|
||||
|
||||
int _FSIM_IsActive(void)
|
||||
{
|
||||
if (IM_Context.bFlip)
|
||||
return (hFSIME != NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_IM_EVENT */
|
||||
|
Reference in New Issue
Block a user