2000-03-19 13:08:09 +01:00
/*
* X11DRV initialization code
2000-03-20 19:21:19 +01:00
*
* Copyright 1998 Patrik Stridvall
* Copyright 2000 Alexandre Julliard
2002-03-10 00:29:33 +01:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
2006-05-18 14:49:52 +02:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2000-03-19 13:08:09 +01:00
*/
2000-03-20 19:21:19 +01:00
2000-05-24 01:38:32 +02:00
# include "config.h"
2007-09-23 03:19:08 +02:00
# include "wine/port.h"
2000-05-24 01:38:32 +02:00
2000-04-04 21:57:23 +02:00
# include <fcntl.h>
2003-09-06 01:08:26 +02:00
# include <stdarg.h>
2000-03-19 13:08:09 +01:00
# include <stdio.h>
2000-03-20 19:21:19 +01:00
# include <stdlib.h>
2000-11-12 04:41:47 +01:00
# include <string.h>
2002-08-17 02:43:16 +02:00
# ifdef HAVE_SYS_TIME_H
# include <sys / time.h>
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
2000-03-25 18:30:13 +01:00
# include <X11/cursorfont.h>
2003-11-21 22:50:59 +01:00
# include <X11/Xlib.h>
2003-03-23 21:07:55 +01:00
# ifdef HAVE_XKB
# include <X11/XKBlib.h>
# endif
2006-04-01 14:21:31 +02:00
# ifdef HAVE_X11_EXTENSIONS_XRENDER_H
# include <X11/extensions/Xrender.h>
# endif
2000-03-19 13:08:09 +01:00
2003-09-06 01:08:26 +02:00
# include "windef.h"
2000-03-19 13:08:09 +01:00
# include "winbase.h"
2000-05-15 04:46:44 +02:00
# include "winreg.h"
2000-03-20 19:21:19 +01:00
2000-03-19 13:08:09 +01:00
# include "x11drv.h"
2001-02-14 01:27:34 +01:00
# include "xvidmode.h"
2003-10-16 02:21:42 +02:00
# include "xrandr.h"
2007-09-23 03:19:08 +02:00
# include "xcomposite.h"
2002-05-30 22:40:02 +02:00
# include "wine/server.h"
# include "wine/debug.h"
2007-09-23 03:19:08 +02:00
# include "wine/library.h"
2000-03-19 13:08:09 +01:00
2002-03-10 00:29:33 +01:00
WINE_DEFAULT_DEBUG_CHANNEL ( x11drv ) ;
2006-02-24 21:05:44 +01:00
WINE_DECLARE_DEBUG_CHANNEL ( synchronous ) ;
2009-12-08 13:11:20 +01:00
WINE_DECLARE_DEBUG_CHANNEL ( winediag ) ;
2000-03-20 19:21:19 +01:00
2003-08-13 01:50:54 +02:00
static CRITICAL_SECTION X11DRV_CritSection ;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0 , 0 , & X11DRV_CritSection ,
{ & critsect_debug . ProcessLocksList , & critsect_debug . ProcessLocksList } ,
2005-09-09 12:19:44 +02:00
0 , 0 , { ( DWORD_PTR ) ( __FILE__ " : X11DRV_CritSection " ) }
2003-08-13 01:50:54 +02:00
} ;
static CRITICAL_SECTION X11DRV_CritSection = { & critsect_debug , - 1 , 0 , 0 , 0 , 0 } ;
2001-01-17 21:22:22 +01:00
2000-03-25 15:05:06 +01:00
Screen * screen ;
Visual * visual ;
2000-08-01 01:32:47 +02:00
unsigned int screen_width ;
unsigned int screen_height ;
2007-12-16 14:00:45 +01:00
unsigned int screen_bpp ;
2000-08-01 01:32:47 +02:00
unsigned int screen_depth ;
2006-10-23 14:37:17 +02:00
RECT virtual_screen_rect ;
2000-03-25 15:05:06 +01:00
Window root_window ;
2004-06-14 18:58:38 +02:00
int dxgrab = 0 ;
2006-04-04 20:10:02 +02:00
int usexvidmode = 1 ;
2004-06-14 18:58:38 +02:00
int usexrandr = 1 ;
2007-09-23 03:19:08 +02:00
int usexcomposite = 1 ;
2003-03-23 21:07:55 +01:00
int use_xkb = 1 ;
2002-09-19 01:09:50 +02:00
int use_take_focus = 1 ;
2005-04-21 19:31:50 +02:00
int use_primary_selection = 0 ;
2002-05-23 18:32:32 +02:00
int managed_mode = 1 ;
2008-04-10 21:53:45 +02:00
int decorated_mode = 1 ;
2005-06-14 20:12:15 +02:00
int private_color_map = 0 ;
2006-10-23 14:37:17 +02:00
int primary_monitor = 0 ;
2002-11-14 23:31:34 +01:00
int client_side_with_core = 1 ;
int client_side_with_render = 1 ;
int client_side_antialias_with_core = 1 ;
int client_side_antialias_with_render = 1 ;
2005-06-14 20:12:15 +02:00
int copy_default_colors = 128 ;
int alloc_system_colors = 256 ;
2005-06-01 13:08:39 +02:00
DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES ;
2006-04-01 14:21:31 +02:00
int xrender_error_base = 0 ;
2008-05-01 10:56:34 +02:00
HMODULE x11drv_module = 0 ;
2000-03-20 19:21:19 +01:00
2002-04-24 23:32:11 +02:00
static x11drv_error_callback err_callback ; /* current callback for error */
static Display * err_callback_display ; /* display callback is set for */
static void * err_callback_arg ; /* error callback argument */
static int err_callback_result ; /* error callback result */
2003-11-09 01:34:43 +01:00
static unsigned long err_serial ; /* serial number of first request */
2002-04-24 23:32:11 +02:00
static int ( * old_error_handler ) ( Display * , XErrorEvent * ) ;
2004-01-21 03:22:26 +01:00
static int use_xim = 1 ;
static char input_style [ 20 ] ;
2002-04-24 23:32:11 +02:00
2001-07-23 02:04:00 +02:00
# define IS_OPTION_TRUE(ch) \
( ( ch ) = = ' y ' | | ( ch ) = = ' Y ' | | ( ch ) = = ' t ' | | ( ch ) = = ' T ' | | ( ch ) = = ' 1 ' )
# define IS_OPTION_FALSE(ch) \
( ( ch ) = = ' n ' | | ( ch ) = = ' N ' | | ( ch ) = = ' f ' | | ( ch ) = = ' F ' | | ( ch ) = = ' 0 ' )
2005-07-07 19:30:57 +02:00
Atom X11DRV_Atoms [ NB_XATOMS - FIRST_XATOM ] ;
static const char * const atom_names [ NB_XATOMS - FIRST_XATOM ] =
{
" CLIPBOARD " ,
" COMPOUND_TEXT " ,
2008-10-31 04:18:00 +01:00
" INCR " ,
2005-07-07 19:30:57 +02:00
" MULTIPLE " ,
" SELECTION_DATA " ,
" TARGETS " ,
" TEXT " ,
" UTF8_STRING " ,
" RAW_ASCENT " ,
" RAW_DESCENT " ,
" RAW_CAP_HEIGHT " ,
" WM_PROTOCOLS " ,
" WM_DELETE_WINDOW " ,
2008-02-27 19:11:43 +01:00
" WM_STATE " ,
2005-07-07 19:30:57 +02:00
" WM_TAKE_FOCUS " ,
" DndProtocol " ,
" DndSelection " ,
2008-03-05 15:57:39 +01:00
" _ICC_PROFILE " ,
2005-07-07 19:30:57 +02:00
" _MOTIF_WM_HINTS " ,
2009-01-06 19:59:07 +01:00
" _NET_STARTUP_INFO_BEGIN " ,
" _NET_STARTUP_INFO " ,
2008-03-12 17:29:28 +01:00
" _NET_SUPPORTED " ,
2006-08-23 02:14:11 +02:00
" _NET_SYSTEM_TRAY_OPCODE " ,
" _NET_SYSTEM_TRAY_S0 " ,
2005-07-07 19:30:57 +02:00
" _NET_WM_MOVERESIZE " ,
2006-06-19 19:25:54 +02:00
" _NET_WM_NAME " ,
2005-07-07 19:30:57 +02:00
" _NET_WM_PID " ,
" _NET_WM_PING " ,
2006-06-19 19:25:54 +02:00
" _NET_WM_STATE " ,
2007-10-31 18:13:20 +01:00
" _NET_WM_STATE_ABOVE " ,
2006-06-19 19:25:54 +02:00
" _NET_WM_STATE_FULLSCREEN " ,
2008-03-01 13:30:58 +01:00
" _NET_WM_STATE_MAXIMIZED_HORZ " ,
" _NET_WM_STATE_MAXIMIZED_VERT " ,
2007-10-11 11:40:55 +02:00
" _NET_WM_STATE_SKIP_PAGER " ,
" _NET_WM_STATE_SKIP_TASKBAR " ,
2008-09-12 15:54:02 +02:00
" _NET_WM_WINDOW_OPACITY " ,
2005-07-07 19:30:57 +02:00
" _NET_WM_WINDOW_TYPE " ,
2006-10-11 17:32:22 +02:00
" _NET_WM_WINDOW_TYPE_DIALOG " ,
" _NET_WM_WINDOW_TYPE_NORMAL " ,
2005-07-07 19:30:57 +02:00
" _NET_WM_WINDOW_TYPE_UTILITY " ,
2008-10-01 21:00:18 +02:00
" _NET_WORKAREA " ,
2006-08-23 02:14:11 +02:00
" _XEMBED_INFO " ,
2005-07-07 19:30:57 +02:00
" XdndAware " ,
" XdndEnter " ,
" XdndPosition " ,
" XdndStatus " ,
" XdndLeave " ,
" XdndFinished " ,
" XdndDrop " ,
" XdndActionCopy " ,
" XdndActionMove " ,
" XdndActionLink " ,
" XdndActionAsk " ,
" XdndActionPrivate " ,
" XdndSelection " ,
" XdndTarget " ,
" XdndTypeList " ,
2009-11-22 21:30:18 +01:00
" HTML Format " ,
2005-07-07 19:30:57 +02:00
" WCF_DIB " ,
" image/gif " ,
2009-06-19 20:54:33 +02:00
" image/jpeg " ,
2009-06-19 20:46:57 +02:00
" image/png " ,
2005-07-07 19:30:57 +02:00
" text/html " ,
" text/plain " ,
" text/rtf " ,
2007-06-27 09:50:35 +02:00
" text/richtext " ,
" text/uri-list "
2005-07-07 19:30:57 +02:00
} ;
2003-11-21 06:30:34 +01:00
/***********************************************************************
* ignore_error
*
* Check if the X error is one we can ignore .
*/
static inline BOOL ignore_error ( Display * display , XErrorEvent * event )
{
2009-11-11 21:37:51 +01:00
if ( event - > request_code = = X_SetInputFocus & &
( event - > error_code = = BadMatch | | event - > error_code = = BadWindow ) ) return TRUE ;
2006-04-01 14:21:31 +02:00
/* ignore a number of errors on gdi display caused by creating/destroying windows */
if ( display = = gdi_display )
{
if ( event - > error_code = = BadDrawable | | event - > error_code = = BadGC ) return TRUE ;
# ifdef HAVE_X11_EXTENSIONS_XRENDER_H
if ( xrender_error_base ) /* check for XRender errors */
{
if ( event - > error_code = = xrender_error_base + BadPicture ) return TRUE ;
}
# endif
}
2003-11-21 06:30:34 +01:00
return FALSE ;
}
2001-01-17 21:22:22 +01:00
/***********************************************************************
2002-04-24 23:32:11 +02:00
* X11DRV_expect_error
2001-01-17 21:22:22 +01:00
*
2002-04-24 23:32:11 +02:00
* Setup a callback function that will be called on an X error . The
* callback must return non - zero if the error is the one it expected .
* This function acquires the x11 lock ; X11DRV_check_error must be
* called in all cases to release it .
2001-01-17 21:22:22 +01:00
*/
2002-04-24 23:32:11 +02:00
void X11DRV_expect_error ( Display * display , x11drv_error_callback callback , void * arg )
2001-01-17 21:22:22 +01:00
{
2002-04-24 23:32:11 +02:00
wine_tsx11_lock ( ) ;
err_callback = callback ;
err_callback_display = display ;
err_callback_arg = arg ;
err_callback_result = 0 ;
2003-11-09 01:34:43 +01:00
err_serial = NextRequest ( display ) ;
2001-01-17 21:22:22 +01:00
}
2002-04-24 23:32:11 +02:00
2001-01-17 21:22:22 +01:00
/***********************************************************************
2002-04-24 23:32:11 +02:00
* X11DRV_check_error
2001-01-17 21:22:22 +01:00
*
2002-04-24 23:32:11 +02:00
* Check if an expected X11 error occurred ; return non - zero if yes .
* Also release the x11 lock obtained in X11DRV_expect_error .
2003-11-09 01:34:43 +01:00
* The caller is responsible for calling XSync first if necessary .
2001-01-17 21:22:22 +01:00
*/
2002-04-24 23:32:11 +02:00
int X11DRV_check_error ( void )
2001-01-17 21:22:22 +01:00
{
2002-04-24 23:32:11 +02:00
int ret ;
err_callback = NULL ;
ret = err_callback_result ;
wine_tsx11_unlock ( ) ;
return ret ;
2001-01-17 21:22:22 +01:00
}
2002-04-24 23:32:11 +02:00
2001-01-17 21:22:22 +01:00
2000-03-20 19:21:19 +01:00
/***********************************************************************
* error_handler
*/
2002-04-24 23:32:11 +02:00
static int error_handler ( Display * display , XErrorEvent * error_evt )
2000-03-20 19:21:19 +01:00
{
2003-11-09 01:34:43 +01:00
if ( err_callback & & display = = err_callback_display & &
( long ) ( error_evt - > serial - err_serial ) > = 0 )
2002-04-24 23:32:11 +02:00
{
if ( ( err_callback_result = err_callback ( display , error_evt , err_callback_arg ) ) )
{
2003-11-21 06:30:34 +01:00
TRACE ( " got expected error %d req %d \n " ,
error_evt - > error_code , error_evt - > request_code ) ;
2002-04-24 23:32:11 +02:00
return 0 ;
}
}
2003-11-21 06:30:34 +01:00
if ( ignore_error ( display , error_evt ) )
{
TRACE ( " got ignored error %d req %d \n " ,
error_evt - > error_code , error_evt - > request_code ) ;
return 0 ;
}
2006-02-24 21:05:44 +01:00
if ( TRACE_ON ( synchronous ) )
2004-07-09 21:25:59 +02:00
{
ERR ( " X protocol error: serial=%ld, request_code=%d - breaking into debugger \n " ,
error_evt - > serial , error_evt - > request_code ) ;
DebugBreak ( ) ; /* force an entry in the debugger */
}
2002-04-24 23:32:11 +02:00
old_error_handler ( display , error_evt ) ;
2000-03-20 19:21:19 +01:00
return 0 ;
}
2000-12-06 01:04:10 +01:00
/***********************************************************************
2002-09-25 05:29:55 +02:00
* wine_tsx11_lock ( X11DRV . @ )
2000-12-06 01:04:10 +01:00
*/
2008-12-18 21:12:36 +01:00
void CDECL wine_tsx11_lock ( void )
2000-12-06 01:04:10 +01:00
{
2002-05-17 05:31:08 +02:00
EnterCriticalSection ( & X11DRV_CritSection ) ;
2000-12-06 01:04:10 +01:00
}
/***********************************************************************
2002-09-25 05:29:55 +02:00
* wine_tsx11_unlock ( X11DRV . @ )
2000-12-06 01:04:10 +01:00
*/
2008-12-18 21:12:36 +01:00
void CDECL wine_tsx11_unlock ( void )
2000-12-06 01:04:10 +01:00
{
2002-05-17 05:31:08 +02:00
LeaveCriticalSection ( & X11DRV_CritSection ) ;
2000-12-06 01:04:10 +01:00
}
2000-03-20 19:21:19 +01:00
2000-09-23 00:37:56 +02:00
2008-02-04 14:36:18 +01:00
/***********************************************************************
* depth_to_bpp
*
* Convert X11 - reported depth to the BPP value that Windows apps expect to see .
*/
unsigned int depth_to_bpp ( unsigned int depth )
{
switch ( depth )
{
case 1 :
case 8 :
return depth ;
case 15 :
case 16 :
return 16 ;
case 24 :
/* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
* with 24 bit framebuffers and 32 bit framebuffers . It doesn ' t make any difference
* for windowing , but gl applications can get visuals with alpha channels . So we
* should check the framebuffer and / or opengl formats available to find out what the
* framebuffer actually does
*/
case 32 :
return 32 ;
default :
FIXME ( " Unexpected X11 depth %d bpp, what to report to app? \n " , depth ) ;
return depth ;
}
}
2001-03-28 21:43:38 +02:00
/***********************************************************************
* get_config_key
*
* Get a config key from either the app - specific or the default config
*/
2007-03-17 11:47:28 +01:00
static inline DWORD get_config_key ( HKEY defkey , HKEY appkey , const char * name ,
2001-03-28 21:43:38 +02:00
char * buffer , DWORD size )
{
2005-07-06 21:08:05 +02:00
if ( appkey & & ! RegQueryValueExA ( appkey , name , 0 , NULL , ( LPBYTE ) buffer , & size ) ) return 0 ;
if ( defkey & & ! RegQueryValueExA ( defkey , name , 0 , NULL , ( LPBYTE ) buffer , & size ) ) return 0 ;
2005-06-16 18:14:46 +02:00
return ERROR_FILE_NOT_FOUND ;
2001-03-28 21:43:38 +02:00
}
2000-05-15 04:46:44 +02:00
/***********************************************************************
* setup_options
*
* Setup the x11drv options .
*/
static void setup_options ( void )
{
2001-03-28 21:43:38 +02:00
char buffer [ MAX_PATH + 16 ] ;
HKEY hkey , appkey = 0 ;
2004-05-19 05:22:55 +02:00
DWORD len ;
2000-05-15 04:46:44 +02:00
2005-06-16 18:14:46 +02:00
/* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
if ( RegOpenKeyA ( HKEY_CURRENT_USER , " Software \\ Wine \\ X11 Driver " , & hkey ) ) hkey = 0 ;
2000-05-15 04:46:44 +02:00
2001-03-28 21:43:38 +02:00
/* open the app-specific key */
2004-05-19 05:22:55 +02:00
len = ( GetModuleFileNameA ( 0 , buffer , MAX_PATH ) ) ;
if ( len & & len < MAX_PATH )
2001-03-28 21:43:38 +02:00
{
HKEY tmpkey ;
char * p , * appname = buffer ;
if ( ( p = strrchr ( appname , ' / ' ) ) ) appname = p + 1 ;
if ( ( p = strrchr ( appname , ' \\ ' ) ) ) appname = p + 1 ;
2005-06-16 18:14:46 +02:00
strcat ( appname , " \\ X11 Driver " ) ;
/* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
if ( ! RegOpenKeyA ( HKEY_CURRENT_USER , " Software \\ Wine \\ AppDefaults " , & tmpkey ) )
2001-03-28 21:43:38 +02:00
{
if ( RegOpenKeyA ( tmpkey , appname , & appkey ) ) appkey = 0 ;
RegCloseKey ( tmpkey ) ;
}
}
2002-05-23 18:32:32 +02:00
if ( ! get_config_key ( hkey , appkey , " Managed " , buffer , sizeof ( buffer ) ) )
managed_mode = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2008-04-10 21:53:45 +02:00
if ( ! get_config_key ( hkey , appkey , " Decorated " , buffer , sizeof ( buffer ) ) )
decorated_mode = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2002-05-23 18:32:32 +02:00
2001-04-27 20:00:06 +02:00
if ( ! get_config_key ( hkey , appkey , " DXGrab " , buffer , sizeof ( buffer ) ) )
dxgrab = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2001-09-11 01:05:57 +02:00
if ( ! get_config_key ( hkey , appkey , " UseXVidMode " , buffer , sizeof ( buffer ) ) )
usexvidmode = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2003-10-16 02:21:42 +02:00
if ( ! get_config_key ( hkey , appkey , " UseXRandR " , buffer , sizeof ( buffer ) ) )
usexrandr = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2002-09-19 01:09:50 +02:00
if ( ! get_config_key ( hkey , appkey , " UseTakeFocus " , buffer , sizeof ( buffer ) ) )
use_take_focus = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2005-04-21 19:31:50 +02:00
if ( ! get_config_key ( hkey , appkey , " UsePrimarySelection " , buffer , sizeof ( buffer ) ) )
use_primary_selection = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2001-03-24 00:45:45 +01:00
screen_depth = 0 ;
2001-03-28 21:43:38 +02:00
if ( ! get_config_key ( hkey , appkey , " ScreenDepth " , buffer , sizeof ( buffer ) ) )
2001-03-24 00:45:45 +01:00
screen_depth = atoi ( buffer ) ;
2002-11-14 23:31:34 +01:00
if ( ! get_config_key ( hkey , appkey , " ClientSideWithCore " , buffer , sizeof ( buffer ) ) )
client_side_with_core = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
if ( ! get_config_key ( hkey , appkey , " ClientSideWithRender " , buffer , sizeof ( buffer ) ) )
client_side_with_render = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
if ( ! get_config_key ( hkey , appkey , " ClientSideAntiAliasWithCore " , buffer , sizeof ( buffer ) ) )
client_side_antialias_with_core = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
if ( ! get_config_key ( hkey , appkey , " ClientSideAntiAliasWithRender " , buffer , sizeof ( buffer ) ) )
client_side_antialias_with_render = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2004-01-21 03:22:26 +01:00
if ( ! get_config_key ( hkey , appkey , " UseXIM " , buffer , sizeof ( buffer ) ) )
use_xim = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2005-06-14 20:12:15 +02:00
if ( ! get_config_key ( hkey , appkey , " PrivateColorMap " , buffer , sizeof ( buffer ) ) )
private_color_map = IS_OPTION_TRUE ( buffer [ 0 ] ) ;
2006-10-23 14:37:17 +02:00
if ( ! get_config_key ( hkey , appkey , " PrimaryMonitor " , buffer , sizeof ( buffer ) ) )
primary_monitor = atoi ( buffer ) ;
2005-06-14 20:12:15 +02:00
if ( ! get_config_key ( hkey , appkey , " CopyDefaultColors " , buffer , sizeof ( buffer ) ) )
copy_default_colors = atoi ( buffer ) ;
if ( ! get_config_key ( hkey , appkey , " AllocSystemColors " , buffer , sizeof ( buffer ) ) )
alloc_system_colors = atoi ( buffer ) ;
2004-01-21 03:22:26 +01:00
get_config_key ( hkey , appkey , " InputStyle " , input_style , sizeof ( input_style ) ) ;
2001-03-28 21:43:38 +02:00
if ( appkey ) RegCloseKey ( appkey ) ;
2005-06-16 18:14:46 +02:00
if ( hkey ) RegCloseKey ( hkey ) ;
2000-05-15 04:46:44 +02:00
}
2007-09-23 03:19:08 +02:00
# ifdef SONAME_LIBXCOMPOSITE
# define MAKE_FUNCPTR(f) typeof(f) * p##f;
MAKE_FUNCPTR ( XCompositeQueryExtension )
MAKE_FUNCPTR ( XCompositeQueryVersion )
MAKE_FUNCPTR ( XCompositeVersion )
MAKE_FUNCPTR ( XCompositeRedirectWindow )
MAKE_FUNCPTR ( XCompositeRedirectSubwindows )
MAKE_FUNCPTR ( XCompositeUnredirectWindow )
MAKE_FUNCPTR ( XCompositeUnredirectSubwindows )
MAKE_FUNCPTR ( XCompositeCreateRegionFromBorderClip )
MAKE_FUNCPTR ( XCompositeNameWindowPixmap )
# undef MAKE_FUNCPTR
static int xcomp_event_base ;
static int xcomp_error_base ;
static void X11DRV_XComposite_Init ( void )
{
void * xcomposite_handle = wine_dlopen ( SONAME_LIBXCOMPOSITE , RTLD_NOW , NULL , 0 ) ;
if ( ! xcomposite_handle )
{
TRACE ( " Unable to open %s, XComposite disabled \n " , SONAME_LIBXCOMPOSITE ) ;
usexcomposite = 0 ;
return ;
}
# define LOAD_FUNCPTR(f) \
if ( ( p # # f = wine_dlsym ( xcomposite_handle , # f , NULL , 0 ) ) = = NULL ) \
goto sym_not_found ;
LOAD_FUNCPTR ( XCompositeQueryExtension )
LOAD_FUNCPTR ( XCompositeQueryVersion )
LOAD_FUNCPTR ( XCompositeVersion )
LOAD_FUNCPTR ( XCompositeRedirectWindow )
LOAD_FUNCPTR ( XCompositeRedirectSubwindows )
LOAD_FUNCPTR ( XCompositeUnredirectWindow )
LOAD_FUNCPTR ( XCompositeUnredirectSubwindows )
LOAD_FUNCPTR ( XCompositeCreateRegionFromBorderClip )
LOAD_FUNCPTR ( XCompositeNameWindowPixmap )
# undef LOAD_FUNCPTR
if ( ! pXCompositeQueryExtension ( gdi_display , & xcomp_event_base ,
& xcomp_error_base ) ) {
TRACE ( " XComposite extension could not be queried; disabled \n " ) ;
wine_dlclose ( xcomposite_handle , NULL , 0 ) ;
xcomposite_handle = NULL ;
usexcomposite = 0 ;
return ;
}
TRACE ( " XComposite is up and running error_base = %d \n " , xcomp_error_base ) ;
return ;
sym_not_found :
TRACE ( " Unable to load function pointers from %s, XComposite disabled \n " , SONAME_LIBXCOMPOSITE ) ;
wine_dlclose ( xcomposite_handle , NULL , 0 ) ;
xcomposite_handle = NULL ;
usexcomposite = 0 ;
}
# endif /* defined(SONAME_LIBXCOMPOSITE) */
2001-03-28 21:43:38 +02:00
2000-03-20 19:21:19 +01:00
/***********************************************************************
* X11DRV process initialisation routine
*/
2004-07-13 05:49:52 +02:00
static BOOL process_attach ( void )
2000-03-20 19:21:19 +01:00
{
2001-05-16 21:52:29 +02:00
Display * display ;
2000-05-15 04:46:44 +02:00
setup_options ( ) ;
2005-06-01 13:08:39 +02:00
if ( ( thread_data_tls_index = TlsAlloc ( ) ) = = TLS_OUT_OF_INDEXES ) return FALSE ;
2000-03-20 19:21:19 +01:00
/* Open display */
2000-05-15 04:46:44 +02:00
2004-07-13 05:49:52 +02:00
if ( ! ( display = XOpenDisplay ( NULL ) ) ) return FALSE ;
2000-04-04 21:57:23 +02:00
fcntl ( ConnectionNumber ( display ) , F_SETFD , 1 ) ; /* set close on exec flag */
2000-03-25 15:05:06 +01:00
screen = DefaultScreenOfDisplay ( display ) ;
visual = DefaultVisual ( display , DefaultScreen ( display ) ) ;
root_window = DefaultRootWindow ( display ) ;
2005-06-29 21:28:06 +02:00
gdi_display = display ;
2002-04-24 23:32:11 +02:00
old_error_handler = XSetErrorHandler ( error_handler ) ;
2000-03-25 15:05:06 +01:00
/* Initialize screen depth */
if ( screen_depth ) /* depth specified */
{
int depth_count , i ;
2003-11-21 01:17:33 +01:00
int * depth_list = XListDepths ( display , DefaultScreen ( display ) , & depth_count ) ;
2000-03-25 15:05:06 +01:00
for ( i = 0 ; i < depth_count ; i + + )
if ( depth_list [ i ] = = screen_depth ) break ;
2003-11-21 01:17:33 +01:00
XFree ( depth_list ) ;
2000-03-25 15:05:06 +01:00
if ( i > = depth_count )
2004-07-13 05:49:52 +02:00
{
WARN ( " invalid depth %d, using default \n " , screen_depth ) ;
screen_depth = 0 ;
}
2000-03-25 15:05:06 +01:00
}
2004-07-13 05:49:52 +02:00
if ( ! screen_depth ) screen_depth = DefaultDepthOfScreen ( screen ) ;
2008-02-04 14:36:18 +01:00
screen_bpp = depth_to_bpp ( screen_depth ) ;
2007-12-16 14:00:45 +01:00
2005-07-07 19:30:57 +02:00
XInternAtoms ( display , ( char * * ) atom_names , NB_XATOMS - FIRST_XATOM , False , X11DRV_Atoms ) ;
2006-02-24 21:05:44 +01:00
if ( TRACE_ON ( synchronous ) ) XSynchronize ( display , True ) ;
2000-03-20 19:21:19 +01:00
2008-01-17 19:59:22 +01:00
xinerama_init ( WidthOfScreen ( screen ) , HeightOfScreen ( screen ) ) ;
2003-10-16 02:21:42 +02:00
X11DRV_Settings_Init ( ) ;
2008-06-26 14:02:17 +02:00
# ifdef SONAME_LIBXXF86VM
2001-02-14 01:27:34 +01:00
/* initialize XVidMode */
X11DRV_XF86VM_Init ( ) ;
# endif
2007-07-04 12:45:03 +02:00
# ifdef SONAME_LIBXRANDR
2003-10-16 02:21:42 +02:00
/* initialize XRandR */
X11DRV_XRandR_Init ( ) ;
# endif
2007-09-23 03:19:08 +02:00
# ifdef SONAME_LIBXCOMPOSITE
X11DRV_XComposite_Init ( ) ;
# endif
2004-07-13 05:49:52 +02:00
2008-07-02 12:03:52 +02:00
# ifdef HAVE_XKB
if ( use_xkb ) use_xkb = XkbUseExtension ( gdi_display , NULL , NULL ) ;
# endif
2008-02-06 20:37:41 +01:00
X11DRV_InitKeyboard ( gdi_display ) ;
2005-07-07 19:30:57 +02:00
X11DRV_InitClipboard ( ) ;
2008-04-10 12:29:01 +02:00
if ( use_xim ) use_xim = X11DRV_InitXIM ( input_style ) ;
2005-03-09 17:45:23 +01:00
2004-07-13 05:49:52 +02:00
return TRUE ;
2000-03-20 19:21:19 +01:00
}
2001-05-16 21:52:29 +02:00
/***********************************************************************
* X11DRV thread termination routine
*/
static void thread_detach ( void )
{
2005-06-01 13:08:39 +02:00
struct x11drv_thread_data * data = TlsGetValue ( thread_data_tls_index ) ;
2001-05-16 21:52:29 +02:00
if ( data )
{
2006-06-05 17:55:14 +02:00
X11DRV_ResetSelectionOwner ( ) ;
2001-05-16 21:52:29 +02:00
wine_tsx11_lock ( ) ;
2006-10-24 12:39:28 +02:00
if ( data - > xim ) XCloseIM ( data - > xim ) ;
2008-10-18 16:03:48 +02:00
if ( data - > font_set ) XFreeFontSet ( data - > display , data - > font_set ) ;
2001-05-16 21:52:29 +02:00
XCloseDisplay ( data - > display ) ;
wine_tsx11_unlock ( ) ;
HeapFree ( GetProcessHeap ( ) , 0 , data ) ;
}
}
2000-03-20 19:21:19 +01:00
/***********************************************************************
* X11DRV process termination routine
*/
static void process_detach ( void )
{
2009-12-29 20:03:40 +01:00
X11DRV_Clipboard_Cleanup ( ) ;
2008-06-26 14:02:17 +02:00
# ifdef SONAME_LIBXXF86VM
2001-02-14 01:27:34 +01:00
/* cleanup XVidMode */
X11DRV_XF86VM_Cleanup ( ) ;
# endif
2002-11-14 23:31:34 +01:00
if ( using_client_side_fonts )
X11DRV_XRender_Finalize ( ) ;
2001-02-14 01:27:34 +01:00
2000-03-20 19:21:19 +01:00
/* cleanup GDI */
X11DRV_GDI_Finalize ( ) ;
2009-05-26 00:52:05 +02:00
X11DRV_OpenGL_Cleanup ( ) ;
2001-03-24 00:45:45 +01:00
2008-05-01 10:56:34 +02:00
IME_UnregisterClasses ( ) ;
2002-05-17 05:31:08 +02:00
DeleteCriticalSection ( & X11DRV_CritSection ) ;
2005-06-01 13:08:39 +02:00
TlsFree ( thread_data_tls_index ) ;
2000-03-20 19:21:19 +01:00
}
2007-04-04 18:02:53 +02:00
/* store the display fd into the message queue */
static void set_queue_display_fd ( Display * display )
{
HANDLE handle ;
int ret ;
if ( wine_server_fd_to_handle ( ConnectionNumber ( display ) , GENERIC_READ | SYNCHRONIZE , 0 , & handle ) )
{
MESSAGE ( " x11drv: Can't allocate handle for display fd \n " ) ;
ExitProcess ( 1 ) ;
}
SERVER_START_REQ ( set_queue_fd )
{
2008-12-08 16:05:17 +01:00
req - > handle = wine_server_obj_handle ( handle ) ;
2007-04-04 18:02:53 +02:00
ret = wine_server_call ( req ) ;
}
SERVER_END_REQ ;
if ( ret )
{
MESSAGE ( " x11drv: Can't store handle for display fd \n " ) ;
ExitProcess ( 1 ) ;
}
CloseHandle ( handle ) ;
}
2001-05-16 21:52:29 +02:00
/***********************************************************************
* X11DRV thread initialisation routine
*/
struct x11drv_thread_data * x11drv_init_thread_data ( void )
{
2008-06-26 15:08:08 +02:00
struct x11drv_thread_data * data = x11drv_thread_data ( ) ;
if ( data ) return data ;
2001-05-16 21:52:29 +02:00
2008-03-13 13:35:02 +01:00
if ( ! ( data = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * data ) ) ) )
2001-05-16 21:52:29 +02:00
{
ERR ( " could not create data \n " ) ;
ExitProcess ( 1 ) ;
}
wine_tsx11_lock ( ) ;
if ( ! ( data - > display = XOpenDisplay ( NULL ) ) )
{
wine_tsx11_unlock ( ) ;
2009-12-08 13:11:20 +01:00
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 ) ) ;
2001-05-16 21:52:29 +02:00
ExitProcess ( 1 ) ;
}
2003-01-23 02:28:12 +01:00
2004-01-21 03:22:26 +01:00
fcntl ( ConnectionNumber ( data - > display ) , F_SETFD , 1 ) ; /* set close on exec flag */
2003-01-23 02:28:12 +01:00
2003-03-23 21:07:55 +01:00
# ifdef HAVE_XKB
2008-07-02 12:03:26 +02:00
if ( use_xkb & & XkbUseExtension ( data - > display , NULL , NULL ) )
XkbSetDetectableAutoRepeat ( data - > display , True , NULL ) ;
2003-03-23 21:07:55 +01:00
# endif
2006-02-24 21:05:44 +01:00
if ( TRACE_ON ( synchronous ) ) XSynchronize ( data - > display , True ) ;
2001-05-16 21:52:29 +02:00
wine_tsx11_unlock ( ) ;
2004-01-21 03:22:26 +01:00
2007-04-04 18:02:53 +02:00
set_queue_display_fd ( data - > display ) ;
2005-06-01 13:08:39 +02:00
TlsSetValue ( thread_data_tls_index , data ) ;
2008-04-10 12:29:01 +02:00
2008-04-04 13:44:36 +02:00
if ( use_xim ) X11DRV_SetupXIM ( ) ;
2008-02-25 13:32:45 +01:00
X11DRV_SetCursor ( NULL ) ;
2008-04-10 12:29:01 +02:00
2001-05-16 21:52:29 +02:00
return data ;
}
2000-03-19 13:08:09 +01:00
/***********************************************************************
* X11DRV initialisation routine
*/
2002-11-05 00:53:41 +01:00
BOOL WINAPI DllMain ( HINSTANCE hinst , DWORD reason , LPVOID reserved )
2000-03-19 13:08:09 +01:00
{
2004-07-13 05:49:52 +02:00
BOOL ret = TRUE ;
2000-03-20 19:21:19 +01:00
switch ( reason )
2000-03-19 13:08:09 +01:00
{
2000-03-20 19:21:19 +01:00
case DLL_PROCESS_ATTACH :
2008-05-01 10:56:34 +02:00
x11drv_module = hinst ;
2004-07-13 05:49:52 +02:00
ret = process_attach ( ) ;
2000-03-20 19:21:19 +01:00
break ;
2001-05-16 21:52:29 +02:00
case DLL_THREAD_DETACH :
thread_detach ( ) ;
break ;
2000-03-20 19:21:19 +01:00
case DLL_PROCESS_DETACH :
2001-01-17 22:51:07 +01:00
process_detach ( ) ;
2000-03-20 19:21:19 +01:00
break ;
2000-03-19 13:08:09 +01:00
}
2004-07-13 05:49:52 +02:00
return ret ;
2000-03-19 13:08:09 +01:00
}
2000-03-25 18:30:13 +01:00
/***********************************************************************
2001-07-02 21:59:40 +02:00
* GetScreenSaveActive ( X11DRV . @ )
2000-03-25 18:30:13 +01:00
*
* Returns the active status of the screen saver
*/
2008-12-16 15:32:08 +01:00
BOOL CDECL X11DRV_GetScreenSaveActive ( void )
2000-03-25 18:30:13 +01:00
{
int timeout , temp ;
2003-11-21 01:17:33 +01:00
wine_tsx11_lock ( ) ;
XGetScreenSaver ( gdi_display , & timeout , & temp , & temp , & temp ) ;
wine_tsx11_unlock ( ) ;
2000-04-29 16:29:41 +02:00
return timeout ! = 0 ;
2000-03-25 18:30:13 +01:00
}
/***********************************************************************
2001-07-02 21:59:40 +02:00
* SetScreenSaveActive ( X11DRV . @ )
2000-03-25 18:30:13 +01:00
*
* Activate / Deactivate the screen saver
*/
2008-12-16 15:32:08 +01:00
void CDECL X11DRV_SetScreenSaveActive ( BOOL bActivate )
2000-03-25 18:30:13 +01:00
{
2001-11-20 21:27:26 +01:00
int timeout , interval , prefer_blanking , allow_exposures ;
static int last_timeout = 15 * 60 ;
2003-11-21 01:17:33 +01:00
wine_tsx11_lock ( ) ;
XGetScreenSaver ( gdi_display , & timeout , & interval , & prefer_blanking ,
& allow_exposures ) ;
2001-11-20 21:27:26 +01:00
if ( timeout ) last_timeout = timeout ;
timeout = bActivate ? last_timeout : 0 ;
2003-11-21 01:17:33 +01:00
XSetScreenSaver ( gdi_display , timeout , interval , prefer_blanking ,
allow_exposures ) ;
wine_tsx11_unlock ( ) ;
2000-03-25 18:30:13 +01:00
}