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
37 #include <X11/cursorfont.h>
39 #include <X11/XKBlib.h>
40 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
41 #include <X11/extensions/Xrender.h>
45 #define WIN32_NO_STATUS
47 #define VK_NO_PROTOTYPES
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
;
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
] =
132 "_KDE_NET_WM_STATE_SKIP_SWITCHER",
134 "_NET_STARTUP_INFO_BEGIN",
137 "_NET_SYSTEM_TRAY_OPCODE",
138 "_NET_SYSTEM_TRAY_S0",
139 "_NET_SYSTEM_TRAY_VISUAL",
140 "_NET_WM_FULLSCREEN_MONITORS",
142 "_NET_WM_MOVERESIZE",
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",
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",
199 /***********************************************************************
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
)
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
;
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 /***********************************************************************
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
;
262 XUnlockDisplay( err_callback_display
);
263 pthread_mutex_unlock( &error_mutex
);
268 /***********************************************************************
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
);
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
);
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
);
295 old_error_handler( display
, error_evt
);
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
;
324 attr
.Length
= sizeof(attr
);
325 attr
.RootDirectory
= root
;
326 attr
.ObjectName
= &nameW
;
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
)
343 DWORD_PTR sid_data
[(sizeof(TOKEN_USER
) + SECURITY_MAX_SID_SIZE
) / sizeof(DWORD_PTR
)];
344 DWORD i
, len
= sizeof(sid_data
);
347 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser
, sid_data
, len
, &len
))
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
,
376 return size
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
380 /***********************************************************************
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
)
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;
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;
410 return ERROR_FILE_NOT_FOUND
;
414 /***********************************************************************
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;
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
)
440 for (i
= 0; appname
[i
]; i
++) buffer
[i
] = RtlDowncaseUnicodeChar( appname
[i
] );
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
) );
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
) );
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
)
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
;
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
);
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
;
559 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base
);
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
)
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
)))
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
;
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
;
630 void *libx11
= dlopen( SONAME_LIBX11
, RTLD_NOW
|RTLD_GLOBAL
);
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
);
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
);
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();
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
);
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();
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
);
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
)
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
);
730 MESSAGE( "x11drv: Can't store handle for display fd\n" );
731 NtTerminateProcess( 0, 1 );
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
);
773 /***********************************************************************
774 * SystemParametersInfo (X11DRV.@)
776 BOOL
X11DRV_SystemParametersInfo( UINT action
, UINT int_param
, void *ptr_param
, UINT flags
)
780 case SPI_GETSCREENSAVEACTIVE
:
784 XGetScreenSaver(gdi_display
, &timeout
, &temp
, &temp
, &temp
);
785 *(BOOL
*)ptr_param
= timeout
!= 0;
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
,
797 if (timeout
) last_timeout
= timeout
;
799 timeout
= int_param
? last_timeout
: 0;
800 XSetScreenSaver(gdi_display
, timeout
, interval
, prefer_blanking
,
802 XUnlockDisplay( gdi_display
);
806 return FALSE
; /* let user32 handle it */
809 NTSTATUS
x11drv_client_func( enum x11drv_client_funcs id
, const void *params
, ULONG size
)
813 return KeUserModeCallback( id
, params
, size
, &ret_ptr
, &ret_len
);
817 const unixlib_entry_t __wine_unix_call_funcs
[] =
820 x11drv_tablet_attach_queue
,
821 x11drv_tablet_get_packet
,
823 x11drv_tablet_load_info
,
827 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs
) == unix_funcs_count
);
832 static NTSTATUS
x11drv_wow64_init( void *arg
)
836 ULONG foreign_window_proc
;
838 struct init_params params
;
840 params
.foreign_window_proc
= UlongToPtr( params32
->foreign_window_proc
);
841 return x11drv_init( ¶ms
);
844 static NTSTATUS
x11drv_wow64_tablet_get_packet( void *arg
)
846 FIXME( "%p\n", arg
);
850 static NTSTATUS
x11drv_wow64_tablet_info( void *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( ¶ms
);
866 const unixlib_entry_t __wine_unix_call_wow64_funcs
[] =
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
);