wined3d: Replace an open-coded implementation of LIST_FOR_EACH_ENTRY_SAFE.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blob85c69bfbd357c1e5198271dd70bc809364d5bd0d
1 /*
2 * X11DRV initialization code
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2000 Alexandre Julliard
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.
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.
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
22 #include "config.h"
23 #include "wine/port.h"
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
45 #include "windef.h"
46 #include "winbase.h"
47 #include "winreg.h"
49 #include "x11drv.h"
50 #include "xcomposite.h"
51 #include "wine/server.h"
52 #include "wine/debug.h"
53 #include "wine/library.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
56 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
57 WINE_DECLARE_DEBUG_CHANNEL(winediag);
59 XVisualInfo default_visual = { 0 };
60 XVisualInfo argb_visual = { 0 };
61 Colormap default_colormap = None;
62 XPixmapFormatValues **pixmap_formats;
63 unsigned int screen_bpp;
64 Window root_window;
65 BOOL usexvidmode = TRUE;
66 BOOL usexrandr = TRUE;
67 BOOL usexcomposite = TRUE;
68 BOOL use_xkb = TRUE;
69 BOOL use_take_focus = TRUE;
70 BOOL use_primary_selection = FALSE;
71 BOOL use_system_cursors = TRUE;
72 BOOL show_systray = TRUE;
73 BOOL grab_pointer = TRUE;
74 BOOL grab_fullscreen = FALSE;
75 BOOL managed_mode = TRUE;
76 BOOL decorated_mode = TRUE;
77 BOOL private_color_map = FALSE;
78 int primary_monitor = 0;
79 BOOL client_side_graphics = TRUE;
80 BOOL client_side_with_render = TRUE;
81 BOOL shape_layered_windows = TRUE;
82 int copy_default_colors = 128;
83 int alloc_system_colors = 256;
84 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
85 int xrender_error_base = 0;
86 HMODULE x11drv_module = 0;
88 static x11drv_error_callback err_callback; /* current callback for error */
89 static Display *err_callback_display; /* display callback is set for */
90 static void *err_callback_arg; /* error callback argument */
91 static int err_callback_result; /* error callback result */
92 static unsigned long err_serial; /* serial number of first request */
93 static int (*old_error_handler)( Display *, XErrorEvent * );
94 static BOOL use_xim = TRUE;
95 static char input_style[20];
97 #define IS_OPTION_TRUE(ch) \
98 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
99 #define IS_OPTION_FALSE(ch) \
100 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
102 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
104 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
106 "CLIPBOARD",
107 "COMPOUND_TEXT",
108 "INCR",
109 "MANAGER",
110 "MULTIPLE",
111 "SELECTION_DATA",
112 "TARGETS",
113 "TEXT",
114 "UTF8_STRING",
115 "RAW_ASCENT",
116 "RAW_DESCENT",
117 "RAW_CAP_HEIGHT",
118 "Rel X",
119 "Rel Y",
120 "WM_PROTOCOLS",
121 "WM_DELETE_WINDOW",
122 "WM_STATE",
123 "WM_TAKE_FOCUS",
124 "DndProtocol",
125 "DndSelection",
126 "_ICC_PROFILE",
127 "_MOTIF_WM_HINTS",
128 "_NET_STARTUP_INFO_BEGIN",
129 "_NET_STARTUP_INFO",
130 "_NET_SUPPORTED",
131 "_NET_SYSTEM_TRAY_OPCODE",
132 "_NET_SYSTEM_TRAY_S0",
133 "_NET_SYSTEM_TRAY_VISUAL",
134 "_NET_WM_ICON",
135 "_NET_WM_MOVERESIZE",
136 "_NET_WM_NAME",
137 "_NET_WM_PID",
138 "_NET_WM_PING",
139 "_NET_WM_STATE",
140 "_NET_WM_STATE_ABOVE",
141 "_NET_WM_STATE_FULLSCREEN",
142 "_NET_WM_STATE_MAXIMIZED_HORZ",
143 "_NET_WM_STATE_MAXIMIZED_VERT",
144 "_NET_WM_STATE_SKIP_PAGER",
145 "_NET_WM_STATE_SKIP_TASKBAR",
146 "_NET_WM_USER_TIME",
147 "_NET_WM_USER_TIME_WINDOW",
148 "_NET_WM_WINDOW_OPACITY",
149 "_NET_WM_WINDOW_TYPE",
150 "_NET_WM_WINDOW_TYPE_DIALOG",
151 "_NET_WM_WINDOW_TYPE_NORMAL",
152 "_NET_WM_WINDOW_TYPE_UTILITY",
153 "_NET_WORKAREA",
154 "_XEMBED",
155 "_XEMBED_INFO",
156 "XdndAware",
157 "XdndEnter",
158 "XdndPosition",
159 "XdndStatus",
160 "XdndLeave",
161 "XdndFinished",
162 "XdndDrop",
163 "XdndActionCopy",
164 "XdndActionMove",
165 "XdndActionLink",
166 "XdndActionAsk",
167 "XdndActionPrivate",
168 "XdndSelection",
169 "XdndTarget",
170 "XdndTypeList",
171 "HTML Format",
172 "WCF_BITMAP",
173 "WCF_DIB",
174 "WCF_DIBV5",
175 "WCF_DIF",
176 "WCF_DSPBITMAP",
177 "WCF_DSPENHMETAFILE",
178 "WCF_DSPMETAFILEPICT",
179 "WCF_DSPTEXT",
180 "WCF_ENHMETAFILE",
181 "WCF_HDROP",
182 "WCF_LOCALE",
183 "WCF_METAFILEPICT",
184 "WCF_OEMTEXT",
185 "WCF_OWNERDISPLAY",
186 "WCF_PALETTE",
187 "WCF_PENDATA",
188 "WCF_RIFF",
189 "WCF_SYLK",
190 "WCF_TIFF",
191 "WCF_WAVE",
192 "image/bmp",
193 "image/gif",
194 "image/jpeg",
195 "image/png",
196 "text/html",
197 "text/plain",
198 "text/rtf",
199 "text/richtext",
200 "text/uri-list"
203 /***********************************************************************
204 * ignore_error
206 * Check if the X error is one we can ignore.
208 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
210 if ((event->request_code == X_SetInputFocus || event->request_code == X_ChangeWindowAttributes) &&
211 (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
213 /* ignore a number of errors on gdi display caused by creating/destroying windows */
214 if (display == gdi_display)
216 if (event->error_code == BadDrawable ||
217 event->error_code == BadGC ||
218 event->error_code == BadWindow)
219 return TRUE;
220 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
221 if (xrender_error_base) /* check for XRender errors */
223 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
225 #endif
227 return FALSE;
231 /***********************************************************************
232 * X11DRV_expect_error
234 * Setup a callback function that will be called on an X error. The
235 * callback must return non-zero if the error is the one it expected.
237 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
239 err_callback = callback;
240 err_callback_display = display;
241 err_callback_arg = arg;
242 err_callback_result = 0;
243 err_serial = NextRequest(display);
247 /***********************************************************************
248 * X11DRV_check_error
250 * Check if an expected X11 error occurred; return non-zero if yes.
251 * The caller is responsible for calling XSync first if necessary.
253 int X11DRV_check_error(void)
255 err_callback = NULL;
256 return err_callback_result;
260 /***********************************************************************
261 * error_handler
263 static int error_handler( Display *display, XErrorEvent *error_evt )
265 if (err_callback && display == err_callback_display &&
266 (long)(error_evt->serial - err_serial) >= 0)
268 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
270 TRACE( "got expected error %d req %d\n",
271 error_evt->error_code, error_evt->request_code );
272 return 0;
275 if (ignore_error( display, error_evt ))
277 TRACE( "got ignored error %d req %d\n",
278 error_evt->error_code, error_evt->request_code );
279 return 0;
281 if (TRACE_ON(synchronous))
283 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
284 error_evt->serial, error_evt->request_code );
285 DebugBreak(); /* force an entry in the debugger */
287 old_error_handler( display, error_evt );
288 return 0;
291 /***********************************************************************
292 * init_pixmap_formats
294 static void init_pixmap_formats( Display *display )
296 int i, count, max = 32;
297 XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
299 for (i = 0; i < count; i++)
301 TRACE( "depth %u, bpp %u, pad %u\n",
302 formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
303 if (formats[i].depth > max) max = formats[i].depth;
305 pixmap_formats = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pixmap_formats) * (max + 1) );
306 for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
310 /***********************************************************************
311 * get_config_key
313 * Get a config key from either the app-specific or the default config
315 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
316 char *buffer, DWORD size )
318 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
319 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
320 return ERROR_FILE_NOT_FOUND;
324 /***********************************************************************
325 * setup_options
327 * Setup the x11drv options.
329 static void setup_options(void)
331 char buffer[MAX_PATH+16];
332 HKEY hkey, appkey = 0;
333 DWORD len;
335 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
336 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
338 /* open the app-specific key */
340 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
341 if (len && len < MAX_PATH)
343 HKEY tmpkey;
344 char *p, *appname = buffer;
345 if ((p = strrchr( appname, '/' ))) appname = p + 1;
346 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
347 strcat( appname, "\\X11 Driver" );
348 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
349 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
351 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
352 RegCloseKey( tmpkey );
356 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
357 managed_mode = IS_OPTION_TRUE( buffer[0] );
359 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
360 decorated_mode = IS_OPTION_TRUE( buffer[0] );
362 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
363 usexvidmode = IS_OPTION_TRUE( buffer[0] );
365 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
366 usexrandr = IS_OPTION_TRUE( buffer[0] );
368 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
369 use_take_focus = IS_OPTION_TRUE( buffer[0] );
371 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
372 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
374 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
375 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
377 if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
378 show_systray = IS_OPTION_TRUE( buffer[0] );
380 if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
381 grab_pointer = IS_OPTION_TRUE( buffer[0] );
383 if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
384 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
386 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
387 default_visual.depth = atoi(buffer);
389 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
390 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
392 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
393 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
395 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
396 use_xim = IS_OPTION_TRUE( buffer[0] );
398 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
399 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
401 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
402 private_color_map = IS_OPTION_TRUE( buffer[0] );
404 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
405 primary_monitor = atoi( buffer );
407 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
408 copy_default_colors = atoi(buffer);
410 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
411 alloc_system_colors = atoi(buffer);
413 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
415 if (appkey) RegCloseKey( appkey );
416 if (hkey) RegCloseKey( hkey );
419 #ifdef SONAME_LIBXCOMPOSITE
421 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
422 MAKE_FUNCPTR(XCompositeQueryExtension)
423 MAKE_FUNCPTR(XCompositeQueryVersion)
424 MAKE_FUNCPTR(XCompositeVersion)
425 MAKE_FUNCPTR(XCompositeRedirectWindow)
426 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
427 MAKE_FUNCPTR(XCompositeUnredirectWindow)
428 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
429 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
430 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
431 #undef MAKE_FUNCPTR
433 static int xcomp_event_base;
434 static int xcomp_error_base;
436 static void X11DRV_XComposite_Init(void)
438 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
439 if (!xcomposite_handle)
441 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
442 usexcomposite = FALSE;
443 return;
446 #define LOAD_FUNCPTR(f) \
447 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
448 goto sym_not_found;
449 LOAD_FUNCPTR(XCompositeQueryExtension)
450 LOAD_FUNCPTR(XCompositeQueryVersion)
451 LOAD_FUNCPTR(XCompositeVersion)
452 LOAD_FUNCPTR(XCompositeRedirectWindow)
453 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
454 LOAD_FUNCPTR(XCompositeUnredirectWindow)
455 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
456 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
457 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
458 #undef LOAD_FUNCPTR
460 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
461 &xcomp_error_base)) {
462 TRACE("XComposite extension could not be queried; disabled\n");
463 wine_dlclose(xcomposite_handle, NULL, 0);
464 xcomposite_handle = NULL;
465 usexcomposite = FALSE;
466 return;
468 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
469 return;
471 sym_not_found:
472 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
473 wine_dlclose(xcomposite_handle, NULL, 0);
474 xcomposite_handle = NULL;
475 usexcomposite = FALSE;
477 #endif /* defined(SONAME_LIBXCOMPOSITE) */
479 static void init_visuals( Display *display, int screen )
481 int count;
482 XVisualInfo *info;
484 default_visual.screen = screen;
485 if (default_visual.depth) /* depth specified */
487 info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count );
488 if (info)
490 default_visual = *info;
491 XFree( info );
493 else WARN( "no visual found for depth %d\n", default_visual.depth );
496 if (!default_visual.visual)
498 default_visual.depth = DefaultDepth( display, screen );
499 default_visual.visual = DefaultVisual( display, screen );
500 default_visual.visualid = default_visual.visual->visualid;
501 default_visual.class = default_visual.visual->class;
502 default_visual.red_mask = default_visual.visual->red_mask;
503 default_visual.green_mask = default_visual.visual->green_mask;
504 default_visual.blue_mask = default_visual.visual->blue_mask;
505 default_visual.colormap_size = default_visual.visual->map_entries;
506 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
508 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
510 argb_visual.screen = screen;
511 argb_visual.class = TrueColor;
512 argb_visual.depth = 32;
513 argb_visual.red_mask = 0xff0000;
514 argb_visual.green_mask = 0x00ff00;
515 argb_visual.blue_mask = 0x0000ff;
517 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
518 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
519 &argb_visual, &count )))
521 argb_visual = *info;
522 XFree( info );
524 TRACE( "default visual %lx class %u argb %lx\n",
525 default_visual.visualid, default_visual.class, argb_visual.visualid );
528 /***********************************************************************
529 * X11DRV process initialisation routine
531 static BOOL process_attach(void)
533 char error[1024];
534 Display *display;
535 void *libx11 = wine_dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error) );
537 if (!libx11)
539 ERR( "failed to load %s: %s\n", SONAME_LIBX11, error );
540 return FALSE;
542 pXGetEventData = wine_dlsym( libx11, "XGetEventData", NULL, 0 );
543 pXFreeEventData = wine_dlsym( libx11, "XFreeEventData", NULL, 0 );
544 #ifdef SONAME_LIBXEXT
545 wine_dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0 );
546 #endif
548 setup_options();
550 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
552 /* Open display */
554 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
555 if (!(display = XOpenDisplay( NULL ))) return FALSE;
557 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
558 root_window = DefaultRootWindow( display );
559 gdi_display = display;
560 old_error_handler = XSetErrorHandler( error_handler );
562 init_pixmap_formats( display );
563 init_visuals( display, DefaultScreen( display ));
564 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
566 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
568 winContext = XUniqueContext();
569 win_data_context = XUniqueContext();
570 cursor_context = XUniqueContext();
572 if (TRACE_ON(synchronous)) XSynchronize( display, True );
574 xinerama_init( DisplayWidth( display, default_visual.screen ),
575 DisplayHeight( display, default_visual.screen ));
576 X11DRV_Settings_Init();
578 /* initialize XVidMode */
579 X11DRV_XF86VM_Init();
580 /* initialize XRandR */
581 X11DRV_XRandR_Init();
582 #ifdef SONAME_LIBXCOMPOSITE
583 X11DRV_XComposite_Init();
584 #endif
585 X11DRV_XInput2_Init();
587 #ifdef HAVE_XKB
588 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
589 #endif
590 X11DRV_InitKeyboard( gdi_display );
591 X11DRV_InitClipboard();
592 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
594 return TRUE;
598 /***********************************************************************
599 * X11DRV thread termination routine
601 static void thread_detach(void)
603 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
605 if (data)
607 X11DRV_ResetSelectionOwner();
608 if (data->xim) XCloseIM( data->xim );
609 if (data->font_set) XFreeFontSet( data->display, data->font_set );
610 XCloseDisplay( data->display );
611 HeapFree( GetProcessHeap(), 0, data );
612 /* clear data in case we get re-entered from user32 before the thread is truly dead */
613 TlsSetValue( thread_data_tls_index, NULL );
618 /* store the display fd into the message queue */
619 static void set_queue_display_fd( Display *display )
621 HANDLE handle;
622 int ret;
624 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
626 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
627 ExitProcess(1);
629 SERVER_START_REQ( set_queue_fd )
631 req->handle = wine_server_obj_handle( handle );
632 ret = wine_server_call( req );
634 SERVER_END_REQ;
635 if (ret)
637 MESSAGE( "x11drv: Can't store handle for display fd\n" );
638 ExitProcess(1);
640 CloseHandle( handle );
644 /***********************************************************************
645 * X11DRV thread initialisation routine
647 struct x11drv_thread_data *x11drv_init_thread_data(void)
649 struct x11drv_thread_data *data = x11drv_thread_data();
651 if (data) return data;
653 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
655 ERR( "could not create data\n" );
656 ExitProcess(1);
658 if (!(data->display = XOpenDisplay(NULL)))
660 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));
661 ExitProcess(1);
664 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
666 #ifdef HAVE_XKB
667 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
668 XkbSetDetectableAutoRepeat( data->display, True, NULL );
669 #endif
671 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
673 set_queue_display_fd( data->display );
674 TlsSetValue( thread_data_tls_index, data );
676 if (use_xim) X11DRV_SetupXIM();
678 return data;
682 /***********************************************************************
683 * X11DRV initialisation routine
685 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
687 BOOL ret = TRUE;
689 switch(reason)
691 case DLL_PROCESS_ATTACH:
692 x11drv_module = hinst;
693 ret = process_attach();
694 break;
695 case DLL_THREAD_DETACH:
696 thread_detach();
697 break;
699 return ret;
703 /***********************************************************************
704 * SystemParametersInfo (X11DRV.@)
706 BOOL CDECL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
708 switch (action)
710 case SPI_GETSCREENSAVEACTIVE:
711 if (ptr_param)
713 int timeout, temp;
714 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
715 *(BOOL *)ptr_param = timeout != 0;
716 return TRUE;
718 break;
719 case SPI_SETSCREENSAVEACTIVE:
721 int timeout, interval, prefer_blanking, allow_exposures;
722 static int last_timeout = 15 * 60;
724 XLockDisplay( gdi_display );
725 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
726 &allow_exposures);
727 if (timeout) last_timeout = timeout;
729 timeout = int_param ? last_timeout : 0;
730 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
731 allow_exposures);
732 XUnlockDisplay( gdi_display );
734 break;
736 return FALSE; /* let user32 handle it */