mstask: Implement ITask::DeleteTrigger().
[wine.git] / dlls / winex11.drv / x11drv_main.c
blobe67a3c05a979f70f8ad441f9c876a34354209819
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/unicode.h"
53 #include "wine/debug.h"
54 #include "wine/library.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
57 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
58 WINE_DECLARE_DEBUG_CHANNEL(winediag);
60 XVisualInfo default_visual = { 0 };
61 XVisualInfo argb_visual = { 0 };
62 Colormap default_colormap = None;
63 XPixmapFormatValues **pixmap_formats;
64 unsigned int screen_bpp;
65 Window root_window;
66 BOOL usexvidmode = TRUE;
67 BOOL usexrandr = TRUE;
68 BOOL usexcomposite = TRUE;
69 BOOL use_xkb = TRUE;
70 BOOL use_take_focus = TRUE;
71 BOOL use_primary_selection = FALSE;
72 BOOL use_system_cursors = TRUE;
73 BOOL show_systray = TRUE;
74 BOOL grab_pointer = TRUE;
75 BOOL grab_fullscreen = FALSE;
76 BOOL managed_mode = TRUE;
77 BOOL decorated_mode = TRUE;
78 BOOL private_color_map = FALSE;
79 int primary_monitor = 0;
80 BOOL client_side_graphics = TRUE;
81 BOOL client_side_with_render = TRUE;
82 BOOL shape_layered_windows = TRUE;
83 int copy_default_colors = 128;
84 int alloc_system_colors = 256;
85 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
86 int xrender_error_base = 0;
87 HMODULE x11drv_module = 0;
88 char *process_name = NULL;
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 BOOL use_xim = TRUE;
97 static char input_style[20];
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')
104 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
106 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
108 "CLIPBOARD",
109 "COMPOUND_TEXT",
110 "INCR",
111 "MANAGER",
112 "MULTIPLE",
113 "SELECTION_DATA",
114 "TARGETS",
115 "TEXT",
116 "TIMESTAMP",
117 "UTF8_STRING",
118 "RAW_ASCENT",
119 "RAW_DESCENT",
120 "RAW_CAP_HEIGHT",
121 "Rel X",
122 "Rel Y",
123 "WM_PROTOCOLS",
124 "WM_DELETE_WINDOW",
125 "WM_STATE",
126 "WM_TAKE_FOCUS",
127 "DndProtocol",
128 "DndSelection",
129 "_ICC_PROFILE",
130 "_MOTIF_WM_HINTS",
131 "_NET_STARTUP_INFO_BEGIN",
132 "_NET_STARTUP_INFO",
133 "_NET_SUPPORTED",
134 "_NET_SYSTEM_TRAY_OPCODE",
135 "_NET_SYSTEM_TRAY_S0",
136 "_NET_SYSTEM_TRAY_VISUAL",
137 "_NET_WM_ICON",
138 "_NET_WM_MOVERESIZE",
139 "_NET_WM_NAME",
140 "_NET_WM_PID",
141 "_NET_WM_PING",
142 "_NET_WM_STATE",
143 "_NET_WM_STATE_ABOVE",
144 "_NET_WM_STATE_DEMANDS_ATTENTION",
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 "XdndTypeList",
174 "HTML Format",
175 "WCF_DIF",
176 "WCF_ENHMETAFILE",
177 "WCF_HDROP",
178 "WCF_PENDATA",
179 "WCF_RIFF",
180 "WCF_SYLK",
181 "WCF_TIFF",
182 "WCF_WAVE",
183 "image/bmp",
184 "image/gif",
185 "image/jpeg",
186 "image/png",
187 "text/html",
188 "text/plain",
189 "text/rtf",
190 "text/richtext",
191 "text/uri-list"
194 /***********************************************************************
195 * ignore_error
197 * Check if the X error is one we can ignore.
199 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
201 if ((event->request_code == X_SetInputFocus ||
202 event->request_code == X_ChangeWindowAttributes ||
203 event->request_code == X_SendEvent) &&
204 (event->error_code == BadMatch ||
205 event->error_code == BadWindow)) return TRUE;
207 /* the clipboard display interacts with external windows, ignore all errors */
208 if (display == clipboard_display) return TRUE;
210 /* ignore a number of errors on gdi display caused by creating/destroying windows */
211 if (display == gdi_display)
213 if (event->error_code == BadDrawable ||
214 event->error_code == BadGC ||
215 event->error_code == BadWindow)
216 return TRUE;
217 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
218 if (xrender_error_base) /* check for XRender errors */
220 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
222 #endif
224 return FALSE;
228 /***********************************************************************
229 * X11DRV_expect_error
231 * Setup a callback function that will be called on an X error. The
232 * callback must return non-zero if the error is the one it expected.
234 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
236 err_callback = callback;
237 err_callback_display = display;
238 err_callback_arg = arg;
239 err_callback_result = 0;
240 err_serial = NextRequest(display);
244 /***********************************************************************
245 * X11DRV_check_error
247 * Check if an expected X11 error occurred; return non-zero if yes.
248 * The caller is responsible for calling XSync first if necessary.
250 int X11DRV_check_error(void)
252 err_callback = NULL;
253 return err_callback_result;
257 /***********************************************************************
258 * error_handler
260 static int error_handler( Display *display, XErrorEvent *error_evt )
262 if (err_callback && display == err_callback_display &&
263 (long)(error_evt->serial - err_serial) >= 0)
265 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
267 TRACE( "got expected error %d req %d\n",
268 error_evt->error_code, error_evt->request_code );
269 return 0;
272 if (ignore_error( display, error_evt ))
274 TRACE( "got ignored error %d req %d\n",
275 error_evt->error_code, error_evt->request_code );
276 return 0;
278 if (TRACE_ON(synchronous))
280 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
281 error_evt->serial, error_evt->request_code );
282 DebugBreak(); /* force an entry in the debugger */
284 old_error_handler( display, error_evt );
285 return 0;
288 /***********************************************************************
289 * init_pixmap_formats
291 static void init_pixmap_formats( Display *display )
293 int i, count, max = 32;
294 XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
296 for (i = 0; i < count; i++)
298 TRACE( "depth %u, bpp %u, pad %u\n",
299 formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
300 if (formats[i].depth > max) max = formats[i].depth;
302 pixmap_formats = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pixmap_formats) * (max + 1) );
303 for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
307 /***********************************************************************
308 * get_config_key
310 * Get a config key from either the app-specific or the default config
312 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
313 char *buffer, DWORD size )
315 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
316 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
317 return ERROR_FILE_NOT_FOUND;
321 /***********************************************************************
322 * setup_options
324 * Setup the x11drv options.
326 static void setup_options(void)
328 static const WCHAR x11driverW[] = {'\\','X','1','1',' ','D','r','i','v','e','r',0};
329 char buffer[64];
330 WCHAR bufferW[MAX_PATH+16];
331 HKEY hkey, appkey = 0;
332 DWORD len;
334 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
335 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
337 /* open the app-specific key */
339 len = (GetModuleFileNameW( 0, bufferW, MAX_PATH ));
340 if (len && len < MAX_PATH)
342 HKEY tmpkey;
343 WCHAR *p, *appname = bufferW;
344 if ((p = strrchrW( appname, '/' ))) appname = p + 1;
345 if ((p = strrchrW( appname, '\\' ))) appname = p + 1;
346 CharLowerW(appname);
347 len = WideCharToMultiByte( CP_UNIXCP, 0, appname, -1, NULL, 0, NULL, NULL );
348 if ((process_name = HeapAlloc( GetProcessHeap(), 0, len )))
349 WideCharToMultiByte( CP_UNIXCP, 0, appname, -1, process_name, len, NULL, NULL );
350 strcatW( appname, x11driverW );
351 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
352 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
354 if (RegOpenKeyW( tmpkey, appname, &appkey )) appkey = 0;
355 RegCloseKey( tmpkey );
359 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
360 managed_mode = IS_OPTION_TRUE( buffer[0] );
362 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
363 decorated_mode = IS_OPTION_TRUE( buffer[0] );
365 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
366 usexvidmode = IS_OPTION_TRUE( buffer[0] );
368 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
369 usexrandr = IS_OPTION_TRUE( buffer[0] );
371 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
372 use_take_focus = IS_OPTION_TRUE( buffer[0] );
374 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
375 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
377 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
378 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
380 if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
381 show_systray = IS_OPTION_TRUE( buffer[0] );
383 if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
384 grab_pointer = IS_OPTION_TRUE( buffer[0] );
386 if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
387 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
389 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
390 default_visual.depth = atoi(buffer);
392 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
393 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
395 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
396 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
398 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
399 use_xim = IS_OPTION_TRUE( buffer[0] );
401 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
402 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
404 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
405 private_color_map = IS_OPTION_TRUE( buffer[0] );
407 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
408 primary_monitor = atoi( buffer );
410 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
411 copy_default_colors = atoi(buffer);
413 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
414 alloc_system_colors = atoi(buffer);
416 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
418 if (appkey) RegCloseKey( appkey );
419 if (hkey) RegCloseKey( hkey );
422 #ifdef SONAME_LIBXCOMPOSITE
424 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
425 MAKE_FUNCPTR(XCompositeQueryExtension)
426 MAKE_FUNCPTR(XCompositeQueryVersion)
427 MAKE_FUNCPTR(XCompositeVersion)
428 MAKE_FUNCPTR(XCompositeRedirectWindow)
429 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
430 MAKE_FUNCPTR(XCompositeUnredirectWindow)
431 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
432 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
433 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
434 #undef MAKE_FUNCPTR
436 static int xcomp_event_base;
437 static int xcomp_error_base;
439 static void X11DRV_XComposite_Init(void)
441 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
442 if (!xcomposite_handle)
444 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
445 usexcomposite = FALSE;
446 return;
449 #define LOAD_FUNCPTR(f) \
450 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
451 goto sym_not_found;
452 LOAD_FUNCPTR(XCompositeQueryExtension)
453 LOAD_FUNCPTR(XCompositeQueryVersion)
454 LOAD_FUNCPTR(XCompositeVersion)
455 LOAD_FUNCPTR(XCompositeRedirectWindow)
456 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
457 LOAD_FUNCPTR(XCompositeUnredirectWindow)
458 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
459 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
460 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
461 #undef LOAD_FUNCPTR
463 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
464 &xcomp_error_base)) {
465 TRACE("XComposite extension could not be queried; disabled\n");
466 wine_dlclose(xcomposite_handle, NULL, 0);
467 xcomposite_handle = NULL;
468 usexcomposite = FALSE;
469 return;
471 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
472 return;
474 sym_not_found:
475 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
476 wine_dlclose(xcomposite_handle, NULL, 0);
477 xcomposite_handle = NULL;
478 usexcomposite = FALSE;
480 #endif /* defined(SONAME_LIBXCOMPOSITE) */
482 static void init_visuals( Display *display, int screen )
484 int count;
485 XVisualInfo *info;
487 argb_visual.screen = screen;
488 argb_visual.class = TrueColor;
489 argb_visual.depth = 32;
490 argb_visual.red_mask = 0xff0000;
491 argb_visual.green_mask = 0x00ff00;
492 argb_visual.blue_mask = 0x0000ff;
494 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
495 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
496 &argb_visual, &count )))
498 argb_visual = *info;
499 XFree( info );
502 default_visual.screen = screen;
503 if (default_visual.depth) /* depth specified */
505 if (default_visual.depth == 32 && argb_visual.visual)
507 default_visual = argb_visual;
509 else if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count )))
511 default_visual = *info;
512 XFree( info );
514 else WARN( "no visual found for depth %d\n", default_visual.depth );
517 if (!default_visual.visual)
519 default_visual.depth = DefaultDepth( display, screen );
520 default_visual.visual = DefaultVisual( display, screen );
521 default_visual.visualid = default_visual.visual->visualid;
522 default_visual.class = default_visual.visual->class;
523 default_visual.red_mask = default_visual.visual->red_mask;
524 default_visual.green_mask = default_visual.visual->green_mask;
525 default_visual.blue_mask = default_visual.visual->blue_mask;
526 default_visual.colormap_size = default_visual.visual->map_entries;
527 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
529 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
531 TRACE( "default visual %lx class %u argb %lx\n",
532 default_visual.visualid, default_visual.class, argb_visual.visualid );
535 /***********************************************************************
536 * X11DRV process initialisation routine
538 static BOOL process_attach(void)
540 char error[1024];
541 Display *display;
542 void *libx11 = wine_dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error) );
544 if (!libx11)
546 ERR( "failed to load %s: %s\n", SONAME_LIBX11, error );
547 return FALSE;
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
555 setup_options();
557 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
559 /* Open display */
561 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
562 if (!(display = XOpenDisplay( NULL ))) return FALSE;
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 );
569 init_pixmap_formats( display );
570 init_visuals( display, DefaultScreen( display ));
571 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
573 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
575 winContext = XUniqueContext();
576 win_data_context = XUniqueContext();
577 cursor_context = XUniqueContext();
579 if (TRACE_ON(synchronous)) XSynchronize( display, True );
581 xinerama_init( DisplayWidth( display, default_visual.screen ),
582 DisplayHeight( display, default_visual.screen ));
583 X11DRV_Settings_Init();
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();
594 #ifdef HAVE_XKB
595 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
596 #endif
597 X11DRV_InitKeyboard( gdi_display );
598 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
600 return TRUE;
604 /***********************************************************************
605 * ThreadDetach (X11DRV.@)
607 void CDECL X11DRV_ThreadDetach(void)
609 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
611 if (data)
613 if (data->xim) XCloseIM( data->xim );
614 if (data->font_set) XFreeFontSet( data->display, data->font_set );
615 XCloseDisplay( data->display );
616 HeapFree( GetProcessHeap(), 0, data );
617 /* clear data in case we get re-entered from user32 before the thread is truly dead */
618 TlsSetValue( thread_data_tls_index, NULL );
623 /* store the display fd into the message queue */
624 static void set_queue_display_fd( Display *display )
626 HANDLE handle;
627 int ret;
629 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
631 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
632 ExitProcess(1);
634 SERVER_START_REQ( set_queue_fd )
636 req->handle = wine_server_obj_handle( handle );
637 ret = wine_server_call( req );
639 SERVER_END_REQ;
640 if (ret)
642 MESSAGE( "x11drv: Can't store handle for display fd\n" );
643 ExitProcess(1);
645 CloseHandle( handle );
649 /***********************************************************************
650 * X11DRV thread initialisation routine
652 struct x11drv_thread_data *x11drv_init_thread_data(void)
654 struct x11drv_thread_data *data = x11drv_thread_data();
656 if (data) return data;
658 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
660 ERR( "could not create data\n" );
661 ExitProcess(1);
663 if (!(data->display = XOpenDisplay(NULL)))
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);
669 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
671 #ifdef HAVE_XKB
672 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
673 XkbSetDetectableAutoRepeat( data->display, True, NULL );
674 #endif
676 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
678 set_queue_display_fd( data->display );
679 TlsSetValue( thread_data_tls_index, data );
681 if (use_xim) X11DRV_SetupXIM();
683 return data;
687 /***********************************************************************
688 * X11DRV initialisation routine
690 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
692 BOOL ret = TRUE;
694 switch(reason)
696 case DLL_PROCESS_ATTACH:
697 DisableThreadLibraryCalls( hinst );
698 x11drv_module = hinst;
699 ret = process_attach();
700 break;
702 return ret;
706 /***********************************************************************
707 * SystemParametersInfo (X11DRV.@)
709 BOOL CDECL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
711 switch (action)
713 case SPI_GETSCREENSAVEACTIVE:
714 if (ptr_param)
716 int timeout, temp;
717 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
718 *(BOOL *)ptr_param = timeout != 0;
719 return TRUE;
721 break;
722 case SPI_SETSCREENSAVEACTIVE:
724 int timeout, interval, prefer_blanking, allow_exposures;
725 static int last_timeout = 15 * 60;
727 XLockDisplay( gdi_display );
728 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
729 &allow_exposures);
730 if (timeout) last_timeout = timeout;
732 timeout = int_param ? last_timeout : 0;
733 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
734 allow_exposures);
735 XUnlockDisplay( gdi_display );
737 break;
739 return FALSE; /* let user32 handle it */