winecoreaudio: Implement widStart.
[wine/gsoc_dplay.git] / dlls / winex11.drv / x11drv_main.c
bloba06f7eafb1ff400be169957ceb63bb34d3bcb842
1 /*
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
22 #include "config.h"
24 #include <fcntl.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #ifdef HAVE_SYS_TIME_H
30 # include <sys/time.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
35 #include <X11/cursorfont.h>
36 #include <X11/Xlib.h>
37 #ifdef HAVE_XKB
38 #include <X11/XKBlib.h>
39 #endif
40 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
41 #include <X11/extensions/Xrender.h>
42 #endif
44 #include "windef.h"
45 #include "winbase.h"
46 #include "wine/winbase16.h"
47 #include "winreg.h"
49 #include "x11drv.h"
50 #include "xvidmode.h"
51 #include "xrandr.h"
52 #include "wine/server.h"
53 #include "wine/debug.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
56 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
58 static CRITICAL_SECTION X11DRV_CritSection;
59 static CRITICAL_SECTION_DEBUG critsect_debug =
61 0, 0, &X11DRV_CritSection,
62 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
63 0, 0, { (DWORD_PTR)(__FILE__ ": X11DRV_CritSection") }
65 static CRITICAL_SECTION X11DRV_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 };
67 Screen *screen;
68 Visual *visual;
69 unsigned int screen_width;
70 unsigned int screen_height;
71 unsigned int screen_depth;
72 RECT virtual_screen_rect;
73 Window root_window;
74 int dxgrab = 0;
75 int usexvidmode = 1;
76 int usexrandr = 1;
77 int use_xkb = 1;
78 int use_take_focus = 1;
79 int use_primary_selection = 0;
80 int managed_mode = 1;
81 int private_color_map = 0;
82 int primary_monitor = 0;
83 int client_side_with_core = 1;
84 int client_side_with_render = 1;
85 int client_side_antialias_with_core = 1;
86 int client_side_antialias_with_render = 1;
87 int copy_default_colors = 128;
88 int alloc_system_colors = 256;
89 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
90 int xrender_error_base = 0;
92 static BOOL desktop_dbl_buf = TRUE;
94 static x11drv_error_callback err_callback; /* current callback for error */
95 static Display *err_callback_display; /* display callback is set for */
96 static void *err_callback_arg; /* error callback argument */
97 static int err_callback_result; /* error callback result */
98 static unsigned long err_serial; /* serial number of first request */
99 static int (*old_error_handler)( Display *, XErrorEvent * );
100 static int use_xim = 1;
101 static char input_style[20];
103 #define IS_OPTION_TRUE(ch) \
104 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
105 #define IS_OPTION_FALSE(ch) \
106 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
108 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
110 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
112 "CLIPBOARD",
113 "COMPOUND_TEXT",
114 "MULTIPLE",
115 "SELECTION_DATA",
116 "TARGETS",
117 "TEXT",
118 "UTF8_STRING",
119 "RAW_ASCENT",
120 "RAW_DESCENT",
121 "RAW_CAP_HEIGHT",
122 "WM_PROTOCOLS",
123 "WM_DELETE_WINDOW",
124 "WM_TAKE_FOCUS",
125 "KWM_DOCKWINDOW",
126 "DndProtocol",
127 "DndSelection",
128 "_MOTIF_WM_HINTS",
129 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
130 "_NET_SYSTEM_TRAY_OPCODE",
131 "_NET_SYSTEM_TRAY_S0",
132 "_NET_WM_MOVERESIZE",
133 "_NET_WM_NAME",
134 "_NET_WM_PID",
135 "_NET_WM_PING",
136 "_NET_WM_STATE",
137 "_NET_WM_STATE_FULLSCREEN",
138 "_NET_WM_WINDOW_TYPE",
139 "_NET_WM_WINDOW_TYPE_DIALOG",
140 "_NET_WM_WINDOW_TYPE_NORMAL",
141 "_NET_WM_WINDOW_TYPE_UTILITY",
142 "_XEMBED_INFO",
143 "XdndAware",
144 "XdndEnter",
145 "XdndPosition",
146 "XdndStatus",
147 "XdndLeave",
148 "XdndFinished",
149 "XdndDrop",
150 "XdndActionCopy",
151 "XdndActionMove",
152 "XdndActionLink",
153 "XdndActionAsk",
154 "XdndActionPrivate",
155 "XdndSelection",
156 "XdndTarget",
157 "XdndTypeList",
158 "WCF_DIB",
159 "image/gif",
160 "text/html",
161 "text/plain",
162 "text/rtf",
163 "text/richtext"
166 /***********************************************************************
167 * ignore_error
169 * Check if the X error is one we can ignore.
171 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
173 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
175 /* ignore a number of errors on gdi display caused by creating/destroying windows */
176 if (display == gdi_display)
178 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
179 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
180 if (xrender_error_base) /* check for XRender errors */
182 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
184 #endif
186 return FALSE;
190 /***********************************************************************
191 * X11DRV_expect_error
193 * Setup a callback function that will be called on an X error. The
194 * callback must return non-zero if the error is the one it expected.
195 * This function acquires the x11 lock; X11DRV_check_error must be
196 * called in all cases to release it.
198 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
200 wine_tsx11_lock();
201 err_callback = callback;
202 err_callback_display = display;
203 err_callback_arg = arg;
204 err_callback_result = 0;
205 err_serial = NextRequest(display);
209 /***********************************************************************
210 * X11DRV_check_error
212 * Check if an expected X11 error occurred; return non-zero if yes.
213 * Also release the x11 lock obtained in X11DRV_expect_error.
214 * The caller is responsible for calling XSync first if necessary.
216 int X11DRV_check_error(void)
218 int ret;
219 err_callback = NULL;
220 ret = err_callback_result;
221 wine_tsx11_unlock();
222 return ret;
226 /***********************************************************************
227 * error_handler
229 static int error_handler( Display *display, XErrorEvent *error_evt )
231 if (err_callback && display == err_callback_display &&
232 (long)(error_evt->serial - err_serial) >= 0)
234 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
236 TRACE( "got expected error %d req %d\n",
237 error_evt->error_code, error_evt->request_code );
238 return 0;
241 if (ignore_error( display, error_evt ))
243 TRACE( "got ignored error %d req %d\n",
244 error_evt->error_code, error_evt->request_code );
245 return 0;
247 if (TRACE_ON(synchronous))
249 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
250 error_evt->serial, error_evt->request_code );
251 DebugBreak(); /* force an entry in the debugger */
253 old_error_handler( display, error_evt );
254 return 0;
257 /***********************************************************************
258 * wine_tsx11_lock (X11DRV.@)
260 void wine_tsx11_lock(void)
262 EnterCriticalSection( &X11DRV_CritSection );
265 /***********************************************************************
266 * wine_tsx11_unlock (X11DRV.@)
268 void wine_tsx11_unlock(void)
270 LeaveCriticalSection( &X11DRV_CritSection );
274 /***********************************************************************
275 * get_config_key
277 * Get a config key from either the app-specific or the default config
279 inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
280 char *buffer, DWORD size )
282 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
283 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
284 return ERROR_FILE_NOT_FOUND;
288 /***********************************************************************
289 * setup_options
291 * Setup the x11drv options.
293 static void setup_options(void)
295 char buffer[MAX_PATH+16];
296 HKEY hkey, appkey = 0;
297 DWORD len;
299 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
300 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
302 /* open the app-specific key */
304 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
305 if (len && len < MAX_PATH)
307 HKEY tmpkey;
308 char *p, *appname = buffer;
309 if ((p = strrchr( appname, '/' ))) appname = p + 1;
310 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
311 strcat( appname, "\\X11 Driver" );
312 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
313 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
315 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
316 RegCloseKey( tmpkey );
320 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
321 managed_mode = IS_OPTION_TRUE( buffer[0] );
323 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
324 dxgrab = IS_OPTION_TRUE( buffer[0] );
326 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
327 usexvidmode = IS_OPTION_TRUE( buffer[0] );
329 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
330 usexrandr = IS_OPTION_TRUE( buffer[0] );
332 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
333 use_take_focus = IS_OPTION_TRUE( buffer[0] );
335 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
336 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
338 screen_depth = 0;
339 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
340 screen_depth = atoi(buffer);
342 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
343 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
345 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
346 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
348 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
349 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
351 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
352 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
354 if (!get_config_key( hkey, appkey, "DesktopDoubleBuffered", buffer, sizeof(buffer) ))
355 desktop_dbl_buf = IS_OPTION_TRUE( buffer[0] );
357 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
358 use_xim = IS_OPTION_TRUE( buffer[0] );
360 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
361 private_color_map = IS_OPTION_TRUE( buffer[0] );
363 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
364 primary_monitor = atoi( buffer );
366 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
367 copy_default_colors = atoi(buffer);
369 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
370 alloc_system_colors = atoi(buffer);
372 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
374 if (appkey) RegCloseKey( appkey );
375 if (hkey) RegCloseKey( hkey );
379 /***********************************************************************
380 * X11DRV process initialisation routine
382 static BOOL process_attach(void)
384 Display *display;
385 XVisualInfo *desktop_vi = NULL;
387 setup_options();
389 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
391 /* Open display */
393 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
395 if (!(display = XOpenDisplay( NULL ))) return FALSE;
397 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
398 screen = DefaultScreenOfDisplay( display );
399 visual = DefaultVisual( display, DefaultScreen(display) );
400 root_window = DefaultRootWindow( display );
401 gdi_display = display;
402 old_error_handler = XSetErrorHandler( error_handler );
404 /* Initialize screen depth */
406 if (screen_depth) /* depth specified */
408 int depth_count, i;
409 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
410 for (i = 0; i < depth_count; i++)
411 if (depth_list[i] == screen_depth) break;
412 XFree( depth_list );
413 if (i >= depth_count)
415 WARN( "invalid depth %d, using default\n", screen_depth );
416 screen_depth = 0;
419 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
421 /* If OpenGL is available, change the default visual, etc as necessary */
422 if (desktop_dbl_buf && (desktop_vi = X11DRV_setup_opengl_visual( display )))
424 visual = desktop_vi->visual;
425 screen = ScreenOfDisplay(display, desktop_vi->screen);
426 screen_depth = desktop_vi->depth;
427 XFree(desktop_vi);
430 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
432 if (TRACE_ON(synchronous)) XSynchronize( display, True );
434 screen_width = WidthOfScreen( screen );
435 screen_height = HeightOfScreen( screen );
437 xinerama_init();
438 X11DRV_Settings_Init();
440 #ifdef HAVE_LIBXXF86VM
441 /* initialize XVidMode */
442 X11DRV_XF86VM_Init();
443 #endif
444 #ifdef HAVE_LIBXRANDR
445 /* initialize XRandR */
446 X11DRV_XRandR_Init();
447 #endif
449 X11DRV_InitKeyboard();
450 X11DRV_InitClipboard();
452 return TRUE;
456 /***********************************************************************
457 * X11DRV thread termination routine
459 static void thread_detach(void)
461 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
463 if (data)
465 X11DRV_ResetSelectionOwner();
466 CloseHandle( data->display_fd );
467 wine_tsx11_lock();
468 if (data->xim) XCloseIM( data->xim );
469 XCloseDisplay( data->display );
470 wine_tsx11_unlock();
471 HeapFree( GetProcessHeap(), 0, data );
476 /***********************************************************************
477 * X11DRV process termination routine
479 static void process_detach(void)
481 #ifdef HAVE_LIBXXF86VM
482 /* cleanup XVidMode */
483 X11DRV_XF86VM_Cleanup();
484 #endif
485 if(using_client_side_fonts)
486 X11DRV_XRender_Finalize();
488 /* cleanup GDI */
489 X11DRV_GDI_Finalize();
491 DeleteCriticalSection( &X11DRV_CritSection );
492 TlsFree( thread_data_tls_index );
496 /***********************************************************************
497 * X11DRV thread initialisation routine
499 struct x11drv_thread_data *x11drv_init_thread_data(void)
501 struct x11drv_thread_data *data;
503 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
505 ERR( "could not create data\n" );
506 ExitProcess(1);
508 wine_tsx11_lock();
509 if (!(data->display = XOpenDisplay(NULL)))
511 wine_tsx11_unlock();
512 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
513 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
514 ExitProcess(1);
517 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
519 #ifdef HAVE_XKB
520 if (use_xkb)
522 use_xkb = XkbUseExtension( data->display, NULL, NULL );
523 if (use_xkb)
525 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
526 /* This works around an Xlib bug where it tries to get the display lock */
527 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
528 XkbKeysymToModifiers( data->display, 'A' );
529 XkbSetDetectableAutoRepeat( data->display, True, NULL );
532 #endif
534 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
535 wine_tsx11_unlock();
537 if (!use_xim)
538 data->xim = NULL;
539 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
540 WARN("Input Method is not available\n");
542 if (wine_server_fd_to_handle( ConnectionNumber(data->display), GENERIC_READ | SYNCHRONIZE,
543 0, &data->display_fd ))
545 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
546 ExitProcess(1);
548 data->process_event_count = 0;
549 data->cursor = None;
550 data->cursor_window = None;
551 data->grab_window = None;
552 data->last_focus = 0;
553 data->selection_wnd = 0;
554 TlsSetValue( thread_data_tls_index, data );
555 return data;
559 /***********************************************************************
560 * X11DRV initialisation routine
562 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
564 BOOL ret = TRUE;
566 switch(reason)
568 case DLL_PROCESS_ATTACH:
569 ret = process_attach();
570 break;
571 case DLL_THREAD_DETACH:
572 thread_detach();
573 break;
574 case DLL_PROCESS_DETACH:
575 process_detach();
576 break;
578 return ret;
581 /***********************************************************************
582 * GetScreenSaveActive (X11DRV.@)
584 * Returns the active status of the screen saver
586 BOOL X11DRV_GetScreenSaveActive(void)
588 int timeout, temp;
589 wine_tsx11_lock();
590 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
591 wine_tsx11_unlock();
592 return timeout != 0;
595 /***********************************************************************
596 * SetScreenSaveActive (X11DRV.@)
598 * Activate/Deactivate the screen saver
600 void X11DRV_SetScreenSaveActive(BOOL bActivate)
602 int timeout, interval, prefer_blanking, allow_exposures;
603 static int last_timeout = 15 * 60;
605 wine_tsx11_lock();
606 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
607 &allow_exposures);
608 if (timeout) last_timeout = timeout;
610 timeout = bActivate ? last_timeout : 0;
611 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
612 allow_exposures);
613 wine_tsx11_unlock();