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