DrawText ellipsification on all lines, not just single-line.
[wine/wine-kai.git] / dlls / x11drv / x11drv_main.c
blobae2248e79d91cf58cdc240f779fc2e4d3f4f8677
1 /*
2 * X11DRV initialization code
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2000 Alexandre Julliard
6 */
8 #include "config.h"
10 #ifdef NO_REENTRANT_X11
11 /* Get pointers to the static errno and h_errno variables used by Xlib. This
12 must be done before including <errno.h> makes the variables invisible. */
13 extern int errno;
14 static int *perrno = &errno;
15 extern int h_errno;
16 static int *ph_errno = &h_errno;
17 #endif /* NO_REENTRANT_X11 */
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include <unistd.h>
25 #include <X11/cursorfont.h>
26 #include "ts_xlib.h"
27 #include "ts_xutil.h"
28 #include "ts_shape.h"
30 #include "winbase.h"
31 #include "wine/winbase16.h"
32 #include "winreg.h"
34 #include "debugtools.h"
35 #include "gdi.h"
36 #include "file.h"
37 #include "options.h"
38 #include "user.h"
39 #include "win.h"
40 #include "wine_gl.h"
41 #include "x11drv.h"
42 #include "xvidmode.h"
43 #include "dga2.h"
45 DEFAULT_DEBUG_CHANNEL(x11drv);
47 static void (*old_tsx11_lock)(void);
48 static void (*old_tsx11_unlock)(void);
50 static CRITICAL_SECTION X11DRV_CritSection = CRITICAL_SECTION_INIT("X11DRV_CritSection");
52 Screen *screen;
53 Visual *visual;
54 unsigned int screen_width;
55 unsigned int screen_height;
56 unsigned int screen_depth;
57 Window root_window;
58 int dxgrab, usedga, usexvidmode;
60 unsigned int X11DRV_server_startticks;
62 static BOOL synchronous; /* run in synchronous mode? */
63 static char *desktop_geometry;
64 static XVisualInfo *desktop_vi;
66 #define IS_OPTION_TRUE(ch) \
67 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
68 #define IS_OPTION_FALSE(ch) \
69 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
71 #ifdef NO_REENTRANT_X11
72 static int* (*old_errno_location)(void);
73 static int* (*old_h_errno_location)(void);
75 /***********************************************************************
76 * x11_errno_location
78 * Get the per-thread errno location.
80 static int *x11_errno_location(void)
82 /* Use static libc errno while running in Xlib. */
83 if (X11DRV_CritSection.OwningThread == GetCurrentThreadId()) return perrno;
84 return old_errno_location();
87 /***********************************************************************
88 * x11_h_errno_location
90 * Get the per-thread h_errno location.
92 static int *x11_h_errno_location(void)
94 /* Use static libc h_errno while running in Xlib. */
95 if (X11DRV_CritSection.OwningThread == GetCurrentThreadId()) return ph_errno;
96 return old_h_errno_location();
98 #endif /* NO_REENTRANT_X11 */
100 /***********************************************************************
101 * error_handler
103 static int error_handler(Display *display, XErrorEvent *error_evt)
105 DebugBreak(); /* force an entry in the debugger */
106 return 0;
109 /***********************************************************************
110 * lock_tsx11
112 static void lock_tsx11(void)
114 RtlEnterCriticalSection( &X11DRV_CritSection );
117 /***********************************************************************
118 * unlock_tsx11
120 static void unlock_tsx11(void)
122 RtlLeaveCriticalSection( &X11DRV_CritSection );
125 /***********************************************************************
126 * get_server_startup
128 * Get the server startup time
129 * Won't be exact, but should be sufficient
131 static void get_server_startup(void)
133 struct timeval t;
134 gettimeofday( &t, NULL );
135 X11DRV_server_startticks = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - GetTickCount();
139 /***********************************************************************
140 * get_config_key
142 * Get a config key from either the app-specific or the default config
144 inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
145 char *buffer, DWORD size )
147 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size )) return 0;
148 return RegQueryValueExA( defkey, name, 0, NULL, buffer, &size );
152 /***********************************************************************
153 * setup_options
155 * Setup the x11drv options.
157 static void setup_options(void)
159 char buffer[MAX_PATH+16];
160 HKEY hkey, appkey = 0;
161 DWORD count;
163 if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", 0, NULL,
164 REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ))
166 ERR("Cannot create config registry key\n" );
167 ExitProcess(1);
170 /* open the app-specific key */
172 if (GetModuleFileName16( GetCurrentTask(), buffer, MAX_PATH ) ||
173 GetModuleFileNameA( 0, buffer, MAX_PATH ))
175 HKEY tmpkey;
176 char *p, *appname = buffer;
177 if ((p = strrchr( appname, '/' ))) appname = p + 1;
178 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
179 strcat( appname, "\\x11drv" );
180 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\AppDefaults", &tmpkey ))
182 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
183 RegCloseKey( tmpkey );
187 /* get the display name */
189 strcpy( buffer, "DISPLAY=" );
190 count = sizeof(buffer) - 8;
191 if (!RegQueryValueExA( hkey, "display", 0, NULL, buffer + 8, &count ))
193 const char *display_name = getenv( "DISPLAY" );
194 if (display_name && strcmp( buffer, display_name ))
195 MESSAGE( "x11drv: Warning: $DISPLAY variable ignored, using '%s' specified in config file\n",
196 buffer + 8 );
197 putenv( strdup(buffer) );
200 /* check --managed option in wine config file if it was not set on command line */
202 if (!Options.managed)
204 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
205 Options.managed = IS_OPTION_TRUE( buffer[0] );
208 if (!get_config_key( hkey, appkey, "Desktop", buffer, sizeof(buffer) ))
210 /* Imperfect validation: If Desktop=N, then we don't turn on
211 ** the --desktop option. We should really validate for a correct
212 ** sizing entry */
213 if (!IS_OPTION_FALSE(buffer[0])) desktop_geometry = strdup(buffer);
216 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
217 dxgrab = IS_OPTION_TRUE( buffer[0] );
219 if (!get_config_key( hkey, appkey, "UseDGA", buffer, sizeof(buffer) ))
220 usedga = IS_OPTION_TRUE( buffer[0] );
222 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
223 usexvidmode = IS_OPTION_TRUE( buffer[0] );
225 screen_depth = 0;
226 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
227 screen_depth = atoi(buffer);
229 if (!get_config_key( hkey, appkey, "Synchronous", buffer, sizeof(buffer) ))
230 synchronous = IS_OPTION_TRUE( buffer[0] );
232 if (appkey) RegCloseKey( appkey );
233 RegCloseKey( hkey );
237 /***********************************************************************
238 * setup_opengl_visual
240 * Setup the default visual used for OpenGL and Direct3D, and the desktop
241 * window (if it exists). If OpenGL isn't available, the visual is simply
242 * set to the default visual for the display
244 #ifdef HAVE_OPENGL
245 static void setup_opengl_visual( Display *display )
247 int err_base, evt_base;
249 /* In order to support OpenGL or D3D, we require a double-buffered
250 * visual */
251 if (glXQueryExtension(display, &err_base, &evt_base) == True) {
252 int dblBuf[]={GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None};
254 ENTER_GL();
255 desktop_vi = glXChooseVisual(display, DefaultScreen(display), dblBuf);
256 LEAVE_GL();
259 if (desktop_vi != NULL) {
260 visual = desktop_vi->visual;
261 screen = ScreenOfDisplay(display, desktop_vi->screen);
262 screen_depth = desktop_vi->depth;
265 #endif /* HAVE_OPENGL */
267 /***********************************************************************
268 * X11DRV process initialisation routine
270 static void process_attach(void)
272 Display *display;
274 get_server_startup();
275 setup_options();
277 /* setup TSX11 locking */
278 #ifdef NO_REENTRANT_X11
279 old_errno_location = InterlockedExchangePointer( &wine_errno_location,
280 x11_errno_location );
281 old_h_errno_location = InterlockedExchangePointer( &wine_h_errno_location,
282 x11_h_errno_location );
283 #endif /* NO_REENTRANT_X11 */
284 old_tsx11_lock = wine_tsx11_lock;
285 old_tsx11_unlock = wine_tsx11_unlock;
286 wine_tsx11_lock = lock_tsx11;
287 wine_tsx11_unlock = unlock_tsx11;
289 /* Open display */
291 if (!(display = TSXOpenDisplay( NULL )))
293 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
294 ExitProcess(1);
296 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
297 screen = DefaultScreenOfDisplay( display );
298 visual = DefaultVisual( display, DefaultScreen(display) );
299 root_window = DefaultRootWindow( display );
301 /* Initialize screen depth */
303 if (screen_depth) /* depth specified */
305 int depth_count, i;
306 int *depth_list = TSXListDepths(display, DefaultScreen(display), &depth_count);
307 for (i = 0; i < depth_count; i++)
308 if (depth_list[i] == screen_depth) break;
309 TSXFree( depth_list );
310 if (i >= depth_count)
312 MESSAGE( "x11drv: Depth %d not supported on this screen.\n", screen_depth );
313 ExitProcess(1);
316 else screen_depth = DefaultDepthOfScreen( screen );
318 /* If OpenGL is available, change the default visual, etc as necessary */
319 #ifdef HAVE_OPENGL
320 setup_opengl_visual( display );
321 #endif /* HAVE_OPENGL */
323 /* tell the libX11 that we will do input method handling ourselves
324 * that keep libX11 from doing anything whith dead keys, allowing Wine
325 * to have total control over dead keys, that is this line allows
326 * them to work in Wine, even whith a libX11 including the dead key
327 * patches from Th.Quinot (http://Web.FdN.FR/~tquinot/dead-keys.en.html)
329 TSXOpenIM( display, NULL, NULL, NULL);
331 if (synchronous)
333 XSetErrorHandler( error_handler );
334 XSynchronize( display, True );
337 screen_width = WidthOfScreen( screen );
338 screen_height = HeightOfScreen( screen );
340 if (desktop_geometry)
342 Options.managed = FALSE;
343 root_window = X11DRV_create_desktop( desktop_vi, desktop_geometry );
346 /* initialize GDI */
347 if(!X11DRV_GDI_Initialize( display ))
349 ERR( "Couldn't Initialize GDI.\n" );
350 ExitProcess(1);
353 #ifdef HAVE_LIBXXF86VM
354 /* initialize XVidMode */
355 X11DRV_XF86VM_Init();
356 #endif
357 #ifdef HAVE_LIBXXF86DGA2
358 /* initialize DGA2 */
359 X11DRV_XF86DGA2_Init();
360 #endif
361 #ifdef HAVE_OPENGL
362 /* initialize GLX */
363 /*X11DRV_GLX_Init();*/
364 #endif
366 /* load display.dll */
367 LoadLibrary16( "display" );
371 /***********************************************************************
372 * X11DRV thread termination routine
374 static void thread_detach(void)
376 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
378 if (data)
380 CloseHandle( data->display_fd );
381 wine_tsx11_lock();
382 XCloseDisplay( data->display );
383 wine_tsx11_unlock();
384 HeapFree( GetProcessHeap(), 0, data );
389 /***********************************************************************
390 * X11DRV process termination routine
392 static void process_detach(void)
394 #ifdef HAVE_OPENGL
395 /* cleanup GLX */
396 /*X11DRV_GLX_Cleanup();*/
397 #endif
398 #ifdef HAVE_LIBXXF86DGA2
399 /* cleanup DGA2 */
400 X11DRV_XF86DGA2_Cleanup();
401 #endif
402 #ifdef HAVE_LIBXXF86VM
403 /* cleanup XVidMode */
404 X11DRV_XF86VM_Cleanup();
405 #endif
407 /* FIXME: should detach all threads */
408 thread_detach();
410 /* cleanup GDI */
411 X11DRV_GDI_Finalize();
413 /* restore TSX11 locking */
414 wine_tsx11_lock = old_tsx11_lock;
415 wine_tsx11_unlock = old_tsx11_unlock;
416 #ifdef NO_REENTRANT_X11
417 wine_errno_location = old_errno_location;
418 wine_h_errno_location = old_h_errno_location;
419 #endif /* NO_REENTRANT_X11 */
420 RtlDeleteCriticalSection( &X11DRV_CritSection );
424 /***********************************************************************
425 * X11DRV thread initialisation routine
427 struct x11drv_thread_data *x11drv_init_thread_data(void)
429 struct x11drv_thread_data *data;
431 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
433 ERR( "could not create data\n" );
434 ExitProcess(1);
436 wine_tsx11_lock();
437 if (!(data->display = XOpenDisplay(NULL)))
439 wine_tsx11_unlock();
440 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
441 ExitProcess(1);
443 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
444 if (synchronous) XSynchronize( data->display, True );
445 wine_tsx11_unlock();
446 data->display_fd = FILE_DupUnixHandle( ConnectionNumber(data->display),
447 GENERIC_READ | SYNCHRONIZE, FALSE );
448 data->process_event_count = 0;
449 NtCurrentTeb()->driver_data = data;
450 return data;
454 /***********************************************************************
455 * X11DRV initialisation routine
457 BOOL WINAPI X11DRV_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved )
459 switch(reason)
461 case DLL_PROCESS_ATTACH:
462 process_attach();
463 break;
464 case DLL_THREAD_DETACH:
465 thread_detach();
466 break;
467 case DLL_PROCESS_DETACH:
468 process_detach();
469 break;
471 return TRUE;
474 /***********************************************************************
475 * GetScreenSaveActive (X11DRV.@)
477 * Returns the active status of the screen saver
479 BOOL X11DRV_GetScreenSaveActive(void)
481 int timeout, temp;
482 TSXGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
483 return timeout != 0;
486 /***********************************************************************
487 * SetScreenSaveActive (X11DRV.@)
489 * Activate/Deactivate the screen saver
491 void X11DRV_SetScreenSaveActive(BOOL bActivate)
493 int timeout, interval, prefer_blanking, allow_exposures;
494 static int last_timeout = 15 * 60;
496 TSXGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
497 &allow_exposures);
498 if (timeout) last_timeout = timeout;
500 timeout = bActivate ? last_timeout : 0;
501 TSXSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
502 allow_exposures);