winex11: Added tracking of the WM_STATE window property.
[wine] / dlls / winex11.drv / x11drv_main.c
1 /*
2  * X11DRV initialization code
3  *
4  * Copyright 1998 Patrik Stridvall
5  * Copyright 2000 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #ifdef HAVE_SYS_TIME_H
31 # include <sys/time.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36 #include <X11/cursorfont.h>
37 #include <X11/Xlib.h>
38 #ifdef HAVE_XKB
39 #include <X11/XKBlib.h>
40 #endif
41 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
42 #include <X11/extensions/Xrender.h>
43 #endif
44
45 #include "windef.h"
46 #include "winbase.h"
47 #include "winreg.h"
48
49 #include "x11drv.h"
50 #include "xvidmode.h"
51 #include "xrandr.h"
52 #include "xcomposite.h"
53 #include "wine/server.h"
54 #include "wine/debug.h"
55 #include "wine/library.h"
56
57 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
58 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
59
60 static CRITICAL_SECTION X11DRV_CritSection;
61 static CRITICAL_SECTION_DEBUG critsect_debug =
62 {
63     0, 0, &X11DRV_CritSection,
64     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
65       0, 0, { (DWORD_PTR)(__FILE__ ": X11DRV_CritSection") }
66 };
67 static CRITICAL_SECTION X11DRV_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 };
68
69 Screen *screen;
70 Visual *visual;
71 unsigned int screen_width;
72 unsigned int screen_height;
73 unsigned int screen_bpp;
74 unsigned int screen_depth;
75 RECT virtual_screen_rect;
76 Window root_window;
77 int dxgrab = 0;
78 int usexvidmode = 1;
79 int usexrandr = 1;
80 int usexcomposite = 1;
81 int use_xkb = 1;
82 int use_take_focus = 1;
83 int use_primary_selection = 0;
84 int managed_mode = 1;
85 int private_color_map = 0;
86 int primary_monitor = 0;
87 int client_side_with_core = 1;
88 int client_side_with_render = 1;
89 int client_side_antialias_with_core = 1;
90 int client_side_antialias_with_render = 1;
91 int copy_default_colors = 128;
92 int alloc_system_colors = 256;
93 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
94 int xrender_error_base = 0;
95
96 static x11drv_error_callback err_callback;   /* current callback for error */
97 static Display *err_callback_display;        /* display callback is set for */
98 static void *err_callback_arg;               /* error callback argument */
99 static int err_callback_result;              /* error callback result */
100 static unsigned long err_serial;             /* serial number of first request */
101 static int (*old_error_handler)( Display *, XErrorEvent * );
102 static int use_xim = 1;
103 static char input_style[20];
104
105 #define IS_OPTION_TRUE(ch) \
106     ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
107 #define IS_OPTION_FALSE(ch) \
108     ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
109
110 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
111
112 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
113 {
114     "CLIPBOARD",
115     "COMPOUND_TEXT",
116     "MULTIPLE",
117     "SELECTION_DATA",
118     "TARGETS",
119     "TEXT",
120     "UTF8_STRING",
121     "RAW_ASCENT",
122     "RAW_DESCENT",
123     "RAW_CAP_HEIGHT",
124     "WM_PROTOCOLS",
125     "WM_DELETE_WINDOW",
126     "WM_STATE",
127     "WM_TAKE_FOCUS",
128     "KWM_DOCKWINDOW",
129     "DndProtocol",
130     "DndSelection",
131     "_MOTIF_WM_HINTS",
132     "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
133     "_NET_SYSTEM_TRAY_OPCODE",
134     "_NET_SYSTEM_TRAY_S0",
135     "_NET_WM_MOVERESIZE",
136     "_NET_WM_NAME",
137     "_NET_WM_PID",
138     "_NET_WM_PING",
139     "_NET_WM_STATE",
140     "_NET_WM_STATE_ABOVE",
141     "_NET_WM_STATE_FULLSCREEN",
142     "_NET_WM_STATE_SKIP_PAGER",
143     "_NET_WM_STATE_SKIP_TASKBAR",
144     "_NET_WM_WINDOW_TYPE",
145     "_NET_WM_WINDOW_TYPE_DIALOG",
146     "_NET_WM_WINDOW_TYPE_NORMAL",
147     "_NET_WM_WINDOW_TYPE_UTILITY",
148     "_XEMBED_INFO",
149     "XdndAware",
150     "XdndEnter",
151     "XdndPosition",
152     "XdndStatus",
153     "XdndLeave",
154     "XdndFinished",
155     "XdndDrop",
156     "XdndActionCopy",
157     "XdndActionMove",
158     "XdndActionLink",
159     "XdndActionAsk",
160     "XdndActionPrivate",
161     "XdndSelection",
162     "XdndTarget",
163     "XdndTypeList",
164     "WCF_DIB",
165     "image/gif",
166     "text/html",
167     "text/plain",
168     "text/rtf",
169     "text/richtext",
170     "text/uri-list"
171 };
172
173 /***********************************************************************
174  *              ignore_error
175  *
176  * Check if the X error is one we can ignore.
177  */
178 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
179 {
180     if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
181
182     /* ignore a number of errors on gdi display caused by creating/destroying windows */
183     if (display == gdi_display)
184     {
185         if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
186 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
187         if (xrender_error_base)  /* check for XRender errors */
188         {
189             if (event->error_code == xrender_error_base + BadPicture) return TRUE;
190         }
191 #endif
192     }
193     return FALSE;
194 }
195
196
197 /***********************************************************************
198  *              X11DRV_expect_error
199  *
200  * Setup a callback function that will be called on an X error.  The
201  * callback must return non-zero if the error is the one it expected.
202  * This function acquires the x11 lock; X11DRV_check_error must be
203  * called in all cases to release it.
204  */
205 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
206 {
207     wine_tsx11_lock();
208     err_callback         = callback;
209     err_callback_display = display;
210     err_callback_arg     = arg;
211     err_callback_result  = 0;
212     err_serial           = NextRequest(display);
213 }
214
215
216 /***********************************************************************
217  *              X11DRV_check_error
218  *
219  * Check if an expected X11 error occurred; return non-zero if yes.
220  * Also release the x11 lock obtained in X11DRV_expect_error.
221  * The caller is responsible for calling XSync first if necessary.
222  */
223 int X11DRV_check_error(void)
224 {
225     int ret;
226     err_callback = NULL;
227     ret = err_callback_result;
228     wine_tsx11_unlock();
229     return ret;
230 }
231
232
233 /***********************************************************************
234  *              error_handler
235  */
236 static int error_handler( Display *display, XErrorEvent *error_evt )
237 {
238     if (err_callback && display == err_callback_display &&
239         (long)(error_evt->serial - err_serial) >= 0)
240     {
241         if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
242         {
243             TRACE( "got expected error %d req %d\n",
244                    error_evt->error_code, error_evt->request_code );
245             return 0;
246         }
247     }
248     if (ignore_error( display, error_evt ))
249     {
250         TRACE( "got ignored error %d req %d\n",
251                error_evt->error_code, error_evt->request_code );
252         return 0;
253     }
254     if (TRACE_ON(synchronous))
255     {
256         ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
257              error_evt->serial, error_evt->request_code );
258         DebugBreak();  /* force an entry in the debugger */
259     }
260     old_error_handler( display, error_evt );
261     return 0;
262 }
263
264 /***********************************************************************
265  *              wine_tsx11_lock   (X11DRV.@)
266  */
267 void wine_tsx11_lock(void)
268 {
269     EnterCriticalSection( &X11DRV_CritSection );
270 }
271
272 /***********************************************************************
273  *              wine_tsx11_unlock   (X11DRV.@)
274  */
275 void wine_tsx11_unlock(void)
276 {
277     LeaveCriticalSection( &X11DRV_CritSection );
278 }
279
280
281 /***********************************************************************
282  *              depth_to_bpp
283  *
284  * Convert X11-reported depth to the BPP value that Windows apps expect to see.
285  */
286 unsigned int depth_to_bpp( unsigned int depth )
287 {
288     switch (depth)
289     {
290     case 1:
291     case 8:
292         return depth;
293     case 15:
294     case 16:
295         return 16;
296     case 24:
297         /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
298          * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
299          * for windowing, but gl applications can get visuals with alpha channels. So we
300          * should check the framebuffer and/or opengl formats available to find out what the
301          * framebuffer actually does
302          */
303     case 32:
304         return 32;
305     default:
306         FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
307         return depth;
308     }
309 }
310
311
312 /***********************************************************************
313  *              get_config_key
314  *
315  * Get a config key from either the app-specific or the default config
316  */
317 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
318                                     char *buffer, DWORD size )
319 {
320     if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
321     if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
322     return ERROR_FILE_NOT_FOUND;
323 }
324
325
326 /***********************************************************************
327  *              setup_options
328  *
329  * Setup the x11drv options.
330  */
331 static void setup_options(void)
332 {
333     char buffer[MAX_PATH+16];
334     HKEY hkey, appkey = 0;
335     DWORD len;
336
337     /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
338     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
339
340     /* open the app-specific key */
341
342     len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
343     if (len && len < MAX_PATH)
344     {
345         HKEY tmpkey;
346         char *p, *appname = buffer;
347         if ((p = strrchr( appname, '/' ))) appname = p + 1;
348         if ((p = strrchr( appname, '\\' ))) appname = p + 1;
349         strcat( appname, "\\X11 Driver" );
350         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
351         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
352         {
353             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
354             RegCloseKey( tmpkey );
355         }
356     }
357
358     if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
359         managed_mode = IS_OPTION_TRUE( buffer[0] );
360
361     if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
362         dxgrab = IS_OPTION_TRUE( buffer[0] );
363
364     if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
365         usexvidmode = IS_OPTION_TRUE( buffer[0] );
366
367     if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
368         usexrandr = IS_OPTION_TRUE( buffer[0] );
369
370     if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
371         use_take_focus = IS_OPTION_TRUE( buffer[0] );
372
373     if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
374         use_primary_selection = IS_OPTION_TRUE( buffer[0] );
375
376     screen_depth = 0;
377     if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
378         screen_depth = atoi(buffer);
379
380     if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
381         client_side_with_core = IS_OPTION_TRUE( buffer[0] );
382
383     if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
384         client_side_with_render = IS_OPTION_TRUE( buffer[0] );
385
386     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
387         client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
388
389     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
390         client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
391
392     if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
393         use_xim = IS_OPTION_TRUE( buffer[0] );
394
395     if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
396         private_color_map = IS_OPTION_TRUE( buffer[0] );
397
398     if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
399         primary_monitor = atoi( buffer );
400
401     if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
402         copy_default_colors = atoi(buffer);
403
404     if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
405         alloc_system_colors = atoi(buffer);
406
407     get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
408
409     if (appkey) RegCloseKey( appkey );
410     if (hkey) RegCloseKey( hkey );
411 }
412
413 #ifdef SONAME_LIBXCOMPOSITE
414
415 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
416 MAKE_FUNCPTR(XCompositeQueryExtension)
417 MAKE_FUNCPTR(XCompositeQueryVersion)
418 MAKE_FUNCPTR(XCompositeVersion)
419 MAKE_FUNCPTR(XCompositeRedirectWindow)
420 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
421 MAKE_FUNCPTR(XCompositeUnredirectWindow)
422 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
423 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
424 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
425 #undef MAKE_FUNCPTR
426
427 static int xcomp_event_base;
428 static int xcomp_error_base;
429
430 static void X11DRV_XComposite_Init(void)
431 {
432     void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
433     if (!xcomposite_handle)
434     {
435         TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
436         usexcomposite = 0;
437         return;
438     }
439
440 #define LOAD_FUNCPTR(f) \
441     if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
442         goto sym_not_found;
443     LOAD_FUNCPTR(XCompositeQueryExtension)
444     LOAD_FUNCPTR(XCompositeQueryVersion)
445     LOAD_FUNCPTR(XCompositeVersion)
446     LOAD_FUNCPTR(XCompositeRedirectWindow)
447     LOAD_FUNCPTR(XCompositeRedirectSubwindows)
448     LOAD_FUNCPTR(XCompositeUnredirectWindow)
449     LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
450     LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
451     LOAD_FUNCPTR(XCompositeNameWindowPixmap)
452 #undef LOAD_FUNCPTR
453
454     if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
455                                   &xcomp_error_base)) {
456         TRACE("XComposite extension could not be queried; disabled\n");
457         wine_dlclose(xcomposite_handle, NULL, 0);
458         xcomposite_handle = NULL;
459         usexcomposite = 0;
460         return;
461     }
462     TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
463     return;
464
465 sym_not_found:
466     TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
467     wine_dlclose(xcomposite_handle, NULL, 0);
468     xcomposite_handle = NULL;
469     usexcomposite = 0;
470 }
471 #endif /* defined(SONAME_LIBXCOMPOSITE) */
472
473
474 /***********************************************************************
475  *           X11DRV process initialisation routine
476  */
477 static BOOL process_attach(void)
478 {
479     Display *display;
480     const char *env;
481
482     setup_options();
483
484     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
485
486     /* Open display */
487
488     if (!(env = getenv("XMODIFIERS")) || !*env)  /* try to avoid the Xlib XIM locking bug */
489         if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
490
491     if (!(display = XOpenDisplay( NULL ))) return FALSE;
492
493     fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
494     screen = DefaultScreenOfDisplay( display );
495     visual = DefaultVisual( display, DefaultScreen(display) );
496     root_window = DefaultRootWindow( display );
497     gdi_display = display;
498     old_error_handler = XSetErrorHandler( error_handler );
499
500     /* Initialize screen depth */
501
502     if (screen_depth)  /* depth specified */
503     {
504         int depth_count, i;
505         int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
506         for (i = 0; i < depth_count; i++)
507             if (depth_list[i] == screen_depth) break;
508         XFree( depth_list );
509         if (i >= depth_count)
510         {
511             WARN( "invalid depth %d, using default\n", screen_depth );
512             screen_depth = 0;
513         }
514     }
515     if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
516     screen_bpp = depth_to_bpp( screen_depth );
517
518     XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
519
520     if (TRACE_ON(synchronous)) XSynchronize( display, True );
521
522     xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
523     X11DRV_Settings_Init();
524
525 #ifdef HAVE_LIBXXF86VM
526     /* initialize XVidMode */
527     X11DRV_XF86VM_Init();
528 #endif
529 #ifdef SONAME_LIBXRANDR
530     /* initialize XRandR */
531     X11DRV_XRandR_Init();
532 #endif
533 #ifdef SONAME_LIBXCOMPOSITE
534     X11DRV_XComposite_Init();
535 #endif
536
537     X11DRV_InitKeyboard( gdi_display );
538     X11DRV_InitClipboard();
539
540     return TRUE;
541 }
542
543
544 /***********************************************************************
545  *           X11DRV thread termination routine
546  */
547 static void thread_detach(void)
548 {
549     struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
550
551     if (data)
552     {
553         X11DRV_ResetSelectionOwner();
554         wine_tsx11_lock();
555         if (data->xim) XCloseIM( data->xim );
556         XCloseDisplay( data->display );
557         wine_tsx11_unlock();
558         HeapFree( GetProcessHeap(), 0, data );
559     }
560 }
561
562
563 /***********************************************************************
564  *           X11DRV process termination routine
565  */
566 static void process_detach(void)
567 {
568 #ifdef HAVE_LIBXXF86VM
569     /* cleanup XVidMode */
570     X11DRV_XF86VM_Cleanup();
571 #endif
572     if(using_client_side_fonts)
573         X11DRV_XRender_Finalize();
574
575     /* cleanup GDI */
576     X11DRV_GDI_Finalize();
577
578     DeleteCriticalSection( &X11DRV_CritSection );
579     TlsFree( thread_data_tls_index );
580 }
581
582
583 /* store the display fd into the message queue */
584 static void set_queue_display_fd( Display *display )
585 {
586     HANDLE handle;
587     int ret;
588
589     if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
590     {
591         MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
592         ExitProcess(1);
593     }
594     SERVER_START_REQ( set_queue_fd )
595     {
596         req->handle = handle;
597         ret = wine_server_call( req );
598     }
599     SERVER_END_REQ;
600     if (ret)
601     {
602         MESSAGE( "x11drv: Can't store handle for display fd\n" );
603         ExitProcess(1);
604     }
605     CloseHandle( handle );
606 }
607
608
609 /***********************************************************************
610  *           X11DRV thread initialisation routine
611  */
612 struct x11drv_thread_data *x11drv_init_thread_data(void)
613 {
614     struct x11drv_thread_data *data;
615
616     if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
617     {
618         ERR( "could not create data\n" );
619         ExitProcess(1);
620     }
621     wine_tsx11_lock();
622     if (!(data->display = XOpenDisplay(NULL)))
623     {
624         wine_tsx11_unlock();
625         MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
626         MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
627         ExitProcess(1);
628     }
629
630     fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
631
632 #ifdef HAVE_XKB
633     if (use_xkb)
634     {
635         use_xkb = XkbUseExtension( data->display, NULL, NULL );
636         if (use_xkb)
637         {
638             /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
639             /* This works around an Xlib bug where it tries to get the display lock */
640             /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
641             XkbKeysymToModifiers( data->display, 'A' );
642             XkbSetDetectableAutoRepeat( data->display, True, NULL );
643         }
644     }
645 #endif
646
647     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
648     wine_tsx11_unlock();
649
650     if (!use_xim)
651         data->xim = NULL;
652     else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
653         WARN("Input Method is not available\n");
654
655     set_queue_display_fd( data->display );
656     data->process_event_count = 0;
657     data->cursor = None;
658     data->cursor_window = None;
659     data->grab_window = None;
660     data->last_focus = 0;
661     data->selection_wnd = 0;
662     TlsSetValue( thread_data_tls_index, data );
663     X11DRV_SetCursor( NULL );
664     return data;
665 }
666
667
668 /***********************************************************************
669  *           X11DRV initialisation routine
670  */
671 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
672 {
673     BOOL ret = TRUE;
674
675     switch(reason)
676     {
677     case DLL_PROCESS_ATTACH:
678         ret = process_attach();
679         break;
680     case DLL_THREAD_DETACH:
681         thread_detach();
682         break;
683     case DLL_PROCESS_DETACH:
684         process_detach();
685         break;
686     }
687     return ret;
688 }
689
690 /***********************************************************************
691  *              GetScreenSaveActive (X11DRV.@)
692  *
693  * Returns the active status of the screen saver
694  */
695 BOOL X11DRV_GetScreenSaveActive(void)
696 {
697     int timeout, temp;
698     wine_tsx11_lock();
699     XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
700     wine_tsx11_unlock();
701     return timeout != 0;
702 }
703
704 /***********************************************************************
705  *              SetScreenSaveActive (X11DRV.@)
706  *
707  * Activate/Deactivate the screen saver
708  */
709 void X11DRV_SetScreenSaveActive(BOOL bActivate)
710 {
711     int timeout, interval, prefer_blanking, allow_exposures;
712     static int last_timeout = 15 * 60;
713
714     wine_tsx11_lock();
715     XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
716                     &allow_exposures);
717     if (timeout) last_timeout = timeout;
718
719     timeout = bActivate ? last_timeout : 0;
720     XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
721                     allow_exposures);
722     wine_tsx11_unlock();
723 }