Hello all,
We are experimenting some problems with displaying and inputting Chinese characters in WINE (January 2002 or newer). For example, most Chinese characters show up as squares, and it seems that WINE doesn't accept Chinese input via XCIN (an input method server using the XIM protocol). Did we misconfigured something? Or is this a known problem in WINE? Any pointers would be appreciated. Thanks!
Cheers,
Anthony
"Anthony Fok" anthony@thizlinux.com wrote:
We are experimenting some problems with displaying and inputting Chinese characters in WINE (January 2002 or newer). For example, most Chinese characters show up as squares,
Probably some font misconfiguration problem. Apparently displaying of Chinese characters should work since output of Japanese characters admittedly works.
and it seems that WINE doesn't accept Chinese input via XCIN (an input method server using the XIM protocol). Did we misconfigured something? Or is this a known problem in WINE? Any pointers would be appreciated. Thanks!
I'm afraid that correct input of Chinese and any multibyte characters will require almost complete rewrite of the Wine keyboard code using X Input Method/Input Context. Simultaneously it will solve the problem with dead keys.
Unfortunately nobody worked on that problems yet. Do you want to try?
Hello Dmitry,
On Sun, Feb 24, 2002 at 07:32:09PM +0800, Dmitry Timoshkov wrote:
"Anthony Fok" anthony@thizlinux.com wrote:
We are experimenting some problems with displaying and inputting Chinese characters in WINE (January 2002 or newer). For example, most Chinese characters show up as squares,
Probably some font misconfiguration problem. Apparently displaying of Chinese characters should work since output of Japanese characters admittedly works.
Thanks for your advice. After tweaking the font settings ~/.wine/config, we were able to get notepad to display Chinese text. However, it seems to only work with bitmap fonts like -taipei-*-; it had some problems with the Arphic TrueType fonts that it seems Wine was using a different character set to display the characters. We'll do more investigation. :-)
and it seems that WINE doesn't accept Chinese input via XCIN (an input method server using the XIM protocol). Did we misconfigured something? Or is this a known problem in WINE? Any pointers would be appreciated. Thanks!
I'm afraid that correct input of Chinese and any multibyte characters will require almost complete rewrite of the Wine keyboard code using X Input Method/Input Context. Simultaneously it will solve the problem with dead keys.
Unfortunately nobody worked on that problems yet. Do you want to try?
Yes, we are willing to give it a try. How big a task is this? Where should we start? Which files need to be modified? (I am new to Wine, so any starters/pointers would be helpful.) :-) Many thanks for your help!
Cheers,
Anthony
"Anthony Fok" anthony@thizlinux.com wrote:
We are experimenting some problems with displaying and inputting Chinese characters in WINE (January 2002 or newer). For example, most Chinese characters show up as squares,
Probably some font misconfiguration problem. Apparently displaying of Chinese characters should work since output of Japanese characters admittedly works.
Thanks for your advice. After tweaking the font settings ~/.wine/config, we were able to get notepad to display Chinese text. However, it seems to only work with bitmap fonts like -taipei-*-; it had some problems with the Arphic TrueType fonts that it seems Wine was using a different character set to display the characters.
That's because truetype support has been only recently introduced and wasn't cleaned up for all character sets yet. Apparently only people like you familiar with problems of multibyte languages could enormously help in that area.
We'll do more investigation. :-)
Good. :-)
and it seems that WINE doesn't accept Chinese input via XCIN (an input method server using the XIM protocol). Did we misconfigured something? Or is this a known problem in WINE? Any pointers would be appreciated. Thanks!
I'm afraid that correct input of Chinese and any multibyte characters will require almost complete rewrite of the Wine keyboard code using X Input Method/Input Context. Simultaneously it will solve the problem with dead keys.
Unfortunately nobody worked on that problems yet. Do you want to try?
Yes, we are willing to give it a try. How big a task is this? Where should we start? Which files need to be modified?
I have made some tests and found that actually very little work is required: create Input context using XOpenIM/XCreateIC. In order to not create context for each window and therefore save some memory do attach windows to only one global Input context in FocusIn event handler: XUnsetICFocus()/XSetICValues/ XSetICFocus(). Use XFilterEvent() to pass all work to an X server.
And don't forget to remove ugly dead keys emulating code from windows/message.c.
Dmitry Timoshkov wrote:
"Anthony Fok" anthony@thizlinux.com wrote:
I have made some tests and found that actually very little work is required: create Input context using XOpenIM/XCreateIC. In order to not create context for each window and therefore save some memory do attach windows to only one global Input context in FocusIn event handler: XUnsetICFocus()/XSetICValues/ XSetICFocus(). Use XFilterEvent() to pass all work to an X server.
And don't forget to remove ugly dead keys emulating code from windows/message.c.
Hello,
I am sorry that I am newbie to Xlib, wine and xcin. I would like to ask if I should modify dlls/x11drv/x11drv_main.c, in process_attach(), continue the call of TSXOpenIM(display, NULL, NULL, NULL);
XRegisterIMInstantiateCallback(...,im_callback,...);
and in my callback function:
im_callback() { XOpenIM(); ... XCreateIC(); }
as I know, we need to wrap X functions with wine_tsx11_lock() and wine_tsx11_unlock(); Unfortunately I cannot find the IM API function prototypes
e.g. XGetIMValues()
when I type "man XGetIMValues" it showed
~~~~~~~~~~~~~~~ XOpenIM(3X11) XLIB FUNCTIONS XOpenIM(3X11)
NAME XOpenIM, XCloseIM, XSetIMValues, XGetIMValues, XDisplay- OfIM, XLocaleOfIM, XRegisterIMInstantiateCallback, XUnreg- isterIMInstantiateCallback - open, close, and otain input method information
SYNTAX XIM XOpenIM(display, db, res_name, res_class) Display *display; XrmDatabase db; char *res_name; char *res_class;
Status XCloseIM(im) XIM im;
char * XSetIMValues(im, ...) XIM im;
char * XGetIMValues(im, ...) XIM im; ... ~~~~~~~~~~~~~~
how can I know the details of the arguments? (sorry, maybe it's a Xlib question)
TSXGetIMValues(XIM im, ?????) { wine_tsx11_lock(); XGetIMValues(...); wine_tsx11_unlock(); }
and After my modifications, it does not work. Could anybody help? Thanks very much! (I attached x11drv_main.c that I modified)
/* * X11DRV initialization code * * Copyright 1998 Patrik Stridvall * Copyright 2000 Alexandre Julliard */
#include "config.h"
#ifdef NO_REENTRANT_X11 /* Get pointers to the static errno and h_errno variables used by Xlib. This must be done before including <errno.h> makes the variables invisible. */ extern int errno; static int *perrno = &errno; extern int h_errno; static int *ph_errno = &h_errno; #endif /* NO_REENTRANT_X11 */
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #include <unistd.h> #include <X11/cursorfont.h> #include "ts_xlib.h" #include "ts_xutil.h" #include "ts_shape.h"
#include "winbase.h" #include "wine/winbase16.h" #include "winreg.h"
#include "debugtools.h" #include "gdi.h" #include "file.h" #include "options.h" #include "user.h" #include "win.h" #include "wine_gl.h" #include "x11drv.h" #include "xvidmode.h" #include "dga2.h"
DEFAULT_DEBUG_CHANNEL(x11drv);
static void (*old_tsx11_lock)(void); static void (*old_tsx11_unlock)(void);
static CRITICAL_SECTION X11DRV_CritSection = CRITICAL_SECTION_INIT("X11DRV_CritSection");
Screen *screen; Visual *visual; unsigned int screen_width; unsigned int screen_height; unsigned int screen_depth; Window root_window; int dxgrab, usedga, usexvidmode;
unsigned int X11DRV_server_startticks;
static BOOL synchronous; /* run in synchronous mode? */ static char *desktop_geometry; static XVisualInfo *desktop_vi;
#define IS_OPTION_TRUE(ch) \ ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1') #define IS_OPTION_FALSE(ch) \ ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
#ifdef NO_REENTRANT_X11 static int* (*old_errno_location)(void); static int* (*old_h_errno_location)(void);
/*********************************************************************** * x11_errno_location * * Get the per-thread errno location. */ static int *x11_errno_location(void) { /* Use static libc errno while running in Xlib. */ if (X11DRV_CritSection.OwningThread == GetCurrentThreadId()) return perrno; return old_errno_location(); }
/*********************************************************************** * x11_h_errno_location * * Get the per-thread h_errno location. */ static int *x11_h_errno_location(void) { /* Use static libc h_errno while running in Xlib. */ if (X11DRV_CritSection.OwningThread == GetCurrentThreadId()) return ph_errno; return old_h_errno_location(); } #endif /* NO_REENTRANT_X11 */
//MEW
#include <X11/Xlocale.h>
typedef struct { XIMStyle style; char *description; } im_style_t;
char *fontset_name; XFontSet fontset; int ef_height, ef_width, ef_ascent; XRectangle win_rect;
XIM im; XIC ic; char *im_name; char *im_style; char *lc_ctype; char *encoding; XIMStyle style; wchar_t input_buf[1024]; int idx; char ic_focus; im_style_t im_styles[] = { { XIMPreeditNothing | XIMStatusNothing, "Root" }, { XIMPreeditPosition | XIMStatusNothing, "OverTheSpot" }, { XIMPreeditArea | XIMStatusArea, "OffTheSpot" }, { XIMPreeditCallbacks| XIMStatusCallbacks, "OnTheSpot" }, { (XIMStyle)0, NULL }};
//MEW
/*********************************************************************** * error_handler */ static int error_handler(Display *display, XErrorEvent *error_evt) { DebugBreak(); /* force an entry in the debugger */ return 0; }
/*********************************************************************** * lock_tsx11 */ static void lock_tsx11(void) { RtlEnterCriticalSection( &X11DRV_CritSection ); }
/*********************************************************************** * unlock_tsx11 */ static void unlock_tsx11(void) { RtlLeaveCriticalSection( &X11DRV_CritSection ); }
/*********************************************************************** * get_server_startup * * Get the server startup time * Won't be exact, but should be sufficient */ static void get_server_startup(void) { struct timeval t; gettimeofday( &t, NULL ); X11DRV_server_startticks = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - GetTickCount(); }
/*********************************************************************** * get_config_key * * Get a config key from either the app-specific or the default config */ inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, char *buffer, DWORD size ) { if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size )) return 0; return RegQueryValueExA( defkey, name, 0, NULL, buffer, &size ); }
/*********************************************************************** * setup_options * * Setup the x11drv options. */ static void setup_options(void) { char buffer[MAX_PATH+16]; HKEY hkey, appkey = 0; DWORD count;
if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\Wine\Wine\Config\x11drv", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL )) { ERR("Cannot create config registry key\n" ); ExitProcess(1); }
/* open the app-specific key */
if (GetModuleFileName16( GetCurrentTask(), buffer, MAX_PATH ) || GetModuleFileNameA( 0, buffer, MAX_PATH )) { HKEY tmpkey; char *p, *appname = buffer; if ((p = strrchr( appname, '/' ))) appname = p + 1; if ((p = strrchr( appname, '\' ))) appname = p + 1; strcat( appname, "\x11drv" ); if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\Wine\Wine\Config\AppDefaults", &tmpkey )) { if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0; RegCloseKey( tmpkey ); } }
/* get the display name */
strcpy( buffer, "DISPLAY=" ); count = sizeof(buffer) - 8; if (!RegQueryValueExA( hkey, "display", 0, NULL, buffer + 8, &count )) { const char *display_name = getenv( "DISPLAY" ); if (display_name && strcmp( buffer, display_name )) MESSAGE( "x11drv: Warning: $DISPLAY variable ignored, using '%s' specified in config file\n", buffer + 8 ); putenv( strdup(buffer) ); }
/* check --managed option in wine config file if it was not set on command line */
if (!Options.managed) { if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) )) Options.managed = IS_OPTION_TRUE( buffer[0] ); }
if (!get_config_key( hkey, appkey, "Desktop", buffer, sizeof(buffer) )) { /* Imperfect validation: If Desktop=N, then we don't turn on ** the --desktop option. We should really validate for a correct ** sizing entry */ if (!IS_OPTION_FALSE(buffer[0])) desktop_geometry = strdup(buffer); }
if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) )) dxgrab = IS_OPTION_TRUE( buffer[0] );
if (!get_config_key( hkey, appkey, "UseDGA", buffer, sizeof(buffer) )) usedga = IS_OPTION_TRUE( buffer[0] );
if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) )) usexvidmode = IS_OPTION_TRUE( buffer[0] );
screen_depth = 0; if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) )) screen_depth = atoi(buffer);
if (!get_config_key( hkey, appkey, "Synchronous", buffer, sizeof(buffer) )) synchronous = IS_OPTION_TRUE( buffer[0] );
if (appkey) RegCloseKey( appkey ); RegCloseKey( hkey ); }
/*********************************************************************** * setup_opengl_visual * * Setup the default visual used for OpenGL and Direct3D, and the desktop * window (if it exists). If OpenGL isn't available, the visual is simply * set to the default visual for the display */ #ifdef HAVE_OPENGL static void setup_opengl_visual( Display *display ) { int err_base, evt_base;
/* In order to support OpenGL or D3D, we require a double-buffered * visual */ if (glXQueryExtension(display, &err_base, &evt_base) == True) { int dblBuf[]={GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None}; ENTER_GL(); desktop_vi = glXChooseVisual(display, DefaultScreen(display), dblBuf); LEAVE_GL(); }
if (desktop_vi != NULL) { visual = desktop_vi->visual; screen = ScreenOfDisplay(display, desktop_vi->screen); screen_depth = desktop_vi->depth; } } #endif /* HAVE_OPENGL */
////////////////////////////////////////////////////////////////////////// //MEW static void locale_init(void) { char *s;
if ((s = setlocale(LC_CTYPE, "")) == NULL) { //printf("setlocale LC_CTYPE false.\n"); printf("setlocale LC_CTYPE false.\n"); exit(0); } lc_ctype = (char *)strdup(s); if ((s = strchr(lc_ctype, '.')) != NULL) { *s = '\0'; s++; } else s = "";
printf("LC_CTYPE = %s\n", lc_ctype);
while (*s) { *s = (char)tolower(*s); s++; }
printf("ENCODING = %s\n", s);
if (XSupportsLocale() != True) { printf("XSupportsLocale false.\n"); exit(0); } }
static void destroy_callback_func(XIM current_ic, XPointer client_data, XPointer call_data) { ic = NULL; im = NULL; ic_focus = 0;
printf("destroy_callback_func\n"); }
static void im_callback(Display *display, XPointer client_data, XPointer call_data) { XIMStyles *xim_styles = NULL; /* XIMValuesList im_values_list; */ XIMCallback destroy; int i, j;
XVaNestedList preedit_attr = NULL; XPoint spot; XRectangle local_win_rect;
/* * Open connection to IM server. */ if (! (im = XOpenIM(display, NULL, NULL, NULL))) { printf("Cannot open the connection to XIM server.\n"); exit(1); }
/* * Get IM values. */ /* if (XGetIMValues(im, XNQueryIMValuesList, &im_values_list, NULL) || ! im_values_list.count_values) { printf("no IM values list available.\n"); XCloseIM(im); exit(1); } else { for (i=0; i<im_values_list.count_values; i++) printf("supported: %s\n", im_values_list.supported_values[i]); } destroy.callback = (XIMProc)destroy_callback_func; destroy.client_data = NULL; XSetIMValues(im, XNDestroyCallback, &destroy, NULL);
*/
/* * Detect the input style supported by XIM server. */ if (XGetIMValues(im, XNQueryInputStyle, &xim_styles, NULL) || ! xim_styles) { printf("input method doesn't support any style\n"); XCloseIM(im); exit(1); } else { for (i=0; i<xim_styles->count_styles; i++) { for (j=0; im_styles[j].description!=NULL; j++) { if (im_styles[j].style == xim_styles->supported_styles[i]) { printf("XIM server support input_style = %s\n", im_styles[j].description); break; } } if (im_styles[j].description==NULL) printf("XIM server support unknown input_style = %x\n", (unsigned)(xim_styles->supported_styles[i])); } } /* * Setting the XIM style used by me. */ if (im_style) { for (j=0; im_styles[j].description!=NULL; j++) { if (! strcmp(im_styles[j].description, im_style)) { style = im_styles[j].style; printf("Use input style: %s\n", im_style); break; } } if (im_styles[j].description==NULL) { printf("The input style %s is not supported.\n", im_style); exit(1); }
} else { /* Root input_style as the default */ for (j=0; im_styles[j].description!=NULL; j++) { if (! strcmp(im_styles[j].description, "Root")) { style = im_styles[j].style; printf("Use input style: %s\n", "Root"); break; } } } /* OverTheSpot */ /* if (style == (XIMPreeditPosition | XIMStatusNothing)) { spot.x = 5; spot.y = 2*ef_height + 3*(ef_ascent+5); local_win_rect.x = 1; local_win_rect.y = 1; local_win_rect.width = win_rect.width; local_win_rect.height = win_rect.height; preedit_attr = XVaCreateNestedList(0, XNArea, &local_win_rect, XNSpotLocation, &spot, XNFontSet, fontset, XNForeground, WhitePixel(display, screen), XNBackground, BlackPixel(display, screen), NULL); } */
/* * Create IC. */ ic = XCreateIC(im, XNInputStyle, style, XNClientWindow, root_window, XNFocusWindow, root_window, (preedit_attr) ? XNPreeditAttributes : NULL, preedit_attr, NULL); if(ic == NULL) { printf("Cannot create XIC.\n"); exit(1); } }
static void xim_init(Display *display) { char buf[1024];
memset(buf, 0, 1024); if (XSetLocaleModifiers(buf) == NULL) { printf("XSetLocaleModifiers false.\n"); exit(0); } if (XRegisterIMInstantiateCallback( display, NULL, NULL, NULL, im_callback, NULL) != True) { printf("XRegisterIMInstantiateCallback false.\n"); exit(0); } }
//MEW
/*********************************************************************** * X11DRV process initialisation routine */ static void process_attach(void) { Display *display;
get_server_startup(); setup_options();
/* setup TSX11 locking */ #ifdef NO_REENTRANT_X11 old_errno_location = InterlockedExchangePointer( &wine_errno_location, x11_errno_location ); old_h_errno_location = InterlockedExchangePointer( &wine_h_errno_location, x11_h_errno_location ); #endif /* NO_REENTRANT_X11 */ old_tsx11_lock = wine_tsx11_lock; old_tsx11_unlock = wine_tsx11_unlock; wine_tsx11_lock = lock_tsx11; wine_tsx11_unlock = unlock_tsx11;
/* Open display */
if (!(display = TSXOpenDisplay( NULL ))) { MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) ); ExitProcess(1); } fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */ screen = DefaultScreenOfDisplay( display ); visual = DefaultVisual( display, DefaultScreen(display) ); root_window = DefaultRootWindow( display );
/* Initialize screen depth */
if (screen_depth) /* depth specified */ { int depth_count, i; int *depth_list = TSXListDepths(display, DefaultScreen(display), &depth_count); for (i = 0; i < depth_count; i++) if (depth_list[i] == screen_depth) break; TSXFree( depth_list ); if (i >= depth_count) { MESSAGE( "x11drv: Depth %d not supported on this screen.\n", screen_depth ); ExitProcess(1); } } else screen_depth = DefaultDepthOfScreen( screen );
/* If OpenGL is available, change the default visual, etc as necessary */ #ifdef HAVE_OPENGL setup_opengl_visual( display ); #endif /* HAVE_OPENGL */
/* tell the libX11 that we will do input method handling ourselves * that keep libX11 from doing anything whith dead keys, allowing Wine * to have total control over dead keys, that is this line allows * them to work in Wine, even whith a libX11 including the dead key * patches from Th.Quinot (http://Web.FdN.FR/~tquinot/dead-keys.en.html) */
//MEW //TSXOpenIM( display, NULL, NULL, NULL);
///////////////// //wine_tsx11_lock();
locale_init();
xim_init(display);
//////////////////// //wine_tsx11_unlock(); //MEW
if (synchronous) { XSetErrorHandler( error_handler ); XSynchronize( display, True ); }
screen_width = WidthOfScreen( screen ); screen_height = HeightOfScreen( screen );
if (desktop_geometry) { Options.managed = FALSE; root_window = X11DRV_create_desktop( desktop_vi, desktop_geometry ); }
/* initialize GDI */ if(!X11DRV_GDI_Initialize( display )) { ERR( "Couldn't Initialize GDI.\n" ); ExitProcess(1); }
#ifdef HAVE_LIBXXF86VM /* initialize XVidMode */ X11DRV_XF86VM_Init(); #endif #ifdef HAVE_LIBXXF86DGA2 /* initialize DGA2 */ X11DRV_XF86DGA2_Init(); #endif #ifdef HAVE_OPENGL /* initialize GLX */ /*X11DRV_GLX_Init();*/ #endif
/* load display.dll */ LoadLibrary16( "display" ); }
/*********************************************************************** * X11DRV thread termination routine */ static void thread_detach(void) { struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
if (data) { CloseHandle( data->display_fd ); wine_tsx11_lock(); XCloseDisplay( data->display ); wine_tsx11_unlock(); HeapFree( GetProcessHeap(), 0, data ); } }
/*********************************************************************** * X11DRV process termination routine */ static void process_detach(void) { #ifdef HAVE_OPENGL /* cleanup GLX */ /*X11DRV_GLX_Cleanup();*/ #endif #ifdef HAVE_LIBXXF86DGA2 /* cleanup DGA2 */ X11DRV_XF86DGA2_Cleanup(); #endif #ifdef HAVE_LIBXXF86VM /* cleanup XVidMode */ X11DRV_XF86VM_Cleanup(); #endif
/* FIXME: should detach all threads */ thread_detach();
/* cleanup GDI */ X11DRV_GDI_Finalize();
/* restore TSX11 locking */ wine_tsx11_lock = old_tsx11_lock; wine_tsx11_unlock = old_tsx11_unlock; #ifdef NO_REENTRANT_X11 wine_errno_location = old_errno_location; wine_h_errno_location = old_h_errno_location; #endif /* NO_REENTRANT_X11 */ RtlDeleteCriticalSection( &X11DRV_CritSection ); }
/*********************************************************************** * X11DRV thread initialisation routine */ struct x11drv_thread_data *x11drv_init_thread_data(void) { struct x11drv_thread_data *data;
if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) ))) { ERR( "could not create data\n" ); ExitProcess(1); } wine_tsx11_lock(); if (!(data->display = XOpenDisplay(NULL))) { wine_tsx11_unlock(); MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) ); ExitProcess(1); } fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */ if (synchronous) XSynchronize( data->display, True ); wine_tsx11_unlock(); data->display_fd = FILE_DupUnixHandle( ConnectionNumber(data->display), GENERIC_READ | SYNCHRONIZE, FALSE ); data->process_event_count = 0; NtCurrentTeb()->driver_data = data; return data; }
/*********************************************************************** * X11DRV initialisation routine */ BOOL WINAPI X11DRV_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { switch(reason) { case DLL_PROCESS_ATTACH: process_attach(); break; case DLL_THREAD_DETACH: thread_detach(); break; case DLL_PROCESS_DETACH: process_detach(); break; } return TRUE; }
/*********************************************************************** * GetScreenSaveActive (X11DRV.@) * * Returns the active status of the screen saver */ BOOL X11DRV_GetScreenSaveActive(void) { int timeout, temp; TSXGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp); return timeout != 0; }
/*********************************************************************** * SetScreenSaveActive (X11DRV.@) * * Activate/Deactivate the screen saver */ void X11DRV_SetScreenSaveActive(BOOL bActivate) { int timeout, interval, prefer_blanking, allow_exposures; static int last_timeout = 15 * 60;
TSXGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking, &allow_exposures); if (timeout) last_timeout = timeout;
timeout = bActivate ? last_timeout : 0; TSXSetScreenSaver(gdi_display, timeout, interval, prefer_blanking, allow_exposures); }
"leanne" leanne@thizlinux.com wrote:
I am sorry that I am newbie to Xlib, wine and xcin. I would like to ask if I should modify dlls/x11drv/x11drv_main.c, in process_attach(), continue the call of TSXOpenIM(display, NULL, NULL, NULL);
I'm not an X expert either. But at least I have a working (for me) test program created by Ivan Pascal (attached). You could use it as a start.