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