push ab3cc77eb114d2bd400734a9dccad24563f936a6
[wine/hacks.git] / dlls / winex11.drv / x11drv_main.c
blobf56d4e2eda51224ec48834ce176ef1510ff76f9f
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"
23 #include "wine/port.h"
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #ifdef HAVE_SYS_TIME_H
31 # include <sys/time.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36 #include <X11/cursorfont.h>
37 #include <X11/Xlib.h>
38 #ifdef HAVE_XKB
39 #include <X11/XKBlib.h>
40 #endif
41 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
42 #include <X11/extensions/Xrender.h>
43 #endif
45 #include "windef.h"
46 #include "winbase.h"
47 #include "winreg.h"
49 #include "x11drv.h"
50 #include "xvidmode.h"
51 #include "xrandr.h"
52 #include "xcomposite.h"
53 #include "wine/server.h"
54 #include "wine/debug.h"
55 #include "wine/library.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
58 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
60 static CRITICAL_SECTION X11DRV_CritSection;
61 static CRITICAL_SECTION_DEBUG critsect_debug =
63 0, 0, &X11DRV_CritSection,
64 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
65 0, 0, { (DWORD_PTR)(__FILE__ ": X11DRV_CritSection") }
67 static CRITICAL_SECTION X11DRV_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 };
69 Screen *screen;
70 Visual *visual;
71 unsigned int screen_width;
72 unsigned int screen_height;
73 unsigned int screen_depth;
74 RECT virtual_screen_rect;
75 Window root_window;
76 int dxgrab = 0;
77 int usexvidmode = 1;
78 int usexrandr = 1;
79 int usexcomposite = 1;
80 int use_xkb = 1;
81 int use_take_focus = 1;
82 int use_primary_selection = 0;
83 int managed_mode = 1;
84 int private_color_map = 0;
85 int primary_monitor = 0;
86 int client_side_with_core = 1;
87 int client_side_with_render = 1;
88 int client_side_antialias_with_core = 1;
89 int client_side_antialias_with_render = 1;
90 int copy_default_colors = 128;
91 int alloc_system_colors = 256;
92 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
93 int xrender_error_base = 0;
95 static x11drv_error_callback err_callback; /* current callback for error */
96 static Display *err_callback_display; /* display callback is set for */
97 static void *err_callback_arg; /* error callback argument */
98 static int err_callback_result; /* error callback result */
99 static unsigned long err_serial; /* serial number of first request */
100 static int (*old_error_handler)( Display *, XErrorEvent * );
101 static int use_xim = 1;
102 static char input_style[20];
104 #define IS_OPTION_TRUE(ch) \
105 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
106 #define IS_OPTION_FALSE(ch) \
107 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
109 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
111 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
113 "CLIPBOARD",
114 "COMPOUND_TEXT",
115 "MULTIPLE",
116 "SELECTION_DATA",
117 "TARGETS",
118 "TEXT",
119 "UTF8_STRING",
120 "RAW_ASCENT",
121 "RAW_DESCENT",
122 "RAW_CAP_HEIGHT",
123 "WM_PROTOCOLS",
124 "WM_DELETE_WINDOW",
125 "WM_TAKE_FOCUS",
126 "KWM_DOCKWINDOW",
127 "DndProtocol",
128 "DndSelection",
129 "_MOTIF_WM_HINTS",
130 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
131 "_NET_SYSTEM_TRAY_OPCODE",
132 "_NET_SYSTEM_TRAY_S0",
133 "_NET_WM_MOVERESIZE",
134 "_NET_WM_NAME",
135 "_NET_WM_PID",
136 "_NET_WM_PING",
137 "_NET_WM_STATE",
138 "_NET_WM_STATE_FULLSCREEN",
139 "_NET_WM_WINDOW_TYPE",
140 "_NET_WM_WINDOW_TYPE_DIALOG",
141 "_NET_WM_WINDOW_TYPE_NORMAL",
142 "_NET_WM_WINDOW_TYPE_UTILITY",
143 "_XEMBED_INFO",
144 "XdndAware",
145 "XdndEnter",
146 "XdndPosition",
147 "XdndStatus",
148 "XdndLeave",
149 "XdndFinished",
150 "XdndDrop",
151 "XdndActionCopy",
152 "XdndActionMove",
153 "XdndActionLink",
154 "XdndActionAsk",
155 "XdndActionPrivate",
156 "XdndSelection",
157 "XdndTarget",
158 "XdndTypeList",
159 "WCF_DIB",
160 "image/gif",
161 "text/html",
162 "text/plain",
163 "text/rtf",
164 "text/richtext",
165 "text/uri-list"
168 /***********************************************************************
169 * ignore_error
171 * Check if the X error is one we can ignore.
173 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
175 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
177 /* ignore a number of errors on gdi display caused by creating/destroying windows */
178 if (display == gdi_display)
180 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
181 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
182 if (xrender_error_base) /* check for XRender errors */
184 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
186 #endif
188 return FALSE;
192 /***********************************************************************
193 * X11DRV_expect_error
195 * Setup a callback function that will be called on an X error. The
196 * callback must return non-zero if the error is the one it expected.
197 * This function acquires the x11 lock; X11DRV_check_error must be
198 * called in all cases to release it.
200 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
202 wine_tsx11_lock();
203 err_callback = callback;
204 err_callback_display = display;
205 err_callback_arg = arg;
206 err_callback_result = 0;
207 err_serial = NextRequest(display);
211 /***********************************************************************
212 * X11DRV_check_error
214 * Check if an expected X11 error occurred; return non-zero if yes.
215 * Also release the x11 lock obtained in X11DRV_expect_error.
216 * The caller is responsible for calling XSync first if necessary.
218 int X11DRV_check_error(void)
220 int ret;
221 err_callback = NULL;
222 ret = err_callback_result;
223 wine_tsx11_unlock();
224 return ret;
228 /***********************************************************************
229 * error_handler
231 static int error_handler( Display *display, XErrorEvent *error_evt )
233 if (err_callback && display == err_callback_display &&
234 (long)(error_evt->serial - err_serial) >= 0)
236 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
238 TRACE( "got expected error %d req %d\n",
239 error_evt->error_code, error_evt->request_code );
240 return 0;
243 if (ignore_error( display, error_evt ))
245 TRACE( "got ignored error %d req %d\n",
246 error_evt->error_code, error_evt->request_code );
247 return 0;
249 if (TRACE_ON(synchronous))
251 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
252 error_evt->serial, error_evt->request_code );
253 DebugBreak(); /* force an entry in the debugger */
255 old_error_handler( display, error_evt );
256 return 0;
259 /***********************************************************************
260 * wine_tsx11_lock (X11DRV.@)
262 void wine_tsx11_lock(void)
264 EnterCriticalSection( &X11DRV_CritSection );
267 /***********************************************************************
268 * wine_tsx11_unlock (X11DRV.@)
270 void wine_tsx11_unlock(void)
272 LeaveCriticalSection( &X11DRV_CritSection );
276 /***********************************************************************
277 * get_config_key
279 * Get a config key from either the app-specific or the default config
281 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
282 char *buffer, DWORD size )
284 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
285 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
286 return ERROR_FILE_NOT_FOUND;
290 /***********************************************************************
291 * setup_options
293 * Setup the x11drv options.
295 static void setup_options(void)
297 char buffer[MAX_PATH+16];
298 HKEY hkey, appkey = 0;
299 DWORD len;
301 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
302 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
304 /* open the app-specific key */
306 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
307 if (len && len < MAX_PATH)
309 HKEY tmpkey;
310 char *p, *appname = buffer;
311 if ((p = strrchr( appname, '/' ))) appname = p + 1;
312 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
313 strcat( appname, "\\X11 Driver" );
314 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
315 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
317 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
318 RegCloseKey( tmpkey );
322 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
323 managed_mode = IS_OPTION_TRUE( buffer[0] );
325 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
326 dxgrab = IS_OPTION_TRUE( buffer[0] );
328 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
329 usexvidmode = IS_OPTION_TRUE( buffer[0] );
331 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
332 usexrandr = IS_OPTION_TRUE( buffer[0] );
334 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
335 use_take_focus = IS_OPTION_TRUE( buffer[0] );
337 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
338 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
340 screen_depth = 0;
341 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
342 screen_depth = atoi(buffer);
344 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
345 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
347 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
348 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
350 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
351 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
353 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
354 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
356 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
357 use_xim = IS_OPTION_TRUE( buffer[0] );
359 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
360 private_color_map = IS_OPTION_TRUE( buffer[0] );
362 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
363 primary_monitor = atoi( buffer );
365 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
366 copy_default_colors = atoi(buffer);
368 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
369 alloc_system_colors = atoi(buffer);
371 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
373 if (appkey) RegCloseKey( appkey );
374 if (hkey) RegCloseKey( hkey );
377 #ifdef SONAME_LIBXCOMPOSITE
379 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
380 MAKE_FUNCPTR(XCompositeQueryExtension)
381 MAKE_FUNCPTR(XCompositeQueryVersion)
382 MAKE_FUNCPTR(XCompositeVersion)
383 MAKE_FUNCPTR(XCompositeRedirectWindow)
384 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
385 MAKE_FUNCPTR(XCompositeUnredirectWindow)
386 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
387 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
388 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
389 #undef MAKE_FUNCPTR
391 static int xcomp_event_base;
392 static int xcomp_error_base;
394 static void X11DRV_XComposite_Init(void)
396 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
397 if (!xcomposite_handle)
399 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
400 usexcomposite = 0;
401 return;
404 #define LOAD_FUNCPTR(f) \
405 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
406 goto sym_not_found;
407 LOAD_FUNCPTR(XCompositeQueryExtension)
408 LOAD_FUNCPTR(XCompositeQueryVersion)
409 LOAD_FUNCPTR(XCompositeVersion)
410 LOAD_FUNCPTR(XCompositeRedirectWindow)
411 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
412 LOAD_FUNCPTR(XCompositeUnredirectWindow)
413 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
414 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
415 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
416 #undef LOAD_FUNCPTR
418 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
419 &xcomp_error_base)) {
420 TRACE("XComposite extension could not be queried; disabled\n");
421 wine_dlclose(xcomposite_handle, NULL, 0);
422 xcomposite_handle = NULL;
423 usexcomposite = 0;
424 return;
426 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
427 return;
429 sym_not_found:
430 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
431 wine_dlclose(xcomposite_handle, NULL, 0);
432 xcomposite_handle = NULL;
433 usexcomposite = 0;
435 #endif /* defined(SONAME_LIBXCOMPOSITE) */
438 /***********************************************************************
439 * X11DRV process initialisation routine
441 static BOOL process_attach(void)
443 Display *display;
444 XVisualInfo *desktop_vi = NULL;
445 const char *env;
447 setup_options();
449 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
451 /* Open display */
453 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
454 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
456 if (!(display = XOpenDisplay( NULL ))) return FALSE;
458 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
459 screen = DefaultScreenOfDisplay( display );
460 visual = DefaultVisual( display, DefaultScreen(display) );
461 root_window = DefaultRootWindow( display );
462 gdi_display = display;
463 old_error_handler = XSetErrorHandler( error_handler );
465 /* Initialize screen depth */
467 if (screen_depth) /* depth specified */
469 int depth_count, i;
470 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
471 for (i = 0; i < depth_count; i++)
472 if (depth_list[i] == screen_depth) break;
473 XFree( depth_list );
474 if (i >= depth_count)
476 WARN( "invalid depth %d, using default\n", screen_depth );
477 screen_depth = 0;
480 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
482 /* If OpenGL is available, change the default visual, etc as necessary */
483 if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
485 visual = desktop_vi->visual;
486 screen = ScreenOfDisplay(display, desktop_vi->screen);
487 screen_depth = desktop_vi->depth;
488 XFree(desktop_vi);
491 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
493 if (TRACE_ON(synchronous)) XSynchronize( display, True );
495 screen_width = WidthOfScreen( screen );
496 screen_height = HeightOfScreen( screen );
498 xinerama_init();
499 X11DRV_Settings_Init();
501 #ifdef HAVE_LIBXXF86VM
502 /* initialize XVidMode */
503 X11DRV_XF86VM_Init();
504 #endif
505 #ifdef SONAME_LIBXRANDR
506 /* initialize XRandR */
507 X11DRV_XRandR_Init();
508 #endif
509 #ifdef SONAME_LIBXCOMPOSITE
510 X11DRV_XComposite_Init();
511 #endif
513 X11DRV_ClipCursor( NULL );
514 X11DRV_InitKeyboard();
515 X11DRV_InitClipboard();
517 return TRUE;
521 /***********************************************************************
522 * X11DRV thread termination routine
524 static void thread_detach(void)
526 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
528 if (data)
530 X11DRV_ResetSelectionOwner();
531 wine_tsx11_lock();
532 if (data->xim) XCloseIM( data->xim );
533 XCloseDisplay( data->display );
534 wine_tsx11_unlock();
535 HeapFree( GetProcessHeap(), 0, data );
540 /***********************************************************************
541 * X11DRV process termination routine
543 static void process_detach(void)
545 #ifdef HAVE_LIBXXF86VM
546 /* cleanup XVidMode */
547 X11DRV_XF86VM_Cleanup();
548 #endif
549 if(using_client_side_fonts)
550 X11DRV_XRender_Finalize();
552 /* cleanup GDI */
553 X11DRV_GDI_Finalize();
555 DeleteCriticalSection( &X11DRV_CritSection );
556 TlsFree( thread_data_tls_index );
560 /* store the display fd into the message queue */
561 static void set_queue_display_fd( Display *display )
563 HANDLE handle;
564 int ret;
566 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
568 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
569 ExitProcess(1);
571 SERVER_START_REQ( set_queue_fd )
573 req->handle = handle;
574 ret = wine_server_call( req );
576 SERVER_END_REQ;
577 if (ret)
579 MESSAGE( "x11drv: Can't store handle for display fd\n" );
580 ExitProcess(1);
582 CloseHandle( handle );
586 /***********************************************************************
587 * X11DRV thread initialisation routine
589 struct x11drv_thread_data *x11drv_init_thread_data(void)
591 struct x11drv_thread_data *data;
593 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
595 ERR( "could not create data\n" );
596 ExitProcess(1);
598 wine_tsx11_lock();
599 if (!(data->display = XOpenDisplay(NULL)))
601 wine_tsx11_unlock();
602 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
603 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
604 ExitProcess(1);
607 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
609 #ifdef HAVE_XKB
610 if (use_xkb)
612 use_xkb = XkbUseExtension( data->display, NULL, NULL );
613 if (use_xkb)
615 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
616 /* This works around an Xlib bug where it tries to get the display lock */
617 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
618 XkbKeysymToModifiers( data->display, 'A' );
619 XkbSetDetectableAutoRepeat( data->display, True, NULL );
622 #endif
624 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
625 wine_tsx11_unlock();
627 if (!use_xim)
628 data->xim = NULL;
629 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
630 WARN("Input Method is not available\n");
632 set_queue_display_fd( data->display );
633 data->process_event_count = 0;
634 data->cursor = None;
635 data->cursor_window = None;
636 data->grab_window = None;
637 data->last_focus = 0;
638 data->selection_wnd = 0;
639 TlsSetValue( thread_data_tls_index, data );
640 return data;
644 /***********************************************************************
645 * X11DRV initialisation routine
647 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
649 BOOL ret = TRUE;
651 switch(reason)
653 case DLL_PROCESS_ATTACH:
654 ret = process_attach();
655 break;
656 case DLL_THREAD_DETACH:
657 thread_detach();
658 break;
659 case DLL_PROCESS_DETACH:
660 process_detach();
661 break;
663 return ret;
666 /***********************************************************************
667 * GetScreenSaveActive (X11DRV.@)
669 * Returns the active status of the screen saver
671 BOOL X11DRV_GetScreenSaveActive(void)
673 int timeout, temp;
674 wine_tsx11_lock();
675 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
676 wine_tsx11_unlock();
677 return timeout != 0;
680 /***********************************************************************
681 * SetScreenSaveActive (X11DRV.@)
683 * Activate/Deactivate the screen saver
685 void X11DRV_SetScreenSaveActive(BOOL bActivate)
687 int timeout, interval, prefer_blanking, allow_exposures;
688 static int last_timeout = 15 * 60;
690 wine_tsx11_lock();
691 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
692 &allow_exposures);
693 if (timeout) last_timeout = timeout;
695 timeout = bActivate ? last_timeout : 0;
696 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
697 allow_exposures);
698 wine_tsx11_unlock();