include: Add STORAGE_HOTPLUG_INFO structure.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blob4c8fd943ffd82e772a90f677a73b76a9c615667c
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 #if 0
23 #pragma makedep unix
24 #endif
26 #include "config.h"
28 #include <fcntl.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/time.h>
34 #include <unistd.h>
35 #include <assert.h>
36 #include <dlfcn.h>
37 #include <X11/cursorfont.h>
38 #include <X11/Xlib.h>
39 #include <X11/XKBlib.h>
40 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
41 #include <X11/extensions/Xrender.h>
42 #endif
44 #include "ntstatus.h"
45 #define WIN32_NO_STATUS
47 #define VK_NO_PROTOTYPES
48 #define WINE_VK_HOST
50 #include "x11drv.h"
51 #include "winreg.h"
52 #include "xcomposite.h"
53 #include "wine/server.h"
54 #include "wine/debug.h"
55 #include "wine/list.h"
56 #include "wine/vulkan.h"
57 #include "wine/vulkan_driver.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
60 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
61 WINE_DECLARE_DEBUG_CHANNEL(winediag);
63 XVisualInfo default_visual = { 0 };
64 XVisualInfo argb_visual = { 0 };
65 Colormap default_colormap = None;
66 XPixmapFormatValues **pixmap_formats;
67 Atom systray_atom = 0;
68 HWND systray_hwnd = 0;
69 unsigned int screen_bpp;
70 Window root_window;
71 BOOL usexvidmode = TRUE;
72 BOOL usexrandr = TRUE;
73 BOOL usexcomposite = TRUE;
74 BOOL use_take_focus = TRUE;
75 BOOL use_primary_selection = FALSE;
76 BOOL use_system_cursors = TRUE;
77 BOOL grab_fullscreen = FALSE;
78 BOOL managed_mode = TRUE;
79 BOOL decorated_mode = TRUE;
80 BOOL private_color_map = FALSE;
81 int primary_monitor = 0;
82 BOOL client_side_graphics = TRUE;
83 BOOL client_side_with_render = TRUE;
84 BOOL shape_layered_windows = TRUE;
85 int copy_default_colors = 128;
86 int alloc_system_colors = 256;
87 int xrender_error_base = 0;
88 char *process_name = NULL;
89 WNDPROC client_foreign_window_proc = NULL;
91 static x11drv_error_callback err_callback; /* current callback for error */
92 static Display *err_callback_display; /* display callback is set for */
93 static void *err_callback_arg; /* error callback argument */
94 static int err_callback_result; /* error callback result */
95 static unsigned long err_serial; /* serial number of first request */
96 static int (*old_error_handler)( Display *, XErrorEvent * );
97 static BOOL use_xim = TRUE;
98 static WCHAR input_style[20];
100 static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
102 #define IS_OPTION_TRUE(ch) \
103 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
104 #define IS_OPTION_FALSE(ch) \
105 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
107 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
109 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
111 "CLIPBOARD",
112 "COMPOUND_TEXT",
113 "EDID",
114 "INCR",
115 "MANAGER",
116 "MULTIPLE",
117 "SELECTION_DATA",
118 "TARGETS",
119 "TEXT",
120 "TIMESTAMP",
121 "UTF8_STRING",
122 "RAW_ASCENT",
123 "RAW_DESCENT",
124 "RAW_CAP_HEIGHT",
125 "WM_PROTOCOLS",
126 "WM_DELETE_WINDOW",
127 "WM_STATE",
128 "WM_TAKE_FOCUS",
129 "DndProtocol",
130 "DndSelection",
131 "_ICC_PROFILE",
132 "_KDE_NET_WM_STATE_SKIP_SWITCHER",
133 "_MOTIF_WM_HINTS",
134 "_NET_STARTUP_INFO_BEGIN",
135 "_NET_STARTUP_INFO",
136 "_NET_SUPPORTED",
137 "_NET_SYSTEM_TRAY_OPCODE",
138 "_NET_SYSTEM_TRAY_S0",
139 "_NET_SYSTEM_TRAY_VISUAL",
140 "_NET_WM_FULLSCREEN_MONITORS",
141 "_NET_WM_ICON",
142 "_NET_WM_MOVERESIZE",
143 "_NET_WM_NAME",
144 "_NET_WM_PID",
145 "_NET_WM_PING",
146 "_NET_WM_STATE",
147 "_NET_WM_STATE_ABOVE",
148 "_NET_WM_STATE_DEMANDS_ATTENTION",
149 "_NET_WM_STATE_FULLSCREEN",
150 "_NET_WM_STATE_MAXIMIZED_HORZ",
151 "_NET_WM_STATE_MAXIMIZED_VERT",
152 "_NET_WM_STATE_SKIP_PAGER",
153 "_NET_WM_STATE_SKIP_TASKBAR",
154 "_NET_WM_USER_TIME",
155 "_NET_WM_USER_TIME_WINDOW",
156 "_NET_WM_WINDOW_OPACITY",
157 "_NET_WM_WINDOW_TYPE",
158 "_NET_WM_WINDOW_TYPE_DIALOG",
159 "_NET_WM_WINDOW_TYPE_NORMAL",
160 "_NET_WM_WINDOW_TYPE_UTILITY",
161 "_NET_WORKAREA",
162 "_GTK_WORKAREAS_D0",
163 "_XEMBED",
164 "_XEMBED_INFO",
165 "XdndAware",
166 "XdndEnter",
167 "XdndPosition",
168 "XdndStatus",
169 "XdndLeave",
170 "XdndFinished",
171 "XdndDrop",
172 "XdndActionCopy",
173 "XdndActionMove",
174 "XdndActionLink",
175 "XdndActionAsk",
176 "XdndActionPrivate",
177 "XdndSelection",
178 "XdndTypeList",
179 "HTML Format",
180 "WCF_DIF",
181 "WCF_ENHMETAFILE",
182 "WCF_HDROP",
183 "WCF_PENDATA",
184 "WCF_RIFF",
185 "WCF_SYLK",
186 "WCF_TIFF",
187 "WCF_WAVE",
188 "image/bmp",
189 "image/gif",
190 "image/jpeg",
191 "image/png",
192 "text/html",
193 "text/plain",
194 "text/rtf",
195 "text/richtext",
196 "text/uri-list"
199 /***********************************************************************
200 * ignore_error
202 * Check if the X error is one we can ignore.
204 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
206 if ((event->request_code == X_SetInputFocus ||
207 event->request_code == X_ChangeWindowAttributes ||
208 event->request_code == X_ConfigureWindow ||
209 event->request_code == X_SendEvent) &&
210 (event->error_code == BadMatch ||
211 event->error_code == BadWindow)) return TRUE;
213 /* the clipboard display interacts with external windows, ignore all errors */
214 if (display == clipboard_display) return TRUE;
216 /* ignore a number of errors on gdi display caused by creating/destroying windows */
217 if (display == gdi_display)
219 if (event->error_code == BadDrawable ||
220 event->error_code == BadGC ||
221 event->error_code == BadWindow)
222 return TRUE;
223 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
224 if (xrender_error_base) /* check for XRender errors */
226 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
228 #endif
230 return FALSE;
234 /***********************************************************************
235 * X11DRV_expect_error
237 * Setup a callback function that will be called on an X error. The
238 * callback must return non-zero if the error is the one it expected.
240 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
242 pthread_mutex_lock( &error_mutex );
243 XLockDisplay( display );
244 err_callback = callback;
245 err_callback_display = display;
246 err_callback_arg = arg;
247 err_callback_result = 0;
248 err_serial = NextRequest(display);
252 /***********************************************************************
253 * X11DRV_check_error
255 * Check if an expected X11 error occurred; return non-zero if yes.
256 * The caller is responsible for calling XSync first if necessary.
258 int X11DRV_check_error(void)
260 int res = err_callback_result;
261 err_callback = NULL;
262 XUnlockDisplay( err_callback_display );
263 pthread_mutex_unlock( &error_mutex );
264 return res;
268 /***********************************************************************
269 * error_handler
271 static int error_handler( Display *display, XErrorEvent *error_evt )
273 if (err_callback && display == err_callback_display &&
274 (!error_evt->serial || error_evt->serial >= err_serial))
276 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
278 TRACE( "got expected error %d req %d\n",
279 error_evt->error_code, error_evt->request_code );
280 return 0;
283 if (ignore_error( display, error_evt ))
285 TRACE( "got ignored error %d req %d\n",
286 error_evt->error_code, error_evt->request_code );
287 return 0;
289 if (TRACE_ON(synchronous))
291 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
292 error_evt->serial, error_evt->request_code );
293 assert( 0 );
295 old_error_handler( display, error_evt );
296 return 0;
299 /***********************************************************************
300 * init_pixmap_formats
302 static void init_pixmap_formats( Display *display )
304 int i, count, max = 32;
305 XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
307 for (i = 0; i < count; i++)
309 TRACE( "depth %u, bpp %u, pad %u\n",
310 formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
311 if (formats[i].depth > max) max = formats[i].depth;
313 pixmap_formats = calloc( 1, sizeof(*pixmap_formats) * (max + 1) );
314 for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
318 HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
320 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
321 OBJECT_ATTRIBUTES attr;
322 HANDLE ret;
324 attr.Length = sizeof(attr);
325 attr.RootDirectory = root;
326 attr.ObjectName = &nameW;
327 attr.Attributes = 0;
328 attr.SecurityDescriptor = NULL;
329 attr.SecurityQualityOfService = NULL;
331 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
335 HKEY open_hkcu_key( const char *name )
337 WCHAR bufferW[256];
338 static HKEY hkcu;
340 if (!hkcu)
342 char buffer[256];
343 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
344 DWORD i, len = sizeof(sid_data);
345 SID *sid;
347 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
348 return 0;
350 sid = ((TOKEN_USER *)sid_data)->User.Sid;
351 len = sprintf( buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
352 (int)MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
353 sid->IdentifierAuthority.Value[4] ),
354 MAKEWORD( sid->IdentifierAuthority.Value[3],
355 sid->IdentifierAuthority.Value[2] )));
356 for (i = 0; i < sid->SubAuthorityCount; i++)
357 len += sprintf( buffer + len, "-%u", (int)sid->SubAuthority[i] );
359 ascii_to_unicode( bufferW, buffer, len );
360 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
363 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
367 ULONG query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
369 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
370 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
372 if (NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
373 info, size, &size ))
374 return 0;
376 return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
380 /***********************************************************************
381 * get_config_key
383 * Get a config key from either the app-specific or the default config
385 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
386 WCHAR *buffer, DWORD size )
388 WCHAR nameW[128];
389 char buf[2048];
390 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
392 asciiz_to_unicode( nameW, name );
394 if (appkey && query_reg_value( appkey, nameW, info, sizeof(buf) ))
396 size = min( info->DataLength, size - sizeof(WCHAR) );
397 memcpy( buffer, info->Data, size );
398 buffer[size / sizeof(WCHAR)] = 0;
399 return 0;
402 if (defkey && query_reg_value( defkey, nameW, info, sizeof(buf) ))
404 size = min( info->DataLength, size - sizeof(WCHAR) );
405 memcpy( buffer, info->Data, size );
406 buffer[size / sizeof(WCHAR)] = 0;
407 return 0;
410 return ERROR_FILE_NOT_FOUND;
414 /***********************************************************************
415 * setup_options
417 * Setup the x11drv options.
419 static void setup_options(void)
421 static const WCHAR x11driverW[] = {'\\','X','1','1',' ','D','r','i','v','e','r',0};
422 WCHAR buffer[MAX_PATH+16], *p, *appname;
423 HKEY hkey, appkey = 0;
424 DWORD len;
426 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
427 hkey = open_hkcu_key( "Software\\Wine\\X11 Driver" );
429 /* open the app-specific key */
431 appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
432 if ((p = wcsrchr( appname, '/' ))) appname = p + 1;
433 if ((p = wcsrchr( appname, '\\' ))) appname = p + 1;
434 len = lstrlenW( appname );
436 if (len && len < MAX_PATH)
438 HKEY tmpkey;
439 int i;
440 for (i = 0; appname[i]; i++) buffer[i] = RtlDowncaseUnicodeChar( appname[i] );
441 buffer[i] = 0;
442 appname = buffer;
443 if ((process_name = malloc( len * 3 + 1 )))
444 ntdll_wcstoumbs( appname, len + 1, process_name, len * 3 + 1, FALSE );
445 memcpy( appname + i, x11driverW, sizeof(x11driverW) );
446 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
447 if ((tmpkey = open_hkcu_key( "Software\\Wine\\AppDefaults" )))
449 appkey = reg_open_key( tmpkey, appname, lstrlenW( appname ) * sizeof(WCHAR) );
450 NtClose( tmpkey );
454 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
455 managed_mode = IS_OPTION_TRUE( buffer[0] );
457 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
458 decorated_mode = IS_OPTION_TRUE( buffer[0] );
460 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
461 usexvidmode = IS_OPTION_TRUE( buffer[0] );
463 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
464 usexrandr = IS_OPTION_TRUE( buffer[0] );
466 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
467 use_take_focus = IS_OPTION_TRUE( buffer[0] );
469 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
470 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
472 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
473 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
475 if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
476 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
478 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
479 default_visual.depth = wcstol( buffer, NULL, 0 );
481 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
482 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
484 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
485 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
487 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
488 use_xim = IS_OPTION_TRUE( buffer[0] );
490 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
491 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
493 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
494 private_color_map = IS_OPTION_TRUE( buffer[0] );
496 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
497 primary_monitor = wcstol( buffer, NULL, 0 );
499 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
500 copy_default_colors = wcstol( buffer, NULL, 0 );
502 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
503 alloc_system_colors = wcstol( buffer, NULL, 0 );
505 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
507 NtClose( appkey );
508 NtClose( hkey );
511 #ifdef SONAME_LIBXCOMPOSITE
513 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
514 MAKE_FUNCPTR(XCompositeQueryExtension)
515 MAKE_FUNCPTR(XCompositeQueryVersion)
516 MAKE_FUNCPTR(XCompositeVersion)
517 MAKE_FUNCPTR(XCompositeRedirectWindow)
518 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
519 MAKE_FUNCPTR(XCompositeUnredirectWindow)
520 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
521 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
522 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
523 #undef MAKE_FUNCPTR
525 static int xcomp_event_base;
526 static int xcomp_error_base;
528 static void X11DRV_XComposite_Init(void)
530 void *xcomposite_handle = dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW);
531 if (!xcomposite_handle)
533 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
534 usexcomposite = FALSE;
535 return;
538 #define LOAD_FUNCPTR(f) \
539 if((p##f = dlsym(xcomposite_handle, #f)) == NULL) goto sym_not_found
540 LOAD_FUNCPTR(XCompositeQueryExtension);
541 LOAD_FUNCPTR(XCompositeQueryVersion);
542 LOAD_FUNCPTR(XCompositeVersion);
543 LOAD_FUNCPTR(XCompositeRedirectWindow);
544 LOAD_FUNCPTR(XCompositeRedirectSubwindows);
545 LOAD_FUNCPTR(XCompositeUnredirectWindow);
546 LOAD_FUNCPTR(XCompositeUnredirectSubwindows);
547 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip);
548 LOAD_FUNCPTR(XCompositeNameWindowPixmap);
549 #undef LOAD_FUNCPTR
551 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
552 &xcomp_error_base)) {
553 TRACE("XComposite extension could not be queried; disabled\n");
554 dlclose(xcomposite_handle);
555 xcomposite_handle = NULL;
556 usexcomposite = FALSE;
557 return;
559 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
560 return;
562 sym_not_found:
563 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
564 dlclose(xcomposite_handle);
565 xcomposite_handle = NULL;
566 usexcomposite = FALSE;
568 #endif /* defined(SONAME_LIBXCOMPOSITE) */
570 static void init_visuals( Display *display, int screen )
572 int count;
573 XVisualInfo *info;
575 argb_visual.screen = screen;
576 argb_visual.class = TrueColor;
577 argb_visual.depth = 32;
578 argb_visual.red_mask = 0xff0000;
579 argb_visual.green_mask = 0x00ff00;
580 argb_visual.blue_mask = 0x0000ff;
582 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
583 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
584 &argb_visual, &count )))
586 argb_visual = *info;
587 XFree( info );
590 default_visual.screen = screen;
591 if (default_visual.depth) /* depth specified */
593 if (default_visual.depth == 32 && argb_visual.visual)
595 default_visual = argb_visual;
597 else if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count )))
599 default_visual = *info;
600 XFree( info );
602 else WARN( "no visual found for depth %d\n", default_visual.depth );
605 if (!default_visual.visual)
607 default_visual.depth = DefaultDepth( display, screen );
608 default_visual.visual = DefaultVisual( display, screen );
609 default_visual.visualid = default_visual.visual->visualid;
610 default_visual.class = default_visual.visual->class;
611 default_visual.red_mask = default_visual.visual->red_mask;
612 default_visual.green_mask = default_visual.visual->green_mask;
613 default_visual.blue_mask = default_visual.visual->blue_mask;
614 default_visual.colormap_size = default_visual.visual->map_entries;
615 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
617 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
619 TRACE( "default visual %lx class %u argb %lx\n",
620 default_visual.visualid, default_visual.class, argb_visual.visualid );
623 /***********************************************************************
624 * X11DRV process initialisation routine
626 static NTSTATUS x11drv_init( void *arg )
628 struct init_params *params = arg;
629 Display *display;
630 void *libx11 = dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL );
632 if (!libx11)
634 ERR( "failed to load %s: %s\n", SONAME_LIBX11, dlerror() );
635 return STATUS_UNSUCCESSFUL;
637 pXGetEventData = dlsym( libx11, "XGetEventData" );
638 pXFreeEventData = dlsym( libx11, "XFreeEventData" );
639 #ifdef SONAME_LIBXEXT
640 dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL );
641 #endif
643 setup_options();
645 /* Open display */
647 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
648 if (!(display = XOpenDisplay( NULL ))) return STATUS_UNSUCCESSFUL;
650 client_foreign_window_proc = params->foreign_window_proc;
652 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
653 root_window = DefaultRootWindow( display );
654 gdi_display = display;
655 old_error_handler = XSetErrorHandler( error_handler );
657 init_pixmap_formats( display );
658 init_visuals( display, DefaultScreen( display ));
659 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
661 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
663 init_win_context();
665 if (TRACE_ON(synchronous)) XSynchronize( display, True );
667 xinerama_init( DisplayWidth( display, default_visual.screen ),
668 DisplayHeight( display, default_visual.screen ));
669 X11DRV_Settings_Init();
671 /* initialize XVidMode */
672 X11DRV_XF86VM_Init();
673 /* initialize XRandR */
674 X11DRV_XRandR_Init();
675 #ifdef SONAME_LIBXCOMPOSITE
676 X11DRV_XComposite_Init();
677 #endif
678 x11drv_xinput2_load();
680 XkbUseExtension( gdi_display, NULL, NULL );
681 X11DRV_InitKeyboard( gdi_display );
682 if (use_xim) use_xim = xim_init( input_style );
684 init_user_driver();
685 X11DRV_DisplayDevices_Init(FALSE);
686 return STATUS_SUCCESS;
690 /***********************************************************************
691 * ThreadDetach (X11DRV.@)
693 void X11DRV_ThreadDetach(void)
695 struct x11drv_thread_data *data = x11drv_thread_data();
697 if (data)
699 vulkan_thread_detach();
700 if (data->xim) XCloseIM( data->xim );
701 if (data->font_set) XFreeFontSet( data->display, data->font_set );
702 XSync( gdi_display, False ); /* make sure XReparentWindow requests have completed before closing the thread display */
703 XCloseDisplay( data->display );
704 free( data );
705 /* clear data in case we get re-entered from user32 before the thread is truly dead */
706 NtUserGetThreadInfo()->driver_data = 0;
711 /* store the display fd into the message queue */
712 static void set_queue_display_fd( Display *display )
714 HANDLE handle;
715 int ret;
717 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
719 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
720 NtTerminateProcess( 0, 1 );
722 SERVER_START_REQ( set_queue_fd )
724 req->handle = wine_server_obj_handle( handle );
725 ret = wine_server_call( req );
727 SERVER_END_REQ;
728 if (ret)
730 MESSAGE( "x11drv: Can't store handle for display fd\n" );
731 NtTerminateProcess( 0, 1 );
733 NtClose( handle );
737 /***********************************************************************
738 * X11DRV thread initialisation routine
740 struct x11drv_thread_data *x11drv_init_thread_data(void)
742 struct x11drv_thread_data *data = x11drv_thread_data();
744 if (data) return data;
746 if (!(data = calloc( 1, sizeof(*data) )))
748 ERR( "could not create data\n" );
749 NtTerminateProcess( 0, 1 );
751 if (!(data->display = XOpenDisplay(NULL)))
753 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));
754 NtTerminateProcess( 0, 1 );
757 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
759 XkbUseExtension( data->display, NULL, NULL );
760 XkbSetDetectableAutoRepeat( data->display, True, NULL );
761 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
763 set_queue_display_fd( data->display );
764 NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
766 if (use_xim) xim_thread_attach( data );
767 x11drv_xinput2_init( data );
769 return data;
773 /***********************************************************************
774 * SystemParametersInfo (X11DRV.@)
776 BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
778 switch (action)
780 case SPI_GETSCREENSAVEACTIVE:
781 if (ptr_param)
783 int timeout, temp;
784 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
785 *(BOOL *)ptr_param = timeout != 0;
786 return TRUE;
788 break;
789 case SPI_SETSCREENSAVEACTIVE:
791 int timeout, interval, prefer_blanking, allow_exposures;
792 static int last_timeout = 15 * 60;
794 XLockDisplay( gdi_display );
795 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
796 &allow_exposures);
797 if (timeout) last_timeout = timeout;
799 timeout = int_param ? last_timeout : 0;
800 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
801 allow_exposures);
802 XUnlockDisplay( gdi_display );
804 break;
806 return FALSE; /* let user32 handle it */
809 NTSTATUS x11drv_client_func( enum x11drv_client_funcs id, const void *params, ULONG size )
811 void *ret_ptr;
812 ULONG ret_len;
813 return KeUserModeCallback( id, params, size, &ret_ptr, &ret_len );
817 const unixlib_entry_t __wine_unix_call_funcs[] =
819 x11drv_init,
820 x11drv_tablet_attach_queue,
821 x11drv_tablet_get_packet,
822 x11drv_tablet_info,
823 x11drv_tablet_load_info,
827 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
830 #ifdef _WIN64
832 static NTSTATUS x11drv_wow64_init( void *arg )
834 struct
836 ULONG foreign_window_proc;
837 } *params32 = arg;
838 struct init_params params;
840 params.foreign_window_proc = UlongToPtr( params32->foreign_window_proc );
841 return x11drv_init( &params );
844 static NTSTATUS x11drv_wow64_tablet_get_packet( void *arg )
846 FIXME( "%p\n", arg );
847 return 0;
850 static NTSTATUS x11drv_wow64_tablet_info( void *arg )
852 struct
854 UINT category;
855 UINT index;
856 ULONG output;
857 } *params32 = arg;
858 struct tablet_info_params params;
860 params.category = params32->category;
861 params.index = params32->index;
862 params.output = UlongToPtr( params32->output );
863 return x11drv_tablet_info( &params );
866 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
868 x11drv_wow64_init,
869 x11drv_tablet_attach_queue,
870 x11drv_wow64_tablet_get_packet,
871 x11drv_wow64_tablet_info,
872 x11drv_tablet_load_info,
875 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );
877 #endif /* _WIN64 */