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