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