opengl32/tests: Only use functions if they are implemented.
[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  *              depth_to_bpp
282  *
283  * Convert X11-reported depth to the BPP value that Windows apps expect to see.
284  */
285 unsigned int depth_to_bpp( unsigned int depth )
286 {
287     switch (depth)
288     {
289     case 1:
290     case 8:
291         return depth;
292     case 15:
293     case 16:
294         return 16;
295     case 24:
296         /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
297          * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
298          * for windowing, but gl applications can get visuals with alpha channels. So we
299          * should check the framebuffer and/or opengl formats available to find out what the
300          * framebuffer actually does
301          */
302     case 32:
303         return 32;
304     default:
305         FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
306         return depth;
307     }
308 }
309
310
311 /***********************************************************************
312  *              get_config_key
313  *
314  * Get a config key from either the app-specific or the default config
315  */
316 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
317                                     char *buffer, DWORD size )
318 {
319     if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
320     if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
321     return ERROR_FILE_NOT_FOUND;
322 }
323
324
325 /***********************************************************************
326  *              setup_options
327  *
328  * Setup the x11drv options.
329  */
330 static void setup_options(void)
331 {
332     char buffer[MAX_PATH+16];
333     HKEY hkey, appkey = 0;
334     DWORD len;
335
336     /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
337     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
338
339     /* open the app-specific key */
340
341     len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
342     if (len && len < MAX_PATH)
343     {
344         HKEY tmpkey;
345         char *p, *appname = buffer;
346         if ((p = strrchr( appname, '/' ))) appname = p + 1;
347         if ((p = strrchr( appname, '\\' ))) appname = p + 1;
348         strcat( appname, "\\X11 Driver" );
349         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
350         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
351         {
352             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
353             RegCloseKey( tmpkey );
354         }
355     }
356
357     if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
358         managed_mode = IS_OPTION_TRUE( buffer[0] );
359
360     if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
361         dxgrab = IS_OPTION_TRUE( buffer[0] );
362
363     if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
364         usexvidmode = IS_OPTION_TRUE( buffer[0] );
365
366     if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
367         usexrandr = IS_OPTION_TRUE( buffer[0] );
368
369     if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
370         use_take_focus = IS_OPTION_TRUE( buffer[0] );
371
372     if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
373         use_primary_selection = IS_OPTION_TRUE( buffer[0] );
374
375     screen_depth = 0;
376     if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
377         screen_depth = atoi(buffer);
378
379     if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
380         client_side_with_core = IS_OPTION_TRUE( buffer[0] );
381
382     if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
383         client_side_with_render = IS_OPTION_TRUE( buffer[0] );
384
385     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
386         client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
387
388     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
389         client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
390
391     if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
392         use_xim = IS_OPTION_TRUE( buffer[0] );
393
394     if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
395         private_color_map = IS_OPTION_TRUE( buffer[0] );
396
397     if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
398         primary_monitor = atoi( buffer );
399
400     if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
401         copy_default_colors = atoi(buffer);
402
403     if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
404         alloc_system_colors = atoi(buffer);
405
406     get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
407
408     if (appkey) RegCloseKey( appkey );
409     if (hkey) RegCloseKey( hkey );
410 }
411
412 #ifdef SONAME_LIBXCOMPOSITE
413
414 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
415 MAKE_FUNCPTR(XCompositeQueryExtension)
416 MAKE_FUNCPTR(XCompositeQueryVersion)
417 MAKE_FUNCPTR(XCompositeVersion)
418 MAKE_FUNCPTR(XCompositeRedirectWindow)
419 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
420 MAKE_FUNCPTR(XCompositeUnredirectWindow)
421 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
422 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
423 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
424 #undef MAKE_FUNCPTR
425
426 static int xcomp_event_base;
427 static int xcomp_error_base;
428
429 static void X11DRV_XComposite_Init(void)
430 {
431     void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
432     if (!xcomposite_handle)
433     {
434         TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
435         usexcomposite = 0;
436         return;
437     }
438
439 #define LOAD_FUNCPTR(f) \
440     if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
441         goto sym_not_found;
442     LOAD_FUNCPTR(XCompositeQueryExtension)
443     LOAD_FUNCPTR(XCompositeQueryVersion)
444     LOAD_FUNCPTR(XCompositeVersion)
445     LOAD_FUNCPTR(XCompositeRedirectWindow)
446     LOAD_FUNCPTR(XCompositeRedirectSubwindows)
447     LOAD_FUNCPTR(XCompositeUnredirectWindow)
448     LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
449     LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
450     LOAD_FUNCPTR(XCompositeNameWindowPixmap)
451 #undef LOAD_FUNCPTR
452
453     if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
454                                   &xcomp_error_base)) {
455         TRACE("XComposite extension could not be queried; disabled\n");
456         wine_dlclose(xcomposite_handle, NULL, 0);
457         xcomposite_handle = NULL;
458         usexcomposite = 0;
459         return;
460     }
461     TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
462     return;
463
464 sym_not_found:
465     TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
466     wine_dlclose(xcomposite_handle, NULL, 0);
467     xcomposite_handle = NULL;
468     usexcomposite = 0;
469 }
470 #endif /* defined(SONAME_LIBXCOMPOSITE) */
471
472
473 /***********************************************************************
474  *           X11DRV process initialisation routine
475  */
476 static BOOL process_attach(void)
477 {
478     Display *display;
479     XVisualInfo *desktop_vi = NULL;
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
517     /* If OpenGL is available, change the default visual, etc as necessary */
518     if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
519     {
520         visual       = desktop_vi->visual;
521         screen       = ScreenOfDisplay(display, desktop_vi->screen);
522         screen_depth = desktop_vi->depth;
523         XFree(desktop_vi);
524     }
525     screen_bpp = depth_to_bpp( screen_depth );
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     xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
532     X11DRV_Settings_Init();
533
534 #ifdef HAVE_LIBXXF86VM
535     /* initialize XVidMode */
536     X11DRV_XF86VM_Init();
537 #endif
538 #ifdef SONAME_LIBXRANDR
539     /* initialize XRandR */
540     X11DRV_XRandR_Init();
541 #endif
542 #ifdef SONAME_LIBXCOMPOSITE
543     X11DRV_XComposite_Init();
544 #endif
545
546     X11DRV_InitKeyboard( gdi_display );
547     X11DRV_InitClipboard();
548
549     return TRUE;
550 }
551
552
553 /***********************************************************************
554  *           X11DRV thread termination routine
555  */
556 static void thread_detach(void)
557 {
558     struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
559
560     if (data)
561     {
562         X11DRV_ResetSelectionOwner();
563         wine_tsx11_lock();
564         if (data->xim) XCloseIM( data->xim );
565         XCloseDisplay( data->display );
566         wine_tsx11_unlock();
567         HeapFree( GetProcessHeap(), 0, data );
568     }
569 }
570
571
572 /***********************************************************************
573  *           X11DRV process termination routine
574  */
575 static void process_detach(void)
576 {
577 #ifdef HAVE_LIBXXF86VM
578     /* cleanup XVidMode */
579     X11DRV_XF86VM_Cleanup();
580 #endif
581     if(using_client_side_fonts)
582         X11DRV_XRender_Finalize();
583
584     /* cleanup GDI */
585     X11DRV_GDI_Finalize();
586
587     DeleteCriticalSection( &X11DRV_CritSection );
588     TlsFree( thread_data_tls_index );
589 }
590
591
592 /* store the display fd into the message queue */
593 static void set_queue_display_fd( Display *display )
594 {
595     HANDLE handle;
596     int ret;
597
598     if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
599     {
600         MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
601         ExitProcess(1);
602     }
603     SERVER_START_REQ( set_queue_fd )
604     {
605         req->handle = handle;
606         ret = wine_server_call( req );
607     }
608     SERVER_END_REQ;
609     if (ret)
610     {
611         MESSAGE( "x11drv: Can't store handle for display fd\n" );
612         ExitProcess(1);
613     }
614     CloseHandle( handle );
615 }
616
617
618 /***********************************************************************
619  *           X11DRV thread initialisation routine
620  */
621 struct x11drv_thread_data *x11drv_init_thread_data(void)
622 {
623     struct x11drv_thread_data *data;
624
625     if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
626     {
627         ERR( "could not create data\n" );
628         ExitProcess(1);
629     }
630     wine_tsx11_lock();
631     if (!(data->display = XOpenDisplay(NULL)))
632     {
633         wine_tsx11_unlock();
634         MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
635         MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
636         ExitProcess(1);
637     }
638
639     fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
640
641 #ifdef HAVE_XKB
642     if (use_xkb)
643     {
644         use_xkb = XkbUseExtension( data->display, NULL, NULL );
645         if (use_xkb)
646         {
647             /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
648             /* This works around an Xlib bug where it tries to get the display lock */
649             /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
650             XkbKeysymToModifiers( data->display, 'A' );
651             XkbSetDetectableAutoRepeat( data->display, True, NULL );
652         }
653     }
654 #endif
655
656     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
657     wine_tsx11_unlock();
658
659     if (!use_xim)
660         data->xim = NULL;
661     else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
662         WARN("Input Method is not available\n");
663
664     set_queue_display_fd( data->display );
665     data->process_event_count = 0;
666     data->cursor = None;
667     data->cursor_window = None;
668     data->grab_window = None;
669     data->last_focus = 0;
670     data->selection_wnd = 0;
671     TlsSetValue( thread_data_tls_index, data );
672     return data;
673 }
674
675
676 /***********************************************************************
677  *           X11DRV initialisation routine
678  */
679 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
680 {
681     BOOL ret = TRUE;
682
683     switch(reason)
684     {
685     case DLL_PROCESS_ATTACH:
686         ret = process_attach();
687         break;
688     case DLL_THREAD_DETACH:
689         thread_detach();
690         break;
691     case DLL_PROCESS_DETACH:
692         process_detach();
693         break;
694     }
695     return ret;
696 }
697
698 /***********************************************************************
699  *              GetScreenSaveActive (X11DRV.@)
700  *
701  * Returns the active status of the screen saver
702  */
703 BOOL X11DRV_GetScreenSaveActive(void)
704 {
705     int timeout, temp;
706     wine_tsx11_lock();
707     XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
708     wine_tsx11_unlock();
709     return timeout != 0;
710 }
711
712 /***********************************************************************
713  *              SetScreenSaveActive (X11DRV.@)
714  *
715  * Activate/Deactivate the screen saver
716  */
717 void X11DRV_SetScreenSaveActive(BOOL bActivate)
718 {
719     int timeout, interval, prefer_blanking, allow_exposures;
720     static int last_timeout = 15 * 60;
721
722     wine_tsx11_lock();
723     XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
724                     &allow_exposures);
725     if (timeout) last_timeout = timeout;
726
727     timeout = bActivate ? last_timeout : 0;
728     XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
729                     allow_exposures);
730     wine_tsx11_unlock();
731 }