2 * X11DRV initialization code
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2000 Alexandre Julliard
16 #include <X11/cursorfont.h>
22 #include "wine/winbase16.h"
26 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(x11drv
);
36 static XKeyboardState keyboard_state
;
41 unsigned int screen_width
;
42 unsigned int screen_height
;
43 unsigned int screen_depth
;
46 unsigned int X11DRV_server_startticks
;
48 /***********************************************************************
51 static int error_handler(Display
*display
, XErrorEvent
*error_evt
)
53 DebugBreak(); /* force an entry in the debugger */
58 /***********************************************************************
61 * Get the server startup time
62 * Won't be exact, but should be sufficient
64 static void get_server_startup(void)
67 gettimeofday( &t
, NULL
);
68 X11DRV_server_startticks
= ((t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000)) - GetTickCount();
72 /***********************************************************************
75 * Setup the x11drv options.
77 static void setup_options(void)
83 if (RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\x11drv", 0, NULL
,
84 REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hkey
, NULL
))
86 ERR("Cannot create config registry key\n" );
90 /* --display option */
92 count
= sizeof(buffer
);
93 if (!RegQueryValueExA( hkey
, "display", 0, &type
, buffer
, &count
))
97 if (strcmp( buffer
, Options
.display
))
98 MESSAGE( "%s: warning: --display option ignored, using '%s'\n", argv0
, buffer
);
100 else if ((Options
.display
= getenv( "DISPLAY" )))
102 if (strcmp( buffer
, Options
.display
))
103 MESSAGE( "%s: warning: $DISPLAY variable ignored, using '%s'\n", argv0
, buffer
);
105 Options
.display
= strdup(buffer
);
109 if (!Options
.display
&& !(Options
.display
= getenv( "DISPLAY" )))
111 MESSAGE( "%s: no display specified\n", argv0
);
114 RegSetValueExA( hkey
, "display", 0, REG_SZ
, Options
.display
, strlen(Options
.display
)+1 );
117 /* check and set --managed and --desktop options in wine config file
118 * if it was not set on command line */
120 if ((!Options
.managed
) && (Options
.desktopGeometry
== NULL
))
122 count
= sizeof(buffer
);
123 if (!RegQueryValueExA( hkey
, "managed", 0, &type
, buffer
, &count
))
124 Options
.managed
= IS_OPTION_TRUE( buffer
[0] );
126 count
= sizeof(buffer
);
127 if (!RegQueryValueExA( hkey
, "Desktop", 0, &type
, buffer
, &count
))
128 /* Imperfect validation: If Desktop=N, then we don't turn on
129 ** the --desktop option. We should really validate for a correct
131 if (! IS_OPTION_FALSE(buffer
[0]))
132 Options
.desktopGeometry
= strdup(buffer
);
136 RegSetValueExA( hkey
, "managed", 0, REG_SZ
, "y", 2 );
138 if (Options
.desktopGeometry
)
139 RegSetValueExA( hkey
, "desktop", 0, REG_SZ
, Options
.desktopGeometry
, strlen(Options
.desktopGeometry
)+1 );
145 /***********************************************************************
148 * Create the desktop window for the --desktop mode.
150 static void create_desktop( const char *geometry
)
152 int x
= 0, y
= 0, flags
;
153 unsigned int width
= 640, height
= 480; /* Default size = 640x480 */
154 char *name
= "Wine desktop";
155 XSizeHints
*size_hints
;
157 XClassHint
*class_hints
;
158 XSetWindowAttributes win_attr
;
159 XTextProperty window_name
;
160 Atom XA_WM_DELETE_WINDOW
;
161 /* Used to create the desktop window with a good visual */
162 XVisualInfo
*vi
= NULL
;
165 int err_base
, evt_base
;
167 /* Get in wine.ini if the desktop window should have a double-buffered visual or not.
168 But first, test if OpenGL is even supported on the display ! */
169 if (glXQueryExtension(display
, &err_base
, &evt_base
) == True
) {
170 dblbuf_visual
= PROFILE_GetWineIniBool( "x11drv", "DesktopDoubleBuffered", 0 );
172 int dblBuf
[]={GLX_RGBA
,GLX_DEPTH_SIZE
,16,GLX_DOUBLEBUFFER
,None
};
175 vi
= glXChooseVisual(display
, DefaultScreen(display
), dblBuf
);
176 win_attr
.colormap
= XCreateColormap(display
, RootWindow(display
,vi
->screen
),
177 vi
->visual
, AllocNone
);
181 #endif /* HAVE_OPENGL */
183 flags
= TSXParseGeometry( geometry
, &x
, &y
, &width
, &height
);
184 screen_width
= width
;
185 screen_height
= height
;
188 win_attr
.background_pixel
= BlackPixel(display
, 0);
189 win_attr
.event_mask
= ExposureMask
| KeyPressMask
| KeyReleaseMask
|
190 PointerMotionMask
| ButtonPressMask
|
191 ButtonReleaseMask
| EnterWindowMask
;
192 win_attr
.cursor
= TSXCreateFontCursor( display
, XC_top_left_arrow
);
196 screen
= ScreenOfDisplay(display
, vi
->screen
);
197 screen_depth
= vi
->depth
;
199 root_window
= TSXCreateWindow( display
,
200 (vi
== NULL
? DefaultRootWindow(display
) : RootWindow(display
, vi
->screen
)),
201 x
, y
, width
, height
, 0,
202 (vi
== NULL
? CopyFromParent
: vi
->depth
),
204 (vi
== NULL
? CopyFromParent
: vi
->visual
),
205 CWBackPixel
| CWEventMask
| CWCursor
| (vi
== NULL
? 0 : CWColormap
),
208 /* Set window manager properties */
209 size_hints
= TSXAllocSizeHints();
210 wm_hints
= TSXAllocWMHints();
211 class_hints
= TSXAllocClassHint();
212 if (!size_hints
|| !wm_hints
|| !class_hints
)
214 MESSAGE("Not enough memory for window manager hints.\n" );
217 size_hints
->min_width
= size_hints
->max_width
= width
;
218 size_hints
->min_height
= size_hints
->max_height
= height
;
219 size_hints
->flags
= PMinSize
| PMaxSize
;
220 if (flags
& (XValue
| YValue
)) size_hints
->flags
|= USPosition
;
221 if (flags
& (WidthValue
| HeightValue
)) size_hints
->flags
|= USSize
;
222 else size_hints
->flags
|= PSize
;
224 wm_hints
->flags
= InputHint
| StateHint
;
225 wm_hints
->input
= True
;
226 wm_hints
->initial_state
= NormalState
;
227 class_hints
->res_name
= (char *)argv0
;
228 class_hints
->res_class
= "Wine";
230 TSXStringListToTextProperty( &name
, 1, &window_name
);
231 TSXSetWMProperties( display
, root_window
, &window_name
, &window_name
,
232 NULL
, 0, size_hints
, wm_hints
, class_hints
);
233 XA_WM_DELETE_WINDOW
= TSXInternAtom( display
, "WM_DELETE_WINDOW", False
);
234 TSXSetWMProtocols( display
, root_window
, &XA_WM_DELETE_WINDOW
, 1 );
235 TSXFree( size_hints
);
237 TSXFree( class_hints
);
240 TSXMapWindow( display
, root_window
);
243 /* Created so that XOpenIM can be called using the 'large stack' */
244 static void XOpenIM_large_stack(void)
246 TSXOpenIM(display
,NULL
,NULL
,NULL
);
249 /***********************************************************************
250 * X11DRV process initialisation routine
252 static void process_attach(void)
254 WND_Driver
= &X11DRV_WND_Driver
;
256 get_server_startup();
261 if (!(display
= TSXOpenDisplay( Options
.display
)))
263 MESSAGE( "%s: Can't open display: %s\n", argv0
, Options
.display
);
266 fcntl( ConnectionNumber(display
), F_SETFD
, 1 ); /* set close on exec flag */
267 screen
= DefaultScreenOfDisplay( display
);
268 visual
= DefaultVisual( display
, DefaultScreen(display
) );
269 root_window
= DefaultRootWindow( display
);
271 /* Initialize screen depth */
273 screen_depth
= PROFILE_GetWineIniInt( "x11drv", "ScreenDepth", 0 );
274 if (screen_depth
) /* depth specified */
277 int *depth_list
= TSXListDepths(display
, DefaultScreen(display
), &depth_count
);
278 for (i
= 0; i
< depth_count
; i
++)
279 if (depth_list
[i
] == screen_depth
) break;
280 TSXFree( depth_list
);
281 if (i
>= depth_count
)
283 MESSAGE( "%s: Depth %d not supported on this screen.\n", argv0
, screen_depth
);
287 else screen_depth
= DefaultDepthOfScreen( screen
);
289 /* tell the libX11 that we will do input method handling ourselves
290 * that keep libX11 from doing anything whith dead keys, allowing Wine
291 * to have total control over dead keys, that is this line allows
292 * them to work in Wine, even whith a libX11 including the dead key
293 * patches from Th.Quinot (http://Web.FdN.FR/~tquinot/dead-keys.en.html)
295 CALL_LARGE_STACK( XOpenIM_large_stack
, NULL
);
297 if (Options
.synchronous
) XSetErrorHandler( error_handler
);
299 screen_width
= WidthOfScreen( screen
);
300 screen_height
= HeightOfScreen( screen
);
302 if (Options
.desktopGeometry
)
304 Options
.managed
= FALSE
;
305 create_desktop( Options
.desktopGeometry
);
309 X11DRV_GDI_Initialize();
311 /* save keyboard setup */
312 TSXGetKeyboardControl(display
, &keyboard_state
);
314 /* initialize event handling */
317 /* load display.dll */
318 LoadLibrary16( "display" );
322 /***********************************************************************
323 * X11DRV process termination routine
325 static void process_detach(void)
327 /* restore keyboard setup */
328 XKeyboardControl keyboard_value
;
330 keyboard_value
.key_click_percent
= keyboard_state
.key_click_percent
;
331 keyboard_value
.bell_percent
= keyboard_state
.bell_percent
;
332 keyboard_value
.bell_pitch
= keyboard_state
.bell_pitch
;
333 keyboard_value
.bell_duration
= keyboard_state
.bell_duration
;
334 keyboard_value
.auto_repeat_mode
= keyboard_state
.global_auto_repeat
;
336 XChangeKeyboardControl(display
, KBKeyClickPercent
| KBBellPercent
|
337 KBBellPitch
| KBBellDuration
| KBAutoRepeatMode
, &keyboard_value
);
340 X11DRV_GDI_Finalize();
344 /* close the display */
345 XCloseDisplay( display
);
353 /***********************************************************************
354 * X11DRV initialisation routine
356 BOOL WINAPI
X11DRV_Init( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
358 static int process_count
;
362 case DLL_PROCESS_ATTACH
:
363 if (!process_count
++) process_attach();
365 case DLL_PROCESS_DETACH
:
366 if (!--process_count
) process_detach();
372 /***********************************************************************
373 * X11DRV_GetScreenSaveActive
375 * Returns the active status of the screen saver
377 BOOL
X11DRV_GetScreenSaveActive(void)
380 TSXGetScreenSaver(display
, &timeout
, &temp
, &temp
, &temp
);
384 /***********************************************************************
385 * X11DRV_SetScreenSaveActive
387 * Activate/Deactivate the screen saver
389 void X11DRV_SetScreenSaveActive(BOOL bActivate
)
392 TSXActivateScreenSaver(display
);
394 TSXResetScreenSaver(display
);
397 /***********************************************************************
398 * X11DRV_GetScreenSaveTimeout
400 * Return the screen saver timeout
402 int X11DRV_GetScreenSaveTimeout(void)
405 TSXGetScreenSaver(display
, &timeout
, &temp
, &temp
, &temp
);
409 /***********************************************************************
410 * X11DRV_SetScreenSaveTimeout
412 * Set the screen saver timeout
414 void X11DRV_SetScreenSaveTimeout(int nTimeout
)
416 /* timeout is a 16bit entity (CARD16) in the protocol, so it should
417 * not get over 32767 or it will get negative. */
418 if (nTimeout
>32767) nTimeout
= 32767;
419 TSXSetScreenSaver(display
, nTimeout
, 60, DefaultBlanking
, DefaultExposures
);
422 /***********************************************************************
423 * X11DRV_IsSingleWindow
425 BOOL
X11DRV_IsSingleWindow(void)
427 return (root_window
!= DefaultRootWindow(display
));