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