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