support system IME for Windows SDL1 builds

This commit is contained in:
Wengier
2021-06-07 12:17:57 -04:00
parent d918998084
commit 61b807e9ad
30 changed files with 1765 additions and 23 deletions

View File

@@ -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
}

View File

@@ -105,6 +105,7 @@
#if defined(WIN32) || defined(_WIN32)
#undef __WIN32__
#define __WIN32__ 1
#define ENABLE_IM_EVENT 1
#endif
#endif /* _SDL_platform_h */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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)
*/

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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

View File

@@ -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);

View File

@@ -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 */