dinput: Silence incorrect warning and move it to a valid place.
[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_TAKE_FOCUS",
127     "KWM_DOCKWINDOW",
128     "DndProtocol",
129     "DndSelection",
130     "_MOTIF_WM_HINTS",
131     "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
132     "_NET_SYSTEM_TRAY_OPCODE",
133     "_NET_SYSTEM_TRAY_S0",
134     "_NET_WM_MOVERESIZE",
135     "_NET_WM_NAME",
136     "_NET_WM_PID",
137     "_NET_WM_PING",
138     "_NET_WM_STATE",
139     "_NET_WM_STATE_ABOVE",
140     "_NET_WM_STATE_FULLSCREEN",
141     "_NET_WM_STATE_SKIP_PAGER",
142     "_NET_WM_STATE_SKIP_TASKBAR",
143     "_NET_WM_WINDOW_TYPE",
144     "_NET_WM_WINDOW_TYPE_DIALOG",
145     "_NET_WM_WINDOW_TYPE_NORMAL",
146     "_NET_WM_WINDOW_TYPE_UTILITY",
147     "_XEMBED_INFO",
148     "XdndAware",
149     "XdndEnter",
150     "XdndPosition",
151     "XdndStatus",
152     "XdndLeave",
153     "XdndFinished",
154     "XdndDrop",
155     "XdndActionCopy",
156     "XdndActionMove",
157     "XdndActionLink",
158     "XdndActionAsk",
159     "XdndActionPrivate",
160     "XdndSelection",
161     "XdndTarget",
162     "XdndTypeList",
163     "WCF_DIB",
164     "image/gif",
165     "text/html",
166     "text/plain",
167     "text/rtf",
168     "text/richtext",
169     "text/uri-list"
170 };
171
172 /***********************************************************************
173  *              ignore_error
174  *
175  * Check if the X error is one we can ignore.
176  */
177 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
178 {
179     if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
180
181     /* ignore a number of errors on gdi display caused by creating/destroying windows */
182     if (display == gdi_display)
183     {
184         if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
185 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
186         if (xrender_error_base)  /* check for XRender errors */
187         {
188             if (event->error_code == xrender_error_base + BadPicture) return TRUE;
189         }
190 #endif
191     }
192     return FALSE;
193 }
194
195
196 /***********************************************************************
197  *              X11DRV_expect_error
198  *
199  * Setup a callback function that will be called on an X error.  The
200  * callback must return non-zero if the error is the one it expected.
201  * This function acquires the x11 lock; X11DRV_check_error must be
202  * called in all cases to release it.
203  */
204 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
205 {
206     wine_tsx11_lock();
207     err_callback         = callback;
208     err_callback_display = display;
209     err_callback_arg     = arg;
210     err_callback_result  = 0;
211     err_serial           = NextRequest(display);
212 }
213
214
215 /***********************************************************************
216  *              X11DRV_check_error
217  *
218  * Check if an expected X11 error occurred; return non-zero if yes.
219  * Also release the x11 lock obtained in X11DRV_expect_error.
220  * The caller is responsible for calling XSync first if necessary.
221  */
222 int X11DRV_check_error(void)
223 {
224     int ret;
225     err_callback = NULL;
226     ret = err_callback_result;
227     wine_tsx11_unlock();
228     return ret;
229 }
230
231
232 /***********************************************************************
233  *              error_handler
234  */
235 static int error_handler( Display *display, XErrorEvent *error_evt )
236 {
237     if (err_callback && display == err_callback_display &&
238         (long)(error_evt->serial - err_serial) >= 0)
239     {
240         if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
241         {
242             TRACE( "got expected error %d req %d\n",
243                    error_evt->error_code, error_evt->request_code );
244             return 0;
245         }
246     }
247     if (ignore_error( display, error_evt ))
248     {
249         TRACE( "got ignored error %d req %d\n",
250                error_evt->error_code, error_evt->request_code );
251         return 0;
252     }
253     if (TRACE_ON(synchronous))
254     {
255         ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
256              error_evt->serial, error_evt->request_code );
257         DebugBreak();  /* force an entry in the debugger */
258     }
259     old_error_handler( display, error_evt );
260     return 0;
261 }
262
263 /***********************************************************************
264  *              wine_tsx11_lock   (X11DRV.@)
265  */
266 void wine_tsx11_lock(void)
267 {
268     EnterCriticalSection( &X11DRV_CritSection );
269 }
270
271 /***********************************************************************
272  *              wine_tsx11_unlock   (X11DRV.@)
273  */
274 void wine_tsx11_unlock(void)
275 {
276     LeaveCriticalSection( &X11DRV_CritSection );
277 }
278
279
280 /***********************************************************************
281  *              get_config_key
282  *
283  * Get a config key from either the app-specific or the default config
284  */
285 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
286                                     char *buffer, DWORD size )
287 {
288     if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
289     if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
290     return ERROR_FILE_NOT_FOUND;
291 }
292
293
294 /***********************************************************************
295  *              setup_options
296  *
297  * Setup the x11drv options.
298  */
299 static void setup_options(void)
300 {
301     char buffer[MAX_PATH+16];
302     HKEY hkey, appkey = 0;
303     DWORD len;
304
305     /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
306     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
307
308     /* open the app-specific key */
309
310     len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
311     if (len && len < MAX_PATH)
312     {
313         HKEY tmpkey;
314         char *p, *appname = buffer;
315         if ((p = strrchr( appname, '/' ))) appname = p + 1;
316         if ((p = strrchr( appname, '\\' ))) appname = p + 1;
317         strcat( appname, "\\X11 Driver" );
318         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
319         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
320         {
321             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
322             RegCloseKey( tmpkey );
323         }
324     }
325
326     if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
327         managed_mode = IS_OPTION_TRUE( buffer[0] );
328
329     if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
330         dxgrab = IS_OPTION_TRUE( buffer[0] );
331
332     if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
333         usexvidmode = IS_OPTION_TRUE( buffer[0] );
334
335     if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
336         usexrandr = IS_OPTION_TRUE( buffer[0] );
337
338     if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
339         use_take_focus = IS_OPTION_TRUE( buffer[0] );
340
341     if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
342         use_primary_selection = IS_OPTION_TRUE( buffer[0] );
343
344     screen_depth = 0;
345     if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
346         screen_depth = atoi(buffer);
347
348     if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
349         client_side_with_core = IS_OPTION_TRUE( buffer[0] );
350
351     if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
352         client_side_with_render = IS_OPTION_TRUE( buffer[0] );
353
354     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
355         client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
356
357     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
358         client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
359
360     if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
361         use_xim = IS_OPTION_TRUE( buffer[0] );
362
363     if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
364         private_color_map = IS_OPTION_TRUE( buffer[0] );
365
366     if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
367         primary_monitor = atoi( buffer );
368
369     if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
370         copy_default_colors = atoi(buffer);
371
372     if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
373         alloc_system_colors = atoi(buffer);
374
375     get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
376
377     if (appkey) RegCloseKey( appkey );
378     if (hkey) RegCloseKey( hkey );
379 }
380
381 #ifdef SONAME_LIBXCOMPOSITE
382
383 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
384 MAKE_FUNCPTR(XCompositeQueryExtension)
385 MAKE_FUNCPTR(XCompositeQueryVersion)
386 MAKE_FUNCPTR(XCompositeVersion)
387 MAKE_FUNCPTR(XCompositeRedirectWindow)
388 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
389 MAKE_FUNCPTR(XCompositeUnredirectWindow)
390 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
391 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
392 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
393 #undef MAKE_FUNCPTR
394
395 static int xcomp_event_base;
396 static int xcomp_error_base;
397
398 static void X11DRV_XComposite_Init(void)
399 {
400     void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
401     if (!xcomposite_handle)
402     {
403         TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
404         usexcomposite = 0;
405         return;
406     }
407
408 #define LOAD_FUNCPTR(f) \
409     if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
410         goto sym_not_found;
411     LOAD_FUNCPTR(XCompositeQueryExtension)
412     LOAD_FUNCPTR(XCompositeQueryVersion)
413     LOAD_FUNCPTR(XCompositeVersion)
414     LOAD_FUNCPTR(XCompositeRedirectWindow)
415     LOAD_FUNCPTR(XCompositeRedirectSubwindows)
416     LOAD_FUNCPTR(XCompositeUnredirectWindow)
417     LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
418     LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
419     LOAD_FUNCPTR(XCompositeNameWindowPixmap)
420 #undef LOAD_FUNCPTR
421
422     if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
423                                   &xcomp_error_base)) {
424         TRACE("XComposite extension could not be queried; disabled\n");
425         wine_dlclose(xcomposite_handle, NULL, 0);
426         xcomposite_handle = NULL;
427         usexcomposite = 0;
428         return;
429     }
430     TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
431     return;
432
433 sym_not_found:
434     TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
435     wine_dlclose(xcomposite_handle, NULL, 0);
436     xcomposite_handle = NULL;
437     usexcomposite = 0;
438 }
439 #endif /* defined(SONAME_LIBXCOMPOSITE) */
440
441
442 /***********************************************************************
443  *           X11DRV process initialisation routine
444  */
445 static BOOL process_attach(void)
446 {
447     Display *display;
448     XVisualInfo *desktop_vi = NULL;
449     const char *env;
450
451     setup_options();
452
453     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
454
455     /* Open display */
456
457     if (!(env = getenv("XMODIFIERS")) || !*env)  /* try to avoid the Xlib XIM locking bug */
458         if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
459
460     if (!(display = XOpenDisplay( NULL ))) return FALSE;
461
462     fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
463     screen = DefaultScreenOfDisplay( display );
464     visual = DefaultVisual( display, DefaultScreen(display) );
465     root_window = DefaultRootWindow( display );
466     gdi_display = display;
467     old_error_handler = XSetErrorHandler( error_handler );
468
469     /* Initialize screen depth */
470
471     if (screen_depth)  /* depth specified */
472     {
473         int depth_count, i;
474         int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
475         for (i = 0; i < depth_count; i++)
476             if (depth_list[i] == screen_depth) break;
477         XFree( depth_list );
478         if (i >= depth_count)
479         {
480             WARN( "invalid depth %d, using default\n", screen_depth );
481             screen_depth = 0;
482         }
483     }
484     if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
485
486     /* If OpenGL is available, change the default visual, etc as necessary */
487     if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
488     {
489         visual       = desktop_vi->visual;
490         screen       = ScreenOfDisplay(display, desktop_vi->screen);
491         screen_depth = desktop_vi->depth;
492         XFree(desktop_vi);
493     }
494
495     switch(screen_depth) {
496         case 8:
497             screen_bpp = 8;
498             break;
499
500         case 15:
501             /* Out tests suggest that windows does not support 15 bpp color depth.
502              * X11 does, what should we do with these situations?
503              */
504             FIXME("The X server is running at 15 bpp color depth\n");
505             screen_bpp = 15;
506             break;
507
508         case 16:
509             screen_bpp = 16;
510             break;
511
512         case 24:
513             /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
514              * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
515              * for windowing, but gl applications can get visuals with alpha channels. So we
516              * should check the framebuffer and/or opengl formats available to find out what the
517              * framebuffer actually does
518              */
519             screen_bpp = 32;
520             break;
521
522         default:
523             FIXME("Unexpected X11 depth %d bpp, what to report to app?\n", screen_depth);
524             screen_bpp = screen_depth;
525     }
526
527     XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
528
529     if (TRACE_ON(synchronous)) XSynchronize( display, True );
530
531     screen_width  = WidthOfScreen( screen );
532     screen_height = HeightOfScreen( screen );
533
534     xinerama_init();
535     X11DRV_Settings_Init();
536
537 #ifdef HAVE_LIBXXF86VM
538     /* initialize XVidMode */
539     X11DRV_XF86VM_Init();
540 #endif
541 #ifdef SONAME_LIBXRANDR
542     /* initialize XRandR */
543     X11DRV_XRandR_Init();
544 #endif
545 #ifdef SONAME_LIBXCOMPOSITE
546     X11DRV_XComposite_Init();
547 #endif
548
549     X11DRV_ClipCursor( NULL );
550     X11DRV_InitKeyboard();
551     X11DRV_InitClipboard();
552
553     return TRUE;
554 }
555
556
557 /***********************************************************************
558  *           X11DRV thread termination routine
559  */
560 static void thread_detach(void)
561 {
562     struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
563
564     if (data)
565     {
566         X11DRV_ResetSelectionOwner();
567         wine_tsx11_lock();
568         if (data->xim) XCloseIM( data->xim );
569         XCloseDisplay( data->display );
570         wine_tsx11_unlock();
571         HeapFree( GetProcessHeap(), 0, data );
572     }
573 }
574
575
576 /***********************************************************************
577  *           X11DRV process termination routine
578  */
579 static void process_detach(void)
580 {
581 #ifdef HAVE_LIBXXF86VM
582     /* cleanup XVidMode */
583     X11DRV_XF86VM_Cleanup();
584 #endif
585     if(using_client_side_fonts)
586         X11DRV_XRender_Finalize();
587
588     /* cleanup GDI */
589     X11DRV_GDI_Finalize();
590
591     DeleteCriticalSection( &X11DRV_CritSection );
592     TlsFree( thread_data_tls_index );
593 }
594
595
596 /* store the display fd into the message queue */
597 static void set_queue_display_fd( Display *display )
598 {
599     HANDLE handle;
600     int ret;
601
602     if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
603     {
604         MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
605         ExitProcess(1);
606     }
607     SERVER_START_REQ( set_queue_fd )
608     {
609         req->handle = handle;
610         ret = wine_server_call( req );
611     }
612     SERVER_END_REQ;
613     if (ret)
614     {
615         MESSAGE( "x11drv: Can't store handle for display fd\n" );
616         ExitProcess(1);
617     }
618     CloseHandle( handle );
619 }
620
621
622 /***********************************************************************
623  *           X11DRV thread initialisation routine
624  */
625 struct x11drv_thread_data *x11drv_init_thread_data(void)
626 {
627     struct x11drv_thread_data *data;
628
629     if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
630     {
631         ERR( "could not create data\n" );
632         ExitProcess(1);
633     }
634     wine_tsx11_lock();
635     if (!(data->display = XOpenDisplay(NULL)))
636     {
637         wine_tsx11_unlock();
638         MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
639         MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
640         ExitProcess(1);
641     }
642
643     fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
644
645 #ifdef HAVE_XKB
646     if (use_xkb)
647     {
648         use_xkb = XkbUseExtension( data->display, NULL, NULL );
649         if (use_xkb)
650         {
651             /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
652             /* This works around an Xlib bug where it tries to get the display lock */
653             /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
654             XkbKeysymToModifiers( data->display, 'A' );
655             XkbSetDetectableAutoRepeat( data->display, True, NULL );
656         }
657     }
658 #endif
659
660     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
661     wine_tsx11_unlock();
662
663     if (!use_xim)
664         data->xim = NULL;
665     else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
666         WARN("Input Method is not available\n");
667
668     set_queue_display_fd( data->display );
669     data->process_event_count = 0;
670     data->cursor = None;
671     data->cursor_window = None;
672     data->grab_window = None;
673     data->last_focus = 0;
674     data->selection_wnd = 0;
675     TlsSetValue( thread_data_tls_index, data );
676     return data;
677 }
678
679
680 /***********************************************************************
681  *           X11DRV initialisation routine
682  */
683 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
684 {
685     BOOL ret = TRUE;
686
687     switch(reason)
688     {
689     case DLL_PROCESS_ATTACH:
690         ret = process_attach();
691         break;
692     case DLL_THREAD_DETACH:
693         thread_detach();
694         break;
695     case DLL_PROCESS_DETACH:
696         process_detach();
697         break;
698     }
699     return ret;
700 }
701
702 /***********************************************************************
703  *              GetScreenSaveActive (X11DRV.@)
704  *
705  * Returns the active status of the screen saver
706  */
707 BOOL X11DRV_GetScreenSaveActive(void)
708 {
709     int timeout, temp;
710     wine_tsx11_lock();
711     XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
712     wine_tsx11_unlock();
713     return timeout != 0;
714 }
715
716 /***********************************************************************
717  *              SetScreenSaveActive (X11DRV.@)
718  *
719  * Activate/Deactivate the screen saver
720  */
721 void X11DRV_SetScreenSaveActive(BOOL bActivate)
722 {
723     int timeout, interval, prefer_blanking, allow_exposures;
724     static int last_timeout = 15 * 60;
725
726     wine_tsx11_lock();
727     XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
728                     &allow_exposures);
729     if (timeout) last_timeout = timeout;
730
731     timeout = bActivate ? last_timeout : 0;
732     XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
733                     allow_exposures);
734     wine_tsx11_unlock();
735 }