2 * X11DRV initialization code
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2000 Alexandre Julliard
15 #include <X11/cursorfont.h>
21 #include "wine/winbase16.h"
25 #include "debugtools.h"
33 DEFAULT_DEBUG_CHANNEL(x11drv
);
35 static XKeyboardState keyboard_state
;
40 unsigned int screen_width
;
41 unsigned int screen_height
;
42 unsigned int screen_depth
;
45 unsigned int X11DRV_server_startticks
;
47 /***********************************************************************
50 static int error_handler(Display
*display
, XErrorEvent
*error_evt
)
52 DebugBreak(); /* force an entry in the debugger */
57 /***********************************************************************
60 * Get the server startup time
61 * Won't be exact, but should be sufficient
63 static void get_server_startup(void)
66 gettimeofday( &t
, NULL
);
67 X11DRV_server_startticks
= ((t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000)) - GetTickCount();
71 /***********************************************************************
74 * Setup the x11drv options.
76 static void setup_options(void)
82 if (RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\x11drv", 0, NULL
,
83 REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hkey
, NULL
))
85 ERR("Cannot create config registry key\n" );
89 /* --display option */
91 count
= sizeof(buffer
);
92 if (!RegQueryValueExA( hkey
, "display", 0, &type
, buffer
, &count
))
96 if (strcmp( buffer
, Options
.display
))
97 MESSAGE( "%s: warning: --display option ignored, using '%s'\n", argv0
, buffer
);
99 else if ((Options
.display
= getenv( "DISPLAY" )))
101 if (strcmp( buffer
, Options
.display
))
102 MESSAGE( "%s: warning: $DISPLAY variable ignored, using '%s'\n", argv0
, buffer
);
104 Options
.display
= strdup(buffer
);
108 if (!Options
.display
&& !(Options
.display
= getenv( "DISPLAY" )))
110 MESSAGE( "%s: no display specified\n", argv0
);
113 RegSetValueExA( hkey
, "display", 0, REG_SZ
, Options
.display
, strlen(Options
.display
)+1 );
116 /* --managed option */
118 if (!Options
.managed
)
120 count
= sizeof(buffer
);
121 if (!RegQueryValueExA( hkey
, "managed", 0, &type
, buffer
, &count
))
122 Options
.managed
= IS_OPTION_TRUE( buffer
[0] );
124 else RegSetValueExA( hkey
, "managed", 0, REG_SZ
, "y", 2 );
130 /***********************************************************************
133 * Create the desktop window for the --desktop mode.
135 static void create_desktop( const char *geometry
)
137 int x
= 0, y
= 0, flags
;
138 unsigned int width
= 640, height
= 480; /* Default size = 640x480 */
139 char *name
= "Wine desktop";
140 XSizeHints
*size_hints
;
142 XClassHint
*class_hints
;
143 XSetWindowAttributes win_attr
;
144 XTextProperty window_name
;
145 Atom XA_WM_DELETE_WINDOW
;
146 /* Used to create the desktop window with a good visual */
147 XVisualInfo
*vi
= NULL
;
151 /* Get in wine.ini if the desktop window should have a double-buffered visual or not */
152 dblbuf_visual
= PROFILE_GetWineIniBool( "x11drv", "DesktopDoubleBuffered", 0 );
154 int dblBuf
[]={GLX_RGBA
,GLX_DEPTH_SIZE
,16,GLX_DOUBLEBUFFER
,None
};
157 vi
= glXChooseVisual(display
, DefaultScreen(display
), dblBuf
);
158 win_attr
.colormap
= XCreateColormap(display
, RootWindow(display
,vi
->screen
),
159 vi
->visual
, AllocNone
);
162 #endif /* HAVE_OPENGL */
164 flags
= TSXParseGeometry( geometry
, &x
, &y
, &width
, &height
);
165 screen_width
= width
;
166 screen_height
= height
;
169 win_attr
.background_pixel
= BlackPixel(display
, 0);
170 win_attr
.event_mask
= ExposureMask
| KeyPressMask
| KeyReleaseMask
|
171 PointerMotionMask
| ButtonPressMask
|
172 ButtonReleaseMask
| EnterWindowMask
;
173 win_attr
.cursor
= TSXCreateFontCursor( display
, XC_top_left_arrow
);
177 screen
= ScreenOfDisplay(display
, vi
->screen
);
178 screen_depth
= vi
->depth
;
180 root_window
= TSXCreateWindow( display
,
181 (vi
== NULL
? DefaultRootWindow(display
) : RootWindow(display
, vi
->screen
)),
182 x
, y
, width
, height
, 0,
183 (vi
== NULL
? CopyFromParent
: vi
->depth
),
185 (vi
== NULL
? CopyFromParent
: vi
->visual
),
186 CWBackPixel
| CWEventMask
| CWCursor
| (vi
== NULL
? 0 : CWColormap
),
189 /* Set window manager properties */
190 size_hints
= TSXAllocSizeHints();
191 wm_hints
= TSXAllocWMHints();
192 class_hints
= TSXAllocClassHint();
193 if (!size_hints
|| !wm_hints
|| !class_hints
)
195 MESSAGE("Not enough memory for window manager hints.\n" );
198 size_hints
->min_width
= size_hints
->max_width
= width
;
199 size_hints
->min_height
= size_hints
->max_height
= height
;
200 size_hints
->flags
= PMinSize
| PMaxSize
;
201 if (flags
& (XValue
| YValue
)) size_hints
->flags
|= USPosition
;
202 if (flags
& (WidthValue
| HeightValue
)) size_hints
->flags
|= USSize
;
203 else size_hints
->flags
|= PSize
;
205 wm_hints
->flags
= InputHint
| StateHint
;
206 wm_hints
->input
= True
;
207 wm_hints
->initial_state
= NormalState
;
208 class_hints
->res_name
= (char *)argv0
;
209 class_hints
->res_class
= "Wine";
211 TSXStringListToTextProperty( &name
, 1, &window_name
);
212 TSXSetWMProperties( display
, root_window
, &window_name
, &window_name
,
213 NULL
, 0, size_hints
, wm_hints
, class_hints
);
214 XA_WM_DELETE_WINDOW
= TSXInternAtom( display
, "WM_DELETE_WINDOW", False
);
215 TSXSetWMProtocols( display
, root_window
, &XA_WM_DELETE_WINDOW
, 1 );
216 TSXFree( size_hints
);
218 TSXFree( class_hints
);
221 TSXMapWindow( display
, root_window
);
224 /* Created so that XOpenIM can be called using the 'large stack' */
225 static void XOpenIM_large_stack(void)
227 TSXOpenIM(display
,NULL
,NULL
,NULL
);
230 /***********************************************************************
231 * X11DRV process initialisation routine
233 static void process_attach(void)
235 WND_Driver
= &X11DRV_WND_Driver
;
237 get_server_startup();
242 if (!(display
= TSXOpenDisplay( Options
.display
)))
244 MESSAGE( "%s: Can't open display: %s\n", argv0
, Options
.display
);
247 fcntl( ConnectionNumber(display
), F_SETFD
, 1 ); /* set close on exec flag */
248 screen
= DefaultScreenOfDisplay( display
);
249 visual
= DefaultVisual( display
, DefaultScreen(display
) );
250 root_window
= DefaultRootWindow( display
);
252 /* Initialize screen depth */
254 screen_depth
= PROFILE_GetWineIniInt( "x11drv", "ScreenDepth", 0 );
255 if (screen_depth
) /* depth specified */
258 int *depth_list
= TSXListDepths(display
, DefaultScreen(display
), &depth_count
);
259 for (i
= 0; i
< depth_count
; i
++)
260 if (depth_list
[i
] == screen_depth
) break;
261 TSXFree( depth_list
);
262 if (i
>= depth_count
)
264 MESSAGE( "%s: Depth %d not supported on this screen.\n", argv0
, screen_depth
);
268 else screen_depth
= DefaultDepthOfScreen( screen
);
270 /* tell the libX11 that we will do input method handling ourselves
271 * that keep libX11 from doing anything whith dead keys, allowing Wine
272 * to have total control over dead keys, that is this line allows
273 * them to work in Wine, even whith a libX11 including the dead key
274 * patches from Th.Quinot (http://Web.FdN.FR/~tquinot/dead-keys.en.html)
276 CALL_LARGE_STACK( XOpenIM_large_stack
, NULL
);
278 if (Options
.synchronous
) XSetErrorHandler( error_handler
);
280 screen_width
= WidthOfScreen( screen
);
281 screen_height
= HeightOfScreen( screen
);
283 if (Options
.desktopGeometry
)
285 Options
.managed
= FALSE
;
286 create_desktop( Options
.desktopGeometry
);
290 X11DRV_GDI_Initialize();
292 /* save keyboard setup */
293 TSXGetKeyboardControl(display
, &keyboard_state
);
295 /* initialize event handling */
298 /* load display.dll */
299 LoadLibrary16( "display" );
303 /***********************************************************************
304 * X11DRV process termination routine
306 static void process_detach(void)
308 /* restore keyboard setup */
309 XKeyboardControl keyboard_value
;
311 keyboard_value
.key_click_percent
= keyboard_state
.key_click_percent
;
312 keyboard_value
.bell_percent
= keyboard_state
.bell_percent
;
313 keyboard_value
.bell_pitch
= keyboard_state
.bell_pitch
;
314 keyboard_value
.bell_duration
= keyboard_state
.bell_duration
;
315 keyboard_value
.auto_repeat_mode
= keyboard_state
.global_auto_repeat
;
317 XChangeKeyboardControl(display
, KBKeyClickPercent
| KBBellPercent
|
318 KBBellPitch
| KBBellDuration
| KBAutoRepeatMode
, &keyboard_value
);
321 X11DRV_GDI_Finalize();
325 /* close the display */
326 XCloseDisplay( display
);
334 /***********************************************************************
335 * X11DRV initialisation routine
337 BOOL WINAPI
X11DRV_Init( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
339 static int process_count
;
343 case DLL_PROCESS_ATTACH
:
344 if (!process_count
++) process_attach();
346 case DLL_PROCESS_DETACH
:
347 if (!--process_count
) process_detach();
353 /***********************************************************************
354 * X11DRV_GetScreenSaveActive
356 * Returns the active status of the screen saver
358 BOOL
X11DRV_GetScreenSaveActive(void)
361 TSXGetScreenSaver(display
, &timeout
, &temp
, &temp
, &temp
);
365 /***********************************************************************
366 * X11DRV_SetScreenSaveActive
368 * Activate/Deactivate the screen saver
370 void X11DRV_SetScreenSaveActive(BOOL bActivate
)
373 TSXActivateScreenSaver(display
);
375 TSXResetScreenSaver(display
);
378 /***********************************************************************
379 * X11DRV_GetScreenSaveTimeout
381 * Return the screen saver timeout
383 int X11DRV_GetScreenSaveTimeout(void)
386 TSXGetScreenSaver(display
, &timeout
, &temp
, &temp
, &temp
);
390 /***********************************************************************
391 * X11DRV_SetScreenSaveTimeout
393 * Set the screen saver timeout
395 void X11DRV_SetScreenSaveTimeout(int nTimeout
)
397 /* timeout is a 16bit entity (CARD16) in the protocol, so it should
398 * not get over 32767 or it will get negative. */
399 if (nTimeout
>32767) nTimeout
= 32767;
400 TSXSetScreenSaver(display
, nTimeout
, 60, DefaultBlanking
, DefaultExposures
);
403 /***********************************************************************
404 * X11DRV_IsSingleWindow
406 BOOL
X11DRV_IsSingleWindow(void)
408 return (root_window
!= DefaultRootWindow(display
));