shlwapi/tests: Move URL testing functions from path.c to url.c.
[wine/gsoc_dplay.git] / dlls / winex11.drv / x11drv_main.c
blob1cfc0b0f3ce49c355a556d4da48d0171e30e45f0
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_STATE_SKIP_PAGER",
140 "_NET_WM_STATE_SKIP_TASKBAR",
141 "_NET_WM_WINDOW_TYPE",
142 "_NET_WM_WINDOW_TYPE_DIALOG",
143 "_NET_WM_WINDOW_TYPE_NORMAL",
144 "_NET_WM_WINDOW_TYPE_UTILITY",
145 "_XEMBED_INFO",
146 "XdndAware",
147 "XdndEnter",
148 "XdndPosition",
149 "XdndStatus",
150 "XdndLeave",
151 "XdndFinished",
152 "XdndDrop",
153 "XdndActionCopy",
154 "XdndActionMove",
155 "XdndActionLink",
156 "XdndActionAsk",
157 "XdndActionPrivate",
158 "XdndSelection",
159 "XdndTarget",
160 "XdndTypeList",
161 "WCF_DIB",
162 "image/gif",
163 "text/html",
164 "text/plain",
165 "text/rtf",
166 "text/richtext",
167 "text/uri-list"
170 /***********************************************************************
171 * ignore_error
173 * Check if the X error is one we can ignore.
175 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
177 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
179 /* ignore a number of errors on gdi display caused by creating/destroying windows */
180 if (display == gdi_display)
182 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
183 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
184 if (xrender_error_base) /* check for XRender errors */
186 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
188 #endif
190 return FALSE;
194 /***********************************************************************
195 * X11DRV_expect_error
197 * Setup a callback function that will be called on an X error. The
198 * callback must return non-zero if the error is the one it expected.
199 * This function acquires the x11 lock; X11DRV_check_error must be
200 * called in all cases to release it.
202 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
204 wine_tsx11_lock();
205 err_callback = callback;
206 err_callback_display = display;
207 err_callback_arg = arg;
208 err_callback_result = 0;
209 err_serial = NextRequest(display);
213 /***********************************************************************
214 * X11DRV_check_error
216 * Check if an expected X11 error occurred; return non-zero if yes.
217 * Also release the x11 lock obtained in X11DRV_expect_error.
218 * The caller is responsible for calling XSync first if necessary.
220 int X11DRV_check_error(void)
222 int ret;
223 err_callback = NULL;
224 ret = err_callback_result;
225 wine_tsx11_unlock();
226 return ret;
230 /***********************************************************************
231 * error_handler
233 static int error_handler( Display *display, XErrorEvent *error_evt )
235 if (err_callback && display == err_callback_display &&
236 (long)(error_evt->serial - err_serial) >= 0)
238 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
240 TRACE( "got expected error %d req %d\n",
241 error_evt->error_code, error_evt->request_code );
242 return 0;
245 if (ignore_error( display, error_evt ))
247 TRACE( "got ignored error %d req %d\n",
248 error_evt->error_code, error_evt->request_code );
249 return 0;
251 if (TRACE_ON(synchronous))
253 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
254 error_evt->serial, error_evt->request_code );
255 DebugBreak(); /* force an entry in the debugger */
257 old_error_handler( display, error_evt );
258 return 0;
261 /***********************************************************************
262 * wine_tsx11_lock (X11DRV.@)
264 void wine_tsx11_lock(void)
266 EnterCriticalSection( &X11DRV_CritSection );
269 /***********************************************************************
270 * wine_tsx11_unlock (X11DRV.@)
272 void wine_tsx11_unlock(void)
274 LeaveCriticalSection( &X11DRV_CritSection );
278 /***********************************************************************
279 * get_config_key
281 * Get a config key from either the app-specific or the default config
283 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
284 char *buffer, DWORD size )
286 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
287 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
288 return ERROR_FILE_NOT_FOUND;
292 /***********************************************************************
293 * setup_options
295 * Setup the x11drv options.
297 static void setup_options(void)
299 char buffer[MAX_PATH+16];
300 HKEY hkey, appkey = 0;
301 DWORD len;
303 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
304 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
306 /* open the app-specific key */
308 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
309 if (len && len < MAX_PATH)
311 HKEY tmpkey;
312 char *p, *appname = buffer;
313 if ((p = strrchr( appname, '/' ))) appname = p + 1;
314 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
315 strcat( appname, "\\X11 Driver" );
316 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
317 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
319 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
320 RegCloseKey( tmpkey );
324 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
325 managed_mode = IS_OPTION_TRUE( buffer[0] );
327 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
328 dxgrab = IS_OPTION_TRUE( buffer[0] );
330 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
331 usexvidmode = IS_OPTION_TRUE( buffer[0] );
333 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
334 usexrandr = IS_OPTION_TRUE( buffer[0] );
336 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
337 use_take_focus = IS_OPTION_TRUE( buffer[0] );
339 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
340 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
342 screen_depth = 0;
343 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
344 screen_depth = atoi(buffer);
346 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
347 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
349 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
350 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
352 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
353 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
355 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
356 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
358 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
359 use_xim = IS_OPTION_TRUE( buffer[0] );
361 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
362 private_color_map = IS_OPTION_TRUE( buffer[0] );
364 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
365 primary_monitor = atoi( buffer );
367 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
368 copy_default_colors = atoi(buffer);
370 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
371 alloc_system_colors = atoi(buffer);
373 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
375 if (appkey) RegCloseKey( appkey );
376 if (hkey) RegCloseKey( hkey );
379 #ifdef SONAME_LIBXCOMPOSITE
381 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
382 MAKE_FUNCPTR(XCompositeQueryExtension)
383 MAKE_FUNCPTR(XCompositeQueryVersion)
384 MAKE_FUNCPTR(XCompositeVersion)
385 MAKE_FUNCPTR(XCompositeRedirectWindow)
386 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
387 MAKE_FUNCPTR(XCompositeUnredirectWindow)
388 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
389 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
390 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
391 #undef MAKE_FUNCPTR
393 static int xcomp_event_base;
394 static int xcomp_error_base;
396 static void X11DRV_XComposite_Init(void)
398 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
399 if (!xcomposite_handle)
401 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
402 usexcomposite = 0;
403 return;
406 #define LOAD_FUNCPTR(f) \
407 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
408 goto sym_not_found;
409 LOAD_FUNCPTR(XCompositeQueryExtension)
410 LOAD_FUNCPTR(XCompositeQueryVersion)
411 LOAD_FUNCPTR(XCompositeVersion)
412 LOAD_FUNCPTR(XCompositeRedirectWindow)
413 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
414 LOAD_FUNCPTR(XCompositeUnredirectWindow)
415 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
416 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
417 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
418 #undef LOAD_FUNCPTR
420 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
421 &xcomp_error_base)) {
422 TRACE("XComposite extension could not be queried; disabled\n");
423 wine_dlclose(xcomposite_handle, NULL, 0);
424 xcomposite_handle = NULL;
425 usexcomposite = 0;
426 return;
428 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
429 return;
431 sym_not_found:
432 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
433 wine_dlclose(xcomposite_handle, NULL, 0);
434 xcomposite_handle = NULL;
435 usexcomposite = 0;
437 #endif /* defined(SONAME_LIBXCOMPOSITE) */
440 /***********************************************************************
441 * X11DRV process initialisation routine
443 static BOOL process_attach(void)
445 Display *display;
446 XVisualInfo *desktop_vi = NULL;
447 const char *env;
449 setup_options();
451 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
453 /* Open display */
455 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
456 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
458 if (!(display = XOpenDisplay( NULL ))) return FALSE;
460 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
461 screen = DefaultScreenOfDisplay( display );
462 visual = DefaultVisual( display, DefaultScreen(display) );
463 root_window = DefaultRootWindow( display );
464 gdi_display = display;
465 old_error_handler = XSetErrorHandler( error_handler );
467 /* Initialize screen depth */
469 if (screen_depth) /* depth specified */
471 int depth_count, i;
472 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
473 for (i = 0; i < depth_count; i++)
474 if (depth_list[i] == screen_depth) break;
475 XFree( depth_list );
476 if (i >= depth_count)
478 WARN( "invalid depth %d, using default\n", screen_depth );
479 screen_depth = 0;
482 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
484 /* If OpenGL is available, change the default visual, etc as necessary */
485 if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
487 visual = desktop_vi->visual;
488 screen = ScreenOfDisplay(display, desktop_vi->screen);
489 screen_depth = desktop_vi->depth;
490 XFree(desktop_vi);
493 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
495 if (TRACE_ON(synchronous)) XSynchronize( display, True );
497 screen_width = WidthOfScreen( screen );
498 screen_height = HeightOfScreen( screen );
500 xinerama_init();
501 X11DRV_Settings_Init();
503 #ifdef HAVE_LIBXXF86VM
504 /* initialize XVidMode */
505 X11DRV_XF86VM_Init();
506 #endif
507 #ifdef SONAME_LIBXRANDR
508 /* initialize XRandR */
509 X11DRV_XRandR_Init();
510 #endif
511 #ifdef SONAME_LIBXCOMPOSITE
512 X11DRV_XComposite_Init();
513 #endif
515 X11DRV_ClipCursor( NULL );
516 X11DRV_InitKeyboard();
517 X11DRV_InitClipboard();
519 return TRUE;
523 /***********************************************************************
524 * X11DRV thread termination routine
526 static void thread_detach(void)
528 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
530 if (data)
532 X11DRV_ResetSelectionOwner();
533 wine_tsx11_lock();
534 if (data->xim) XCloseIM( data->xim );
535 XCloseDisplay( data->display );
536 wine_tsx11_unlock();
537 HeapFree( GetProcessHeap(), 0, data );
542 /***********************************************************************
543 * X11DRV process termination routine
545 static void process_detach(void)
547 #ifdef HAVE_LIBXXF86VM
548 /* cleanup XVidMode */
549 X11DRV_XF86VM_Cleanup();
550 #endif
551 if(using_client_side_fonts)
552 X11DRV_XRender_Finalize();
554 /* cleanup GDI */
555 X11DRV_GDI_Finalize();
557 DeleteCriticalSection( &X11DRV_CritSection );
558 TlsFree( thread_data_tls_index );
562 /* store the display fd into the message queue */
563 static void set_queue_display_fd( Display *display )
565 HANDLE handle;
566 int ret;
568 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
570 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
571 ExitProcess(1);
573 SERVER_START_REQ( set_queue_fd )
575 req->handle = handle;
576 ret = wine_server_call( req );
578 SERVER_END_REQ;
579 if (ret)
581 MESSAGE( "x11drv: Can't store handle for display fd\n" );
582 ExitProcess(1);
584 CloseHandle( handle );
588 /***********************************************************************
589 * X11DRV thread initialisation routine
591 struct x11drv_thread_data *x11drv_init_thread_data(void)
593 struct x11drv_thread_data *data;
595 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
597 ERR( "could not create data\n" );
598 ExitProcess(1);
600 wine_tsx11_lock();
601 if (!(data->display = XOpenDisplay(NULL)))
603 wine_tsx11_unlock();
604 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
605 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
606 ExitProcess(1);
609 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
611 #ifdef HAVE_XKB
612 if (use_xkb)
614 use_xkb = XkbUseExtension( data->display, NULL, NULL );
615 if (use_xkb)
617 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
618 /* This works around an Xlib bug where it tries to get the display lock */
619 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
620 XkbKeysymToModifiers( data->display, 'A' );
621 XkbSetDetectableAutoRepeat( data->display, True, NULL );
624 #endif
626 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
627 wine_tsx11_unlock();
629 if (!use_xim)
630 data->xim = NULL;
631 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
632 WARN("Input Method is not available\n");
634 set_queue_display_fd( data->display );
635 data->process_event_count = 0;
636 data->cursor = None;
637 data->cursor_window = None;
638 data->grab_window = None;
639 data->last_focus = 0;
640 data->selection_wnd = 0;
641 TlsSetValue( thread_data_tls_index, data );
642 return data;
646 /***********************************************************************
647 * X11DRV initialisation routine
649 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
651 BOOL ret = TRUE;
653 switch(reason)
655 case DLL_PROCESS_ATTACH:
656 ret = process_attach();
657 break;
658 case DLL_THREAD_DETACH:
659 thread_detach();
660 break;
661 case DLL_PROCESS_DETACH:
662 process_detach();
663 break;
665 return ret;
668 /***********************************************************************
669 * GetScreenSaveActive (X11DRV.@)
671 * Returns the active status of the screen saver
673 BOOL X11DRV_GetScreenSaveActive(void)
675 int timeout, temp;
676 wine_tsx11_lock();
677 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
678 wine_tsx11_unlock();
679 return timeout != 0;
682 /***********************************************************************
683 * SetScreenSaveActive (X11DRV.@)
685 * Activate/Deactivate the screen saver
687 void X11DRV_SetScreenSaveActive(BOOL bActivate)
689 int timeout, interval, prefer_blanking, allow_exposures;
690 static int last_timeout = 15 * 60;
692 wine_tsx11_lock();
693 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
694 &allow_exposures);
695 if (timeout) last_timeout = timeout;
697 timeout = bActivate ? last_timeout : 0;
698 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
699 allow_exposures);
700 wine_tsx11_unlock();