winex11: Introduce X11DRV_CALL macro.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blobcc565bd30a70d20d10dad7a9adb7db9dffc5476d
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"
24 #include <fcntl.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/time.h>
30 #include <unistd.h>
31 #include <dlfcn.h>
32 #include <X11/cursorfont.h>
33 #include <X11/Xlib.h>
34 #ifdef HAVE_XKB
35 #include <X11/XKBlib.h>
36 #endif
37 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
38 #include <X11/extensions/Xrender.h>
39 #endif
41 #include "ntstatus.h"
42 #define WIN32_NO_STATUS
43 #include "windef.h"
44 #include "winbase.h"
45 #include "winreg.h"
47 #include "x11drv.h"
48 #include "xcomposite.h"
49 #include "wine/server.h"
50 #include "wine/unicode.h"
51 #include "wine/debug.h"
52 #include "wine/list.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
55 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
56 WINE_DECLARE_DEBUG_CHANNEL(winediag);
58 XVisualInfo default_visual = { 0 };
59 XVisualInfo argb_visual = { 0 };
60 Colormap default_colormap = None;
61 XPixmapFormatValues **pixmap_formats;
62 unsigned int screen_bpp;
63 Window root_window;
64 BOOL usexvidmode = TRUE;
65 BOOL usexrandr = TRUE;
66 BOOL usexcomposite = TRUE;
67 BOOL use_xkb = TRUE;
68 BOOL use_take_focus = TRUE;
69 BOOL use_primary_selection = FALSE;
70 BOOL use_system_cursors = TRUE;
71 BOOL show_systray = TRUE;
72 BOOL grab_pointer = TRUE;
73 BOOL grab_fullscreen = FALSE;
74 BOOL managed_mode = TRUE;
75 BOOL decorated_mode = TRUE;
76 BOOL private_color_map = FALSE;
77 int primary_monitor = 0;
78 BOOL client_side_graphics = TRUE;
79 BOOL client_side_with_render = TRUE;
80 BOOL shape_layered_windows = TRUE;
81 int copy_default_colors = 128;
82 int alloc_system_colors = 256;
83 int xrender_error_base = 0;
84 char *process_name = NULL;
86 static x11drv_error_callback err_callback; /* current callback for error */
87 static Display *err_callback_display; /* display callback is set for */
88 static void *err_callback_arg; /* error callback argument */
89 static int err_callback_result; /* error callback result */
90 static unsigned long err_serial; /* serial number of first request */
91 static int (*old_error_handler)( Display *, XErrorEvent * );
92 static BOOL use_xim = TRUE;
93 static WCHAR input_style[20];
95 static pthread_mutex_t d3dkmt_mutex = PTHREAD_MUTEX_INITIALIZER;
96 static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
98 struct d3dkmt_vidpn_source
100 D3DKMT_VIDPNSOURCEOWNER_TYPE type; /* VidPN source owner type */
101 D3DDDI_VIDEO_PRESENT_SOURCE_ID id; /* VidPN present source id */
102 D3DKMT_HANDLE device; /* Kernel mode device context */
103 struct list entry; /* List entry */
106 static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */
108 #define IS_OPTION_TRUE(ch) \
109 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
110 #define IS_OPTION_FALSE(ch) \
111 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
113 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
115 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
117 "CLIPBOARD",
118 "COMPOUND_TEXT",
119 "EDID",
120 "INCR",
121 "MANAGER",
122 "MULTIPLE",
123 "SELECTION_DATA",
124 "TARGETS",
125 "TEXT",
126 "TIMESTAMP",
127 "UTF8_STRING",
128 "RAW_ASCENT",
129 "RAW_DESCENT",
130 "RAW_CAP_HEIGHT",
131 "Rel X",
132 "Rel Y",
133 "WM_PROTOCOLS",
134 "WM_DELETE_WINDOW",
135 "WM_STATE",
136 "WM_TAKE_FOCUS",
137 "DndProtocol",
138 "DndSelection",
139 "_ICC_PROFILE",
140 "_MOTIF_WM_HINTS",
141 "_NET_STARTUP_INFO_BEGIN",
142 "_NET_STARTUP_INFO",
143 "_NET_SUPPORTED",
144 "_NET_SYSTEM_TRAY_OPCODE",
145 "_NET_SYSTEM_TRAY_S0",
146 "_NET_SYSTEM_TRAY_VISUAL",
147 "_NET_WM_ICON",
148 "_NET_WM_MOVERESIZE",
149 "_NET_WM_NAME",
150 "_NET_WM_PID",
151 "_NET_WM_PING",
152 "_NET_WM_STATE",
153 "_NET_WM_STATE_ABOVE",
154 "_NET_WM_STATE_DEMANDS_ATTENTION",
155 "_NET_WM_STATE_FULLSCREEN",
156 "_NET_WM_STATE_MAXIMIZED_HORZ",
157 "_NET_WM_STATE_MAXIMIZED_VERT",
158 "_NET_WM_STATE_SKIP_PAGER",
159 "_NET_WM_STATE_SKIP_TASKBAR",
160 "_NET_WM_USER_TIME",
161 "_NET_WM_USER_TIME_WINDOW",
162 "_NET_WM_WINDOW_OPACITY",
163 "_NET_WM_WINDOW_TYPE",
164 "_NET_WM_WINDOW_TYPE_DIALOG",
165 "_NET_WM_WINDOW_TYPE_NORMAL",
166 "_NET_WM_WINDOW_TYPE_UTILITY",
167 "_NET_WORKAREA",
168 "_GTK_WORKAREAS_D0",
169 "_XEMBED",
170 "_XEMBED_INFO",
171 "XdndAware",
172 "XdndEnter",
173 "XdndPosition",
174 "XdndStatus",
175 "XdndLeave",
176 "XdndFinished",
177 "XdndDrop",
178 "XdndActionCopy",
179 "XdndActionMove",
180 "XdndActionLink",
181 "XdndActionAsk",
182 "XdndActionPrivate",
183 "XdndSelection",
184 "XdndTypeList",
185 "HTML Format",
186 "WCF_DIF",
187 "WCF_ENHMETAFILE",
188 "WCF_HDROP",
189 "WCF_PENDATA",
190 "WCF_RIFF",
191 "WCF_SYLK",
192 "WCF_TIFF",
193 "WCF_WAVE",
194 "image/bmp",
195 "image/gif",
196 "image/jpeg",
197 "image/png",
198 "text/html",
199 "text/plain",
200 "text/rtf",
201 "text/richtext",
202 "text/uri-list"
205 /***********************************************************************
206 * ignore_error
208 * Check if the X error is one we can ignore.
210 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
212 if ((event->request_code == X_SetInputFocus ||
213 event->request_code == X_ChangeWindowAttributes ||
214 event->request_code == X_SendEvent) &&
215 (event->error_code == BadMatch ||
216 event->error_code == BadWindow)) return TRUE;
218 /* the clipboard display interacts with external windows, ignore all errors */
219 if (display == clipboard_display) return TRUE;
221 /* ignore a number of errors on gdi display caused by creating/destroying windows */
222 if (display == gdi_display)
224 if (event->error_code == BadDrawable ||
225 event->error_code == BadGC ||
226 event->error_code == BadWindow)
227 return TRUE;
228 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
229 if (xrender_error_base) /* check for XRender errors */
231 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
233 #endif
235 return FALSE;
239 /***********************************************************************
240 * X11DRV_expect_error
242 * Setup a callback function that will be called on an X error. The
243 * callback must return non-zero if the error is the one it expected.
245 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
247 pthread_mutex_lock( &error_mutex );
248 err_callback = callback;
249 err_callback_display = display;
250 err_callback_arg = arg;
251 err_callback_result = 0;
252 err_serial = NextRequest(display);
256 /***********************************************************************
257 * X11DRV_check_error
259 * Check if an expected X11 error occurred; return non-zero if yes.
260 * The caller is responsible for calling XSync first if necessary.
262 int X11DRV_check_error(void)
264 int res = err_callback_result;
265 err_callback = NULL;
266 pthread_mutex_unlock( &error_mutex );
267 return res;
271 /***********************************************************************
272 * error_handler
274 static int error_handler( Display *display, XErrorEvent *error_evt )
276 if (err_callback && display == err_callback_display &&
277 (long)(error_evt->serial - err_serial) >= 0)
279 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
281 TRACE( "got expected error %d req %d\n",
282 error_evt->error_code, error_evt->request_code );
283 return 0;
286 if (ignore_error( display, error_evt ))
288 TRACE( "got ignored error %d req %d\n",
289 error_evt->error_code, error_evt->request_code );
290 return 0;
292 if (TRACE_ON(synchronous))
294 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
295 error_evt->serial, error_evt->request_code );
296 DebugBreak(); /* force an entry in the debugger */
298 old_error_handler( display, error_evt );
299 return 0;
302 /***********************************************************************
303 * init_pixmap_formats
305 static void init_pixmap_formats( Display *display )
307 int i, count, max = 32;
308 XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
310 for (i = 0; i < count; i++)
312 TRACE( "depth %u, bpp %u, pad %u\n",
313 formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
314 if (formats[i].depth > max) max = formats[i].depth;
316 pixmap_formats = calloc( 1, sizeof(*pixmap_formats) * (max + 1) );
317 for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
321 HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
323 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
324 OBJECT_ATTRIBUTES attr;
325 HANDLE ret;
327 attr.Length = sizeof(attr);
328 attr.RootDirectory = root;
329 attr.ObjectName = &nameW;
330 attr.Attributes = 0;
331 attr.SecurityDescriptor = NULL;
332 attr.SecurityQualityOfService = NULL;
334 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
338 HKEY open_hkcu_key( const char *name )
340 WCHAR bufferW[256];
341 static HKEY hkcu;
343 if (!hkcu)
345 char buffer[256];
346 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
347 DWORD i, len = sizeof(sid_data);
348 SID *sid;
350 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
351 return 0;
353 sid = ((TOKEN_USER *)sid_data)->User.Sid;
354 len = sprintf( buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
355 MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
356 sid->IdentifierAuthority.Value[4] ),
357 MAKEWORD( sid->IdentifierAuthority.Value[3],
358 sid->IdentifierAuthority.Value[2] )));
359 for (i = 0; i < sid->SubAuthorityCount; i++)
360 len += sprintf( buffer + len, "-%u", sid->SubAuthority[i] );
362 ascii_to_unicode( bufferW, buffer, len );
363 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
366 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
370 ULONG query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
372 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
373 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
375 if (NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
376 info, size, &size ))
377 return 0;
379 return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
383 /***********************************************************************
384 * get_config_key
386 * Get a config key from either the app-specific or the default config
388 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
389 WCHAR *buffer, DWORD size )
391 WCHAR nameW[128];
392 char buf[2048];
393 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
395 asciiz_to_unicode( nameW, name );
397 if (appkey && query_reg_value( appkey, nameW, info, sizeof(buf) ))
399 size = min( info->DataLength, size - sizeof(WCHAR) );
400 memcpy( buffer, info->Data, size );
401 buffer[size / sizeof(WCHAR)] = 0;
402 return 0;
405 if (defkey && query_reg_value( defkey, nameW, info, sizeof(buf) ))
407 size = min( info->DataLength, size - sizeof(WCHAR) );
408 memcpy( buffer, info->Data, size );
409 buffer[size / sizeof(WCHAR)] = 0;
410 return 0;
413 return ERROR_FILE_NOT_FOUND;
417 /***********************************************************************
418 * setup_options
420 * Setup the x11drv options.
422 static void setup_options(void)
424 static const WCHAR x11driverW[] = {'\\','X','1','1',' ','D','r','i','v','e','r',0};
425 WCHAR buffer[MAX_PATH+16];
426 HKEY hkey, appkey = 0;
427 DWORD len;
429 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
430 hkey = open_hkcu_key( "Software\\Wine\\X11 Driver" );
432 /* open the app-specific key */
434 len = GetModuleFileNameW( 0, buffer, MAX_PATH );
435 if (len && len < MAX_PATH)
437 HKEY tmpkey;
438 WCHAR *p, *appname = buffer;
439 if ((p = strrchrW( appname, '/' ))) appname = p + 1;
440 if ((p = strrchrW( appname, '\\' ))) appname = p + 1;
441 CharLowerW(appname);
442 len = WideCharToMultiByte( CP_UNIXCP, 0, appname, -1, NULL, 0, NULL, NULL );
443 if ((process_name = malloc( len )))
444 WideCharToMultiByte( CP_UNIXCP, 0, appname, -1, process_name, len, NULL, NULL );
445 strcatW( appname, 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, "ShowSystray", buffer, sizeof(buffer) ))
476 show_systray = IS_OPTION_TRUE( buffer[0] );
478 if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
479 grab_pointer = IS_OPTION_TRUE( buffer[0] );
481 if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
482 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
484 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
485 default_visual.depth = strtolW( buffer, NULL, 0 );
487 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
488 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
490 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
491 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
493 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
494 use_xim = IS_OPTION_TRUE( buffer[0] );
496 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
497 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
499 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
500 private_color_map = IS_OPTION_TRUE( buffer[0] );
502 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
503 primary_monitor = strtolW( buffer, NULL, 0 );
505 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
506 copy_default_colors = strtolW( buffer, NULL, 0 );
508 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
509 alloc_system_colors = strtolW( buffer, NULL, 0 );
511 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
513 NtClose( appkey );
514 NtClose( hkey );
517 #ifdef SONAME_LIBXCOMPOSITE
519 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
520 MAKE_FUNCPTR(XCompositeQueryExtension)
521 MAKE_FUNCPTR(XCompositeQueryVersion)
522 MAKE_FUNCPTR(XCompositeVersion)
523 MAKE_FUNCPTR(XCompositeRedirectWindow)
524 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
525 MAKE_FUNCPTR(XCompositeUnredirectWindow)
526 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
527 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
528 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
529 #undef MAKE_FUNCPTR
531 static int xcomp_event_base;
532 static int xcomp_error_base;
534 static void X11DRV_XComposite_Init(void)
536 void *xcomposite_handle = dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW);
537 if (!xcomposite_handle)
539 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
540 usexcomposite = FALSE;
541 return;
544 #define LOAD_FUNCPTR(f) \
545 if((p##f = dlsym(xcomposite_handle, #f)) == NULL) goto sym_not_found
546 LOAD_FUNCPTR(XCompositeQueryExtension);
547 LOAD_FUNCPTR(XCompositeQueryVersion);
548 LOAD_FUNCPTR(XCompositeVersion);
549 LOAD_FUNCPTR(XCompositeRedirectWindow);
550 LOAD_FUNCPTR(XCompositeRedirectSubwindows);
551 LOAD_FUNCPTR(XCompositeUnredirectWindow);
552 LOAD_FUNCPTR(XCompositeUnredirectSubwindows);
553 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip);
554 LOAD_FUNCPTR(XCompositeNameWindowPixmap);
555 #undef LOAD_FUNCPTR
557 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
558 &xcomp_error_base)) {
559 TRACE("XComposite extension could not be queried; disabled\n");
560 dlclose(xcomposite_handle);
561 xcomposite_handle = NULL;
562 usexcomposite = FALSE;
563 return;
565 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
566 return;
568 sym_not_found:
569 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
570 dlclose(xcomposite_handle);
571 xcomposite_handle = NULL;
572 usexcomposite = FALSE;
574 #endif /* defined(SONAME_LIBXCOMPOSITE) */
576 static void init_visuals( Display *display, int screen )
578 int count;
579 XVisualInfo *info;
581 argb_visual.screen = screen;
582 argb_visual.class = TrueColor;
583 argb_visual.depth = 32;
584 argb_visual.red_mask = 0xff0000;
585 argb_visual.green_mask = 0x00ff00;
586 argb_visual.blue_mask = 0x0000ff;
588 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
589 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
590 &argb_visual, &count )))
592 argb_visual = *info;
593 XFree( info );
596 default_visual.screen = screen;
597 if (default_visual.depth) /* depth specified */
599 if (default_visual.depth == 32 && argb_visual.visual)
601 default_visual = argb_visual;
603 else if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count )))
605 default_visual = *info;
606 XFree( info );
608 else WARN( "no visual found for depth %d\n", default_visual.depth );
611 if (!default_visual.visual)
613 default_visual.depth = DefaultDepth( display, screen );
614 default_visual.visual = DefaultVisual( display, screen );
615 default_visual.visualid = default_visual.visual->visualid;
616 default_visual.class = default_visual.visual->class;
617 default_visual.red_mask = default_visual.visual->red_mask;
618 default_visual.green_mask = default_visual.visual->green_mask;
619 default_visual.blue_mask = default_visual.visual->blue_mask;
620 default_visual.colormap_size = default_visual.visual->map_entries;
621 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
623 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
625 TRACE( "default visual %lx class %u argb %lx\n",
626 default_visual.visualid, default_visual.class, argb_visual.visualid );
629 /***********************************************************************
630 * X11DRV process initialisation routine
632 static NTSTATUS x11drv_init( void *arg )
634 Display *display;
635 void *libx11 = dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL );
637 if (!libx11)
639 ERR( "failed to load %s: %s\n", SONAME_LIBX11, dlerror() );
640 return STATUS_UNSUCCESSFUL;
642 pXGetEventData = dlsym( libx11, "XGetEventData" );
643 pXFreeEventData = dlsym( libx11, "XFreeEventData" );
644 #ifdef SONAME_LIBXEXT
645 dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL );
646 #endif
648 setup_options();
650 /* Open display */
652 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
653 if (!(display = XOpenDisplay( NULL ))) return STATUS_UNSUCCESSFUL;
655 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
656 root_window = DefaultRootWindow( display );
657 gdi_display = display;
658 old_error_handler = XSetErrorHandler( error_handler );
660 init_pixmap_formats( display );
661 init_visuals( display, DefaultScreen( display ));
662 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
664 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
666 init_win_context();
668 if (TRACE_ON(synchronous)) XSynchronize( display, True );
670 xinerama_init( DisplayWidth( display, default_visual.screen ),
671 DisplayHeight( display, default_visual.screen ));
672 X11DRV_Settings_Init();
674 /* initialize XVidMode */
675 X11DRV_XF86VM_Init();
676 /* initialize XRandR */
677 X11DRV_XRandR_Init();
678 #ifdef SONAME_LIBXCOMPOSITE
679 X11DRV_XComposite_Init();
680 #endif
681 X11DRV_XInput2_Init();
683 #ifdef HAVE_XKB
684 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
685 #endif
686 X11DRV_InitKeyboard( gdi_display );
687 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
689 init_user_driver();
690 X11DRV_DisplayDevices_Init(FALSE);
691 return STATUS_SUCCESS;
695 /***********************************************************************
696 * ThreadDetach (X11DRV.@)
698 void X11DRV_ThreadDetach(void)
700 struct x11drv_thread_data *data = x11drv_thread_data();
702 if (data)
704 vulkan_thread_detach();
705 if (data->xim) XCloseIM( data->xim );
706 if (data->font_set) XFreeFontSet( data->display, data->font_set );
707 XCloseDisplay( data->display );
708 free( data );
709 /* clear data in case we get re-entered from user32 before the thread is truly dead */
710 NtUserGetThreadInfo()->driver_data = NULL;
715 /* store the display fd into the message queue */
716 static void set_queue_display_fd( Display *display )
718 HANDLE handle;
719 int ret;
721 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
723 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
724 NtTerminateProcess( 0, 1 );
726 SERVER_START_REQ( set_queue_fd )
728 req->handle = wine_server_obj_handle( handle );
729 ret = wine_server_call( req );
731 SERVER_END_REQ;
732 if (ret)
734 MESSAGE( "x11drv: Can't store handle for display fd\n" );
735 NtTerminateProcess( 0, 1 );
737 NtClose( handle );
741 /***********************************************************************
742 * X11DRV thread initialisation routine
744 struct x11drv_thread_data *x11drv_init_thread_data(void)
746 struct x11drv_thread_data *data = x11drv_thread_data();
748 if (data) return data;
750 if (!(data = calloc( 1, sizeof(*data) )))
752 ERR( "could not create data\n" );
753 NtTerminateProcess( 0, 1 );
755 if (!(data->display = XOpenDisplay(NULL)))
757 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));
758 NtTerminateProcess( 0, 1 );
761 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
763 #ifdef HAVE_XKB
764 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
765 XkbSetDetectableAutoRepeat( data->display, True, NULL );
766 #endif
768 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
770 set_queue_display_fd( data->display );
771 NtUserGetThreadInfo()->driver_data = data;
773 if (use_xim) X11DRV_SetupXIM();
775 return data;
779 /***********************************************************************
780 * SystemParametersInfo (X11DRV.@)
782 BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
784 switch (action)
786 case SPI_GETSCREENSAVEACTIVE:
787 if (ptr_param)
789 int timeout, temp;
790 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
791 *(BOOL *)ptr_param = timeout != 0;
792 return TRUE;
794 break;
795 case SPI_SETSCREENSAVEACTIVE:
797 int timeout, interval, prefer_blanking, allow_exposures;
798 static int last_timeout = 15 * 60;
800 XLockDisplay( gdi_display );
801 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
802 &allow_exposures);
803 if (timeout) last_timeout = timeout;
805 timeout = int_param ? last_timeout : 0;
806 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
807 allow_exposures);
808 XUnlockDisplay( gdi_display );
810 break;
812 return FALSE; /* let user32 handle it */
815 /**********************************************************************
816 * X11DRV_D3DKMTSetVidPnSourceOwner
818 NTSTATUS CDECL X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
820 struct d3dkmt_vidpn_source *source, *source2;
821 NTSTATUS status = STATUS_SUCCESS;
822 BOOL found;
823 UINT i;
825 TRACE("(%p)\n", desc);
827 pthread_mutex_lock( &d3dkmt_mutex );
829 /* Check parameters */
830 for (i = 0; i < desc->VidPnSourceCount; ++i)
832 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
834 if (source->id == desc->pVidPnSourceId[i])
836 /* Same device */
837 if (source->device == desc->hDevice)
839 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
840 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED
841 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
842 || (source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED
843 && desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE))
845 status = STATUS_INVALID_PARAMETER;
846 goto done;
849 /* Different devices */
850 else
852 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
853 || source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED)
854 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
855 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
857 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
858 goto done;
864 /* On Windows, it seems that all video present sources are owned by DMM clients, so any attempt to set
865 * D3DKMT_VIDPNSOURCEOWNER_SHARED come back STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */
866 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED)
868 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
869 goto done;
872 /* FIXME: D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI unsupported */
873 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI || desc->pType[i] > D3DKMT_VIDPNSOURCEOWNER_EMULATED)
875 status = STATUS_INVALID_PARAMETER;
876 goto done;
880 /* Remove owner */
881 if (!desc->VidPnSourceCount && !desc->pType && !desc->pVidPnSourceId)
883 LIST_FOR_EACH_ENTRY_SAFE( source, source2, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
885 if (source->device == desc->hDevice)
887 list_remove( &source->entry );
888 free( source );
891 goto done;
894 /* Add owner */
895 for (i = 0; i < desc->VidPnSourceCount; ++i)
897 found = FALSE;
898 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
900 if (source->device == desc->hDevice && source->id == desc->pVidPnSourceId[i])
902 found = TRUE;
903 break;
907 if (found)
908 source->type = desc->pType[i];
909 else
911 source = malloc( sizeof( *source ) );
912 if (!source)
914 status = STATUS_NO_MEMORY;
915 goto done;
918 source->id = desc->pVidPnSourceId[i];
919 source->type = desc->pType[i];
920 source->device = desc->hDevice;
921 list_add_tail( &d3dkmt_vidpn_sources, &source->entry );
925 done:
926 pthread_mutex_unlock( &d3dkmt_mutex );
927 return status;
930 /**********************************************************************
931 * X11DRV_D3DKMTCheckVidPnExclusiveOwnership
933 NTSTATUS CDECL X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
935 struct d3dkmt_vidpn_source *source;
937 TRACE("(%p)\n", desc);
939 if (!desc || !desc->hAdapter)
940 return STATUS_INVALID_PARAMETER;
942 pthread_mutex_lock( &d3dkmt_mutex );
943 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
945 if (source->id == desc->VidPnSourceId && source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE)
947 pthread_mutex_unlock( &d3dkmt_mutex );
948 return STATUS_GRAPHICS_PRESENT_OCCLUDED;
951 pthread_mutex_unlock( &d3dkmt_mutex );
952 return STATUS_SUCCESS;
956 const unixlib_entry_t __wine_unix_call_funcs[] =
958 x11drv_clipboard_message,
959 x11drv_create_desktop,
960 x11drv_init,
961 x11drv_tablet_attach_queue,
962 x11drv_tablet_get_packet,
963 x11drv_tablet_info,
964 x11drv_tablet_load_info,
968 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
971 /* FIXME: Use __wine_unix_call instead */
972 NTSTATUS x11drv_unix_call( enum x11drv_funcs code, void *params )
974 return __wine_unix_call_funcs[code]( params );