dmsynth: Dump data passed to Download method.
[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 "xcomposite.h"
51 #include "wine/server.h"
52 #include "wine/debug.h"
53 #include "wine/library.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
56 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
57 WINE_DECLARE_DEBUG_CHANNEL(winediag);
58
59 XVisualInfo default_visual = { 0 };
60 XVisualInfo argb_visual = { 0 };
61 Colormap default_colormap = None;
62 XPixmapFormatValues **pixmap_formats;
63 unsigned int screen_width;
64 unsigned int screen_height;
65 unsigned int screen_bpp;
66 RECT virtual_screen_rect;
67 Window root_window;
68 int usexvidmode = 1;
69 int usexrandr = 1;
70 int usexcomposite = 1;
71 int use_xkb = 1;
72 int use_take_focus = 1;
73 int use_primary_selection = 0;
74 int use_system_cursors = 1;
75 int show_systray = 1;
76 int grab_pointer = 1;
77 int grab_fullscreen = 0;
78 int managed_mode = 1;
79 int decorated_mode = 1;
80 int private_color_map = 0;
81 int primary_monitor = 0;
82 int client_side_graphics = 1;
83 int client_side_with_render = 1;
84 int copy_default_colors = 128;
85 int alloc_system_colors = 256;
86 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
87 int xrender_error_base = 0;
88 HMODULE x11drv_module = 0;
89
90 static x11drv_error_callback err_callback;   /* current callback for error */
91 static Display *err_callback_display;        /* display callback is set for */
92 static void *err_callback_arg;               /* error callback argument */
93 static int err_callback_result;              /* error callback result */
94 static unsigned long err_serial;             /* serial number of first request */
95 static int (*old_error_handler)( Display *, XErrorEvent * );
96 static int use_xim = 1;
97 static char input_style[20];
98
99 #define IS_OPTION_TRUE(ch) \
100     ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
101 #define IS_OPTION_FALSE(ch) \
102     ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
103
104 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
105
106 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
107 {
108     "CLIPBOARD",
109     "COMPOUND_TEXT",
110     "INCR",
111     "MANAGER",
112     "MULTIPLE",
113     "SELECTION_DATA",
114     "TARGETS",
115     "TEXT",
116     "UTF8_STRING",
117     "RAW_ASCENT",
118     "RAW_DESCENT",
119     "RAW_CAP_HEIGHT",
120     "Rel X",
121     "Rel Y",
122     "WM_PROTOCOLS",
123     "WM_DELETE_WINDOW",
124     "WM_STATE",
125     "WM_TAKE_FOCUS",
126     "DndProtocol",
127     "DndSelection",
128     "_ICC_PROFILE",
129     "_MOTIF_WM_HINTS",
130     "_NET_STARTUP_INFO_BEGIN",
131     "_NET_STARTUP_INFO",
132     "_NET_SUPPORTED",
133     "_NET_SYSTEM_TRAY_OPCODE",
134     "_NET_SYSTEM_TRAY_S0",
135     "_NET_SYSTEM_TRAY_VISUAL",
136     "_NET_WM_ICON",
137     "_NET_WM_MOVERESIZE",
138     "_NET_WM_NAME",
139     "_NET_WM_PID",
140     "_NET_WM_PING",
141     "_NET_WM_STATE",
142     "_NET_WM_STATE_ABOVE",
143     "_NET_WM_STATE_FULLSCREEN",
144     "_NET_WM_STATE_MAXIMIZED_HORZ",
145     "_NET_WM_STATE_MAXIMIZED_VERT",
146     "_NET_WM_STATE_SKIP_PAGER",
147     "_NET_WM_STATE_SKIP_TASKBAR",
148     "_NET_WM_USER_TIME",
149     "_NET_WM_USER_TIME_WINDOW",
150     "_NET_WM_WINDOW_OPACITY",
151     "_NET_WM_WINDOW_TYPE",
152     "_NET_WM_WINDOW_TYPE_DIALOG",
153     "_NET_WM_WINDOW_TYPE_NORMAL",
154     "_NET_WM_WINDOW_TYPE_UTILITY",
155     "_NET_WORKAREA",
156     "_XEMBED",
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_BITMAP",
175     "WCF_DIB",
176     "WCF_DIBV5",
177     "WCF_DIF",
178     "WCF_DSPBITMAP",
179     "WCF_DSPENHMETAFILE",
180     "WCF_DSPMETAFILEPICT",
181     "WCF_DSPTEXT",
182     "WCF_ENHMETAFILE",
183     "WCF_HDROP",
184     "WCF_LOCALE",
185     "WCF_METAFILEPICT",
186     "WCF_OEMTEXT",
187     "WCF_OWNERDISPLAY",
188     "WCF_PALETTE",
189     "WCF_PENDATA",
190     "WCF_RIFF",
191     "WCF_SYLK",
192     "WCF_TIFF",
193     "WCF_WAVE",
194     "image/bmp",
195     "image/gif",
196     "image/jpeg",
197     "image/png",
198     "text/html",
199     "text/plain",
200     "text/rtf",
201     "text/richtext",
202     "text/uri-list"
203 };
204
205 /***********************************************************************
206  *              ignore_error
207  *
208  * Check if the X error is one we can ignore.
209  */
210 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
211 {
212     if ((event->request_code == X_SetInputFocus || event->request_code == X_ChangeWindowAttributes) &&
213         (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
214
215     /* ignore a number of errors on gdi display caused by creating/destroying windows */
216     if (display == gdi_display)
217     {
218         if (event->error_code == BadDrawable ||
219             event->error_code == BadGC ||
220             event->error_code == BadWindow)
221             return TRUE;
222 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
223         if (xrender_error_base)  /* check for XRender errors */
224         {
225             if (event->error_code == xrender_error_base + BadPicture) return TRUE;
226         }
227 #endif
228     }
229     return FALSE;
230 }
231
232
233 /***********************************************************************
234  *              X11DRV_expect_error
235  *
236  * Setup a callback function that will be called on an X error.  The
237  * callback must return non-zero if the error is the one it expected.
238  */
239 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
240 {
241     err_callback         = callback;
242     err_callback_display = display;
243     err_callback_arg     = arg;
244     err_callback_result  = 0;
245     err_serial           = NextRequest(display);
246 }
247
248
249 /***********************************************************************
250  *              X11DRV_check_error
251  *
252  * Check if an expected X11 error occurred; return non-zero if yes.
253  * The caller is responsible for calling XSync first if necessary.
254  */
255 int X11DRV_check_error(void)
256 {
257     err_callback = NULL;
258     return err_callback_result;
259 }
260
261
262 /***********************************************************************
263  *              error_handler
264  */
265 static int error_handler( Display *display, XErrorEvent *error_evt )
266 {
267     if (err_callback && display == err_callback_display &&
268         (long)(error_evt->serial - err_serial) >= 0)
269     {
270         if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
271         {
272             TRACE( "got expected error %d req %d\n",
273                    error_evt->error_code, error_evt->request_code );
274             return 0;
275         }
276     }
277     if (ignore_error( display, error_evt ))
278     {
279         TRACE( "got ignored error %d req %d\n",
280                error_evt->error_code, error_evt->request_code );
281         return 0;
282     }
283     if (TRACE_ON(synchronous))
284     {
285         ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
286              error_evt->serial, error_evt->request_code );
287         DebugBreak();  /* force an entry in the debugger */
288     }
289     old_error_handler( display, error_evt );
290     return 0;
291 }
292
293 /***********************************************************************
294  *              init_pixmap_formats
295  */
296 static void init_pixmap_formats( Display *display )
297 {
298     int i, count, max = 32;
299     XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
300
301     for (i = 0; i < count; i++)
302     {
303         TRACE( "depth %u, bpp %u, pad %u\n",
304                formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
305         if (formats[i].depth > max) max = formats[i].depth;
306     }
307     pixmap_formats = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pixmap_formats) * (max + 1) );
308     for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
309 }
310
311
312 /***********************************************************************
313  *              get_config_key
314  *
315  * Get a config key from either the app-specific or the default config
316  */
317 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
318                                     char *buffer, DWORD size )
319 {
320     if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
321     if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
322     return ERROR_FILE_NOT_FOUND;
323 }
324
325
326 /***********************************************************************
327  *              setup_options
328  *
329  * Setup the x11drv options.
330  */
331 static void setup_options(void)
332 {
333     char buffer[MAX_PATH+16];
334     HKEY hkey, appkey = 0;
335     DWORD len;
336
337     /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
338     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
339
340     /* open the app-specific key */
341
342     len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
343     if (len && len < MAX_PATH)
344     {
345         HKEY tmpkey;
346         char *p, *appname = buffer;
347         if ((p = strrchr( appname, '/' ))) appname = p + 1;
348         if ((p = strrchr( appname, '\\' ))) appname = p + 1;
349         strcat( appname, "\\X11 Driver" );
350         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
351         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
352         {
353             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
354             RegCloseKey( tmpkey );
355         }
356     }
357
358     if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
359         managed_mode = IS_OPTION_TRUE( buffer[0] );
360
361     if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
362         decorated_mode = IS_OPTION_TRUE( buffer[0] );
363
364     if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
365         usexvidmode = IS_OPTION_TRUE( buffer[0] );
366
367     if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
368         usexrandr = IS_OPTION_TRUE( buffer[0] );
369
370     if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
371         use_take_focus = IS_OPTION_TRUE( buffer[0] );
372
373     if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
374         use_primary_selection = IS_OPTION_TRUE( buffer[0] );
375
376     if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
377         use_system_cursors = IS_OPTION_TRUE( buffer[0] );
378
379     if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
380         show_systray = IS_OPTION_TRUE( buffer[0] );
381
382     if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
383         grab_pointer = IS_OPTION_TRUE( buffer[0] );
384
385     if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
386         grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
387
388     if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
389         default_visual.depth = atoi(buffer);
390
391     if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
392         client_side_graphics = IS_OPTION_TRUE( buffer[0] );
393
394     if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
395         client_side_with_render = IS_OPTION_TRUE( buffer[0] );
396
397     if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
398         use_xim = IS_OPTION_TRUE( buffer[0] );
399
400     if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
401         private_color_map = IS_OPTION_TRUE( buffer[0] );
402
403     if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
404         primary_monitor = atoi( buffer );
405
406     if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
407         copy_default_colors = atoi(buffer);
408
409     if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
410         alloc_system_colors = atoi(buffer);
411
412     get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
413
414     if (appkey) RegCloseKey( appkey );
415     if (hkey) RegCloseKey( hkey );
416 }
417
418 #ifdef SONAME_LIBXCOMPOSITE
419
420 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
421 MAKE_FUNCPTR(XCompositeQueryExtension)
422 MAKE_FUNCPTR(XCompositeQueryVersion)
423 MAKE_FUNCPTR(XCompositeVersion)
424 MAKE_FUNCPTR(XCompositeRedirectWindow)
425 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
426 MAKE_FUNCPTR(XCompositeUnredirectWindow)
427 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
428 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
429 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
430 #undef MAKE_FUNCPTR
431
432 static int xcomp_event_base;
433 static int xcomp_error_base;
434
435 static void X11DRV_XComposite_Init(void)
436 {
437     void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
438     if (!xcomposite_handle)
439     {
440         TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
441         usexcomposite = 0;
442         return;
443     }
444
445 #define LOAD_FUNCPTR(f) \
446     if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
447         goto sym_not_found;
448     LOAD_FUNCPTR(XCompositeQueryExtension)
449     LOAD_FUNCPTR(XCompositeQueryVersion)
450     LOAD_FUNCPTR(XCompositeVersion)
451     LOAD_FUNCPTR(XCompositeRedirectWindow)
452     LOAD_FUNCPTR(XCompositeRedirectSubwindows)
453     LOAD_FUNCPTR(XCompositeUnredirectWindow)
454     LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
455     LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
456     LOAD_FUNCPTR(XCompositeNameWindowPixmap)
457 #undef LOAD_FUNCPTR
458
459     if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
460                                   &xcomp_error_base)) {
461         TRACE("XComposite extension could not be queried; disabled\n");
462         wine_dlclose(xcomposite_handle, NULL, 0);
463         xcomposite_handle = NULL;
464         usexcomposite = 0;
465         return;
466     }
467     TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
468     return;
469
470 sym_not_found:
471     TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
472     wine_dlclose(xcomposite_handle, NULL, 0);
473     xcomposite_handle = NULL;
474     usexcomposite = 0;
475 }
476 #endif /* defined(SONAME_LIBXCOMPOSITE) */
477
478 static void init_visuals( Display *display, int screen )
479 {
480     int count;
481     XVisualInfo *info;
482
483     default_visual.screen = screen;
484     if (default_visual.depth)  /* depth specified */
485     {
486         info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count );
487         if (info)
488         {
489             default_visual = *info;
490             XFree( info );
491         }
492         else WARN( "no visual found for depth %d\n", default_visual.depth );
493     }
494
495     if (!default_visual.visual)
496     {
497         default_visual.depth         = DefaultDepth( display, screen );
498         default_visual.visual        = DefaultVisual( display, screen );
499         default_visual.visualid      = default_visual.visual->visualid;
500         default_visual.class         = default_visual.visual->class;
501         default_visual.red_mask      = default_visual.visual->red_mask;
502         default_visual.green_mask    = default_visual.visual->green_mask;
503         default_visual.blue_mask     = default_visual.visual->blue_mask;
504         default_visual.colormap_size = default_visual.visual->map_entries;
505         default_visual.bits_per_rgb  = default_visual.visual->bits_per_rgb;
506     }
507     default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
508
509     argb_visual.screen     = screen;
510     argb_visual.class      = TrueColor;
511     argb_visual.depth      = 32;
512     argb_visual.red_mask   = 0xff0000;
513     argb_visual.green_mask = 0x00ff00;
514     argb_visual.blue_mask  = 0x0000ff;
515
516     if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
517                                 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
518                                 &argb_visual, &count )))
519     {
520         argb_visual = *info;
521         XFree( info );
522     }
523     TRACE( "default visual %lx class %u argb %lx\n",
524            default_visual.visualid, default_visual.class, argb_visual.visualid );
525 }
526
527 /***********************************************************************
528  *           X11DRV process initialisation routine
529  */
530 static BOOL process_attach(void)
531 {
532     char error[1024];
533     Display *display;
534     void *libx11 = wine_dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error) );
535
536     if (!libx11)
537     {
538         ERR( "failed to load %s: %s\n", SONAME_LIBX11, error );
539         return FALSE;
540     }
541     pXGetEventData = wine_dlsym( libx11, "XGetEventData", NULL, 0 );
542     pXFreeEventData = wine_dlsym( libx11, "XFreeEventData", NULL, 0 );
543 #ifdef SONAME_LIBXEXT
544     wine_dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0 );
545 #endif
546
547     setup_options();
548
549     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
550
551     /* Open display */
552
553     if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
554     if (!(display = XOpenDisplay( NULL ))) return FALSE;
555
556     fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
557     root_window = DefaultRootWindow( display );
558     gdi_display = display;
559     old_error_handler = XSetErrorHandler( error_handler );
560
561     init_pixmap_formats( display );
562     init_visuals( display, DefaultScreen( display ));
563     screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
564
565     XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
566
567     winContext = XUniqueContext();
568     win_data_context = XUniqueContext();
569     cursor_context = XUniqueContext();
570
571     if (TRACE_ON(synchronous)) XSynchronize( display, True );
572
573     xinerama_init( DisplayWidth( display, default_visual.screen ),
574                    DisplayHeight( display, default_visual.screen ));
575     X11DRV_Settings_Init();
576
577     /* initialize XVidMode */
578     X11DRV_XF86VM_Init();
579     /* initialize XRandR */
580     X11DRV_XRandR_Init();
581 #ifdef SONAME_LIBXCOMPOSITE
582     X11DRV_XComposite_Init();
583 #endif
584     X11DRV_XInput2_Init();
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         if (data->xim) XCloseIM( data->xim );
608         if (data->font_set) XFreeFontSet( data->display, data->font_set );
609         XCloseDisplay( data->display );
610         HeapFree( GetProcessHeap(), 0, data );
611     }
612 }
613
614
615 /* store the display fd into the message queue */
616 static void set_queue_display_fd( Display *display )
617 {
618     HANDLE handle;
619     int ret;
620
621     if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
622     {
623         MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
624         ExitProcess(1);
625     }
626     SERVER_START_REQ( set_queue_fd )
627     {
628         req->handle = wine_server_obj_handle( handle );
629         ret = wine_server_call( req );
630     }
631     SERVER_END_REQ;
632     if (ret)
633     {
634         MESSAGE( "x11drv: Can't store handle for display fd\n" );
635         ExitProcess(1);
636     }
637     CloseHandle( handle );
638 }
639
640
641 /***********************************************************************
642  *           X11DRV thread initialisation routine
643  */
644 struct x11drv_thread_data *x11drv_init_thread_data(void)
645 {
646     struct x11drv_thread_data *data = x11drv_thread_data();
647
648     if (data) return data;
649
650     if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
651     {
652         ERR( "could not create data\n" );
653         ExitProcess(1);
654     }
655     if (!(data->display = XOpenDisplay(NULL)))
656     {
657         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));
658         ExitProcess(1);
659     }
660
661     fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
662
663 #ifdef HAVE_XKB
664     if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
665         XkbSetDetectableAutoRepeat( data->display, True, NULL );
666 #endif
667
668     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
669
670     set_queue_display_fd( data->display );
671     TlsSetValue( thread_data_tls_index, data );
672
673     if (use_xim) X11DRV_SetupXIM();
674
675     return data;
676 }
677
678
679 /***********************************************************************
680  *           X11DRV initialisation routine
681  */
682 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
683 {
684     BOOL ret = TRUE;
685
686     switch(reason)
687     {
688     case DLL_PROCESS_ATTACH:
689         x11drv_module = hinst;
690         ret = process_attach();
691         break;
692     case DLL_THREAD_DETACH:
693         thread_detach();
694         break;
695     }
696     return ret;
697 }
698
699
700 /***********************************************************************
701  *              SystemParametersInfo (X11DRV.@)
702  */
703 BOOL CDECL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
704 {
705     switch (action)
706     {
707     case SPI_GETSCREENSAVEACTIVE:
708         if (ptr_param)
709         {
710             int timeout, temp;
711             XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
712             *(BOOL *)ptr_param = timeout != 0;
713             return TRUE;
714         }
715         break;
716     case SPI_SETSCREENSAVEACTIVE:
717         {
718             int timeout, interval, prefer_blanking, allow_exposures;
719             static int last_timeout = 15 * 60;
720
721             XLockDisplay( gdi_display );
722             XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
723                             &allow_exposures);
724             if (timeout) last_timeout = timeout;
725
726             timeout = int_param ? last_timeout : 0;
727             XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
728                             allow_exposures);
729             XUnlockDisplay( gdi_display );
730         }
731         break;
732     }
733     return FALSE;  /* let user32 handle it */
734 }