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