wined3d: Remove fake nvidia card in GetAdapterIdentifier.
[wine/dibdrv.git] / dlls / winex11.drv / x11drv_main.c
blob15a362484d1ab594c9ccd2880716e23f75b7fd0c
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 x11drv_error_callback err_callback; /* current callback for error */
93 static Display *err_callback_display; /* display callback is set for */
94 static void *err_callback_arg; /* error callback argument */
95 static int err_callback_result; /* error callback result */
96 static unsigned long err_serial; /* serial number of first request */
97 static int (*old_error_handler)( Display *, XErrorEvent * );
98 static int use_xim = 1;
99 static char input_style[20];
101 #define IS_OPTION_TRUE(ch) \
102 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
103 #define IS_OPTION_FALSE(ch) \
104 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
106 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
108 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
110 "CLIPBOARD",
111 "COMPOUND_TEXT",
112 "MULTIPLE",
113 "SELECTION_DATA",
114 "TARGETS",
115 "TEXT",
116 "UTF8_STRING",
117 "RAW_ASCENT",
118 "RAW_DESCENT",
119 "RAW_CAP_HEIGHT",
120 "WM_PROTOCOLS",
121 "WM_DELETE_WINDOW",
122 "WM_TAKE_FOCUS",
123 "KWM_DOCKWINDOW",
124 "DndProtocol",
125 "DndSelection",
126 "_MOTIF_WM_HINTS",
127 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
128 "_NET_SYSTEM_TRAY_OPCODE",
129 "_NET_SYSTEM_TRAY_S0",
130 "_NET_WM_MOVERESIZE",
131 "_NET_WM_NAME",
132 "_NET_WM_PID",
133 "_NET_WM_PING",
134 "_NET_WM_STATE",
135 "_NET_WM_STATE_FULLSCREEN",
136 "_NET_WM_WINDOW_TYPE",
137 "_NET_WM_WINDOW_TYPE_DIALOG",
138 "_NET_WM_WINDOW_TYPE_NORMAL",
139 "_NET_WM_WINDOW_TYPE_UTILITY",
140 "_XEMBED_INFO",
141 "XdndAware",
142 "XdndEnter",
143 "XdndPosition",
144 "XdndStatus",
145 "XdndLeave",
146 "XdndFinished",
147 "XdndDrop",
148 "XdndActionCopy",
149 "XdndActionMove",
150 "XdndActionLink",
151 "XdndActionAsk",
152 "XdndActionPrivate",
153 "XdndSelection",
154 "XdndTarget",
155 "XdndTypeList",
156 "WCF_DIB",
157 "image/gif",
158 "text/html",
159 "text/plain",
160 "text/rtf",
161 "text/richtext"
164 /***********************************************************************
165 * ignore_error
167 * Check if the X error is one we can ignore.
169 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
171 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
173 /* ignore a number of errors on gdi display caused by creating/destroying windows */
174 if (display == gdi_display)
176 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
177 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
178 if (xrender_error_base) /* check for XRender errors */
180 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
182 #endif
184 return FALSE;
188 /***********************************************************************
189 * X11DRV_expect_error
191 * Setup a callback function that will be called on an X error. The
192 * callback must return non-zero if the error is the one it expected.
193 * This function acquires the x11 lock; X11DRV_check_error must be
194 * called in all cases to release it.
196 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
198 wine_tsx11_lock();
199 err_callback = callback;
200 err_callback_display = display;
201 err_callback_arg = arg;
202 err_callback_result = 0;
203 err_serial = NextRequest(display);
207 /***********************************************************************
208 * X11DRV_check_error
210 * Check if an expected X11 error occurred; return non-zero if yes.
211 * Also release the x11 lock obtained in X11DRV_expect_error.
212 * The caller is responsible for calling XSync first if necessary.
214 int X11DRV_check_error(void)
216 int ret;
217 err_callback = NULL;
218 ret = err_callback_result;
219 wine_tsx11_unlock();
220 return ret;
224 /***********************************************************************
225 * error_handler
227 static int error_handler( Display *display, XErrorEvent *error_evt )
229 if (err_callback && display == err_callback_display &&
230 (long)(error_evt->serial - err_serial) >= 0)
232 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
234 TRACE( "got expected error %d req %d\n",
235 error_evt->error_code, error_evt->request_code );
236 return 0;
239 if (ignore_error( display, error_evt ))
241 TRACE( "got ignored error %d req %d\n",
242 error_evt->error_code, error_evt->request_code );
243 return 0;
245 if (TRACE_ON(synchronous))
247 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
248 error_evt->serial, error_evt->request_code );
249 DebugBreak(); /* force an entry in the debugger */
251 old_error_handler( display, error_evt );
252 return 0;
255 /***********************************************************************
256 * wine_tsx11_lock (X11DRV.@)
258 void wine_tsx11_lock(void)
260 EnterCriticalSection( &X11DRV_CritSection );
263 /***********************************************************************
264 * wine_tsx11_unlock (X11DRV.@)
266 void wine_tsx11_unlock(void)
268 LeaveCriticalSection( &X11DRV_CritSection );
272 /***********************************************************************
273 * get_config_key
275 * Get a config key from either the app-specific or the default config
277 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
278 char *buffer, DWORD size )
280 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
281 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
282 return ERROR_FILE_NOT_FOUND;
286 /***********************************************************************
287 * setup_options
289 * Setup the x11drv options.
291 static void setup_options(void)
293 char buffer[MAX_PATH+16];
294 HKEY hkey, appkey = 0;
295 DWORD len;
297 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
298 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
300 /* open the app-specific key */
302 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
303 if (len && len < MAX_PATH)
305 HKEY tmpkey;
306 char *p, *appname = buffer;
307 if ((p = strrchr( appname, '/' ))) appname = p + 1;
308 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
309 strcat( appname, "\\X11 Driver" );
310 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
311 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
313 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
314 RegCloseKey( tmpkey );
318 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
319 managed_mode = IS_OPTION_TRUE( buffer[0] );
321 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
322 dxgrab = IS_OPTION_TRUE( buffer[0] );
324 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
325 usexvidmode = IS_OPTION_TRUE( buffer[0] );
327 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
328 usexrandr = IS_OPTION_TRUE( buffer[0] );
330 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
331 use_take_focus = IS_OPTION_TRUE( buffer[0] );
333 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
334 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
336 screen_depth = 0;
337 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
338 screen_depth = atoi(buffer);
340 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
341 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
343 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
344 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
346 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
347 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
349 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
350 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
352 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
353 use_xim = IS_OPTION_TRUE( buffer[0] );
355 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
356 private_color_map = IS_OPTION_TRUE( buffer[0] );
358 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
359 primary_monitor = atoi( buffer );
361 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
362 copy_default_colors = atoi(buffer);
364 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
365 alloc_system_colors = atoi(buffer);
367 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
369 if (appkey) RegCloseKey( appkey );
370 if (hkey) RegCloseKey( hkey );
374 /***********************************************************************
375 * X11DRV process initialisation routine
377 static BOOL process_attach(void)
379 Display *display;
380 XVisualInfo *desktop_vi = NULL;
381 const char *env;
383 setup_options();
385 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
387 /* Open display */
389 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
390 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
392 if (!(display = XOpenDisplay( NULL ))) return FALSE;
394 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
395 screen = DefaultScreenOfDisplay( display );
396 visual = DefaultVisual( display, DefaultScreen(display) );
397 root_window = DefaultRootWindow( display );
398 gdi_display = display;
399 old_error_handler = XSetErrorHandler( error_handler );
401 /* Initialize screen depth */
403 if (screen_depth) /* depth specified */
405 int depth_count, i;
406 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
407 for (i = 0; i < depth_count; i++)
408 if (depth_list[i] == screen_depth) break;
409 XFree( depth_list );
410 if (i >= depth_count)
412 WARN( "invalid depth %d, using default\n", screen_depth );
413 screen_depth = 0;
416 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
418 /* If OpenGL is available, change the default visual, etc as necessary */
419 if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
421 visual = desktop_vi->visual;
422 screen = ScreenOfDisplay(display, desktop_vi->screen);
423 screen_depth = desktop_vi->depth;
424 XFree(desktop_vi);
427 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
429 if (TRACE_ON(synchronous)) XSynchronize( display, True );
431 screen_width = WidthOfScreen( screen );
432 screen_height = HeightOfScreen( screen );
434 xinerama_init();
435 X11DRV_Settings_Init();
437 #ifdef HAVE_LIBXXF86VM
438 /* initialize XVidMode */
439 X11DRV_XF86VM_Init();
440 #endif
441 #ifdef HAVE_LIBXRANDR
442 /* initialize XRandR */
443 X11DRV_XRandR_Init();
444 #endif
446 X11DRV_ClipCursor( NULL );
447 X11DRV_InitKeyboard();
448 X11DRV_InitClipboard();
450 return TRUE;
454 /***********************************************************************
455 * X11DRV thread termination routine
457 static void thread_detach(void)
459 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
461 if (data)
463 X11DRV_ResetSelectionOwner();
464 wine_tsx11_lock();
465 if (data->xim) XCloseIM( data->xim );
466 XCloseDisplay( data->display );
467 wine_tsx11_unlock();
468 HeapFree( GetProcessHeap(), 0, data );
473 /***********************************************************************
474 * X11DRV process termination routine
476 static void process_detach(void)
478 #ifdef HAVE_LIBXXF86VM
479 /* cleanup XVidMode */
480 X11DRV_XF86VM_Cleanup();
481 #endif
482 if(using_client_side_fonts)
483 X11DRV_XRender_Finalize();
485 /* cleanup GDI */
486 X11DRV_GDI_Finalize();
488 DeleteCriticalSection( &X11DRV_CritSection );
489 TlsFree( thread_data_tls_index );
493 /* store the display fd into the message queue */
494 static void set_queue_display_fd( Display *display )
496 HANDLE handle;
497 int ret;
499 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
501 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
502 ExitProcess(1);
504 SERVER_START_REQ( set_queue_fd )
506 req->handle = handle;
507 ret = wine_server_call( req );
509 SERVER_END_REQ;
510 if (ret)
512 MESSAGE( "x11drv: Can't store handle for display fd\n" );
513 ExitProcess(1);
515 CloseHandle( handle );
519 /***********************************************************************
520 * X11DRV thread initialisation routine
522 struct x11drv_thread_data *x11drv_init_thread_data(void)
524 struct x11drv_thread_data *data;
526 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
528 ERR( "could not create data\n" );
529 ExitProcess(1);
531 wine_tsx11_lock();
532 if (!(data->display = XOpenDisplay(NULL)))
534 wine_tsx11_unlock();
535 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
536 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
537 ExitProcess(1);
540 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
542 #ifdef HAVE_XKB
543 if (use_xkb)
545 use_xkb = XkbUseExtension( data->display, NULL, NULL );
546 if (use_xkb)
548 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
549 /* This works around an Xlib bug where it tries to get the display lock */
550 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
551 XkbKeysymToModifiers( data->display, 'A' );
552 XkbSetDetectableAutoRepeat( data->display, True, NULL );
555 #endif
557 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
558 wine_tsx11_unlock();
560 if (!use_xim)
561 data->xim = NULL;
562 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
563 WARN("Input Method is not available\n");
565 set_queue_display_fd( data->display );
566 data->process_event_count = 0;
567 data->cursor = None;
568 data->cursor_window = None;
569 data->grab_window = None;
570 data->last_focus = 0;
571 data->selection_wnd = 0;
572 TlsSetValue( thread_data_tls_index, data );
573 return data;
577 /***********************************************************************
578 * X11DRV initialisation routine
580 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
582 BOOL ret = TRUE;
584 switch(reason)
586 case DLL_PROCESS_ATTACH:
587 ret = process_attach();
588 break;
589 case DLL_THREAD_DETACH:
590 thread_detach();
591 break;
592 case DLL_PROCESS_DETACH:
593 process_detach();
594 break;
596 return ret;
599 /***********************************************************************
600 * GetScreenSaveActive (X11DRV.@)
602 * Returns the active status of the screen saver
604 BOOL X11DRV_GetScreenSaveActive(void)
606 int timeout, temp;
607 wine_tsx11_lock();
608 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
609 wine_tsx11_unlock();
610 return timeout != 0;
613 /***********************************************************************
614 * SetScreenSaveActive (X11DRV.@)
616 * Activate/Deactivate the screen saver
618 void X11DRV_SetScreenSaveActive(BOOL bActivate)
620 int timeout, interval, prefer_blanking, allow_exposures;
621 static int last_timeout = 15 * 60;
623 wine_tsx11_lock();
624 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
625 &allow_exposures);
626 if (timeout) last_timeout = timeout;
628 timeout = bActivate ? last_timeout : 0;
629 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
630 allow_exposures);
631 wine_tsx11_unlock();