winex11: Distinguish between bpp and depth.
[wine/multimedia.git] / dlls / winex11.drv / x11drv_main.c
blob5912a4ae31c4d1751d48f1b4e25541bb17e47f6d
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_bpp;
74 unsigned int screen_depth;
75 RECT virtual_screen_rect;
76 Window root_window;
77 int dxgrab = 0;
78 int usexvidmode = 1;
79 int usexrandr = 1;
80 int usexcomposite = 1;
81 int use_xkb = 1;
82 int use_take_focus = 1;
83 int use_primary_selection = 0;
84 int managed_mode = 1;
85 int private_color_map = 0;
86 int primary_monitor = 0;
87 int client_side_with_core = 1;
88 int client_side_with_render = 1;
89 int client_side_antialias_with_core = 1;
90 int client_side_antialias_with_render = 1;
91 int copy_default_colors = 128;
92 int alloc_system_colors = 256;
93 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
94 int xrender_error_base = 0;
96 static x11drv_error_callback err_callback; /* current callback for error */
97 static Display *err_callback_display; /* display callback is set for */
98 static void *err_callback_arg; /* error callback argument */
99 static int err_callback_result; /* error callback result */
100 static unsigned long err_serial; /* serial number of first request */
101 static int (*old_error_handler)( Display *, XErrorEvent * );
102 static int use_xim = 1;
103 static char input_style[20];
105 #define IS_OPTION_TRUE(ch) \
106 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
107 #define IS_OPTION_FALSE(ch) \
108 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
110 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
112 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
114 "CLIPBOARD",
115 "COMPOUND_TEXT",
116 "MULTIPLE",
117 "SELECTION_DATA",
118 "TARGETS",
119 "TEXT",
120 "UTF8_STRING",
121 "RAW_ASCENT",
122 "RAW_DESCENT",
123 "RAW_CAP_HEIGHT",
124 "WM_PROTOCOLS",
125 "WM_DELETE_WINDOW",
126 "WM_TAKE_FOCUS",
127 "KWM_DOCKWINDOW",
128 "DndProtocol",
129 "DndSelection",
130 "_MOTIF_WM_HINTS",
131 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
132 "_NET_SYSTEM_TRAY_OPCODE",
133 "_NET_SYSTEM_TRAY_S0",
134 "_NET_WM_MOVERESIZE",
135 "_NET_WM_NAME",
136 "_NET_WM_PID",
137 "_NET_WM_PING",
138 "_NET_WM_STATE",
139 "_NET_WM_STATE_ABOVE",
140 "_NET_WM_STATE_FULLSCREEN",
141 "_NET_WM_STATE_SKIP_PAGER",
142 "_NET_WM_STATE_SKIP_TASKBAR",
143 "_NET_WM_WINDOW_TYPE",
144 "_NET_WM_WINDOW_TYPE_DIALOG",
145 "_NET_WM_WINDOW_TYPE_NORMAL",
146 "_NET_WM_WINDOW_TYPE_UTILITY",
147 "_XEMBED_INFO",
148 "XdndAware",
149 "XdndEnter",
150 "XdndPosition",
151 "XdndStatus",
152 "XdndLeave",
153 "XdndFinished",
154 "XdndDrop",
155 "XdndActionCopy",
156 "XdndActionMove",
157 "XdndActionLink",
158 "XdndActionAsk",
159 "XdndActionPrivate",
160 "XdndSelection",
161 "XdndTarget",
162 "XdndTypeList",
163 "WCF_DIB",
164 "image/gif",
165 "text/html",
166 "text/plain",
167 "text/rtf",
168 "text/richtext",
169 "text/uri-list"
172 /***********************************************************************
173 * ignore_error
175 * Check if the X error is one we can ignore.
177 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
179 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
181 /* ignore a number of errors on gdi display caused by creating/destroying windows */
182 if (display == gdi_display)
184 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
185 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
186 if (xrender_error_base) /* check for XRender errors */
188 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
190 #endif
192 return FALSE;
196 /***********************************************************************
197 * X11DRV_expect_error
199 * Setup a callback function that will be called on an X error. The
200 * callback must return non-zero if the error is the one it expected.
201 * This function acquires the x11 lock; X11DRV_check_error must be
202 * called in all cases to release it.
204 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
206 wine_tsx11_lock();
207 err_callback = callback;
208 err_callback_display = display;
209 err_callback_arg = arg;
210 err_callback_result = 0;
211 err_serial = NextRequest(display);
215 /***********************************************************************
216 * X11DRV_check_error
218 * Check if an expected X11 error occurred; return non-zero if yes.
219 * Also release the x11 lock obtained in X11DRV_expect_error.
220 * The caller is responsible for calling XSync first if necessary.
222 int X11DRV_check_error(void)
224 int ret;
225 err_callback = NULL;
226 ret = err_callback_result;
227 wine_tsx11_unlock();
228 return ret;
232 /***********************************************************************
233 * error_handler
235 static int error_handler( Display *display, XErrorEvent *error_evt )
237 if (err_callback && display == err_callback_display &&
238 (long)(error_evt->serial - err_serial) >= 0)
240 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
242 TRACE( "got expected error %d req %d\n",
243 error_evt->error_code, error_evt->request_code );
244 return 0;
247 if (ignore_error( display, error_evt ))
249 TRACE( "got ignored error %d req %d\n",
250 error_evt->error_code, error_evt->request_code );
251 return 0;
253 if (TRACE_ON(synchronous))
255 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
256 error_evt->serial, error_evt->request_code );
257 DebugBreak(); /* force an entry in the debugger */
259 old_error_handler( display, error_evt );
260 return 0;
263 /***********************************************************************
264 * wine_tsx11_lock (X11DRV.@)
266 void wine_tsx11_lock(void)
268 EnterCriticalSection( &X11DRV_CritSection );
271 /***********************************************************************
272 * wine_tsx11_unlock (X11DRV.@)
274 void wine_tsx11_unlock(void)
276 LeaveCriticalSection( &X11DRV_CritSection );
280 /***********************************************************************
281 * get_config_key
283 * Get a config key from either the app-specific or the default config
285 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
286 char *buffer, DWORD size )
288 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
289 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
290 return ERROR_FILE_NOT_FOUND;
294 /***********************************************************************
295 * setup_options
297 * Setup the x11drv options.
299 static void setup_options(void)
301 char buffer[MAX_PATH+16];
302 HKEY hkey, appkey = 0;
303 DWORD len;
305 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
306 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
308 /* open the app-specific key */
310 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
311 if (len && len < MAX_PATH)
313 HKEY tmpkey;
314 char *p, *appname = buffer;
315 if ((p = strrchr( appname, '/' ))) appname = p + 1;
316 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
317 strcat( appname, "\\X11 Driver" );
318 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
319 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
321 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
322 RegCloseKey( tmpkey );
326 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
327 managed_mode = IS_OPTION_TRUE( buffer[0] );
329 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
330 dxgrab = IS_OPTION_TRUE( buffer[0] );
332 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
333 usexvidmode = IS_OPTION_TRUE( buffer[0] );
335 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
336 usexrandr = IS_OPTION_TRUE( buffer[0] );
338 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
339 use_take_focus = IS_OPTION_TRUE( buffer[0] );
341 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
342 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
344 screen_depth = 0;
345 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
346 screen_depth = atoi(buffer);
348 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
349 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
351 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
352 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
354 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
355 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
357 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
358 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
360 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
361 use_xim = IS_OPTION_TRUE( buffer[0] );
363 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
364 private_color_map = IS_OPTION_TRUE( buffer[0] );
366 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
367 primary_monitor = atoi( buffer );
369 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
370 copy_default_colors = atoi(buffer);
372 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
373 alloc_system_colors = atoi(buffer);
375 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
377 if (appkey) RegCloseKey( appkey );
378 if (hkey) RegCloseKey( hkey );
381 #ifdef SONAME_LIBXCOMPOSITE
383 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
384 MAKE_FUNCPTR(XCompositeQueryExtension)
385 MAKE_FUNCPTR(XCompositeQueryVersion)
386 MAKE_FUNCPTR(XCompositeVersion)
387 MAKE_FUNCPTR(XCompositeRedirectWindow)
388 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
389 MAKE_FUNCPTR(XCompositeUnredirectWindow)
390 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
391 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
392 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
393 #undef MAKE_FUNCPTR
395 static int xcomp_event_base;
396 static int xcomp_error_base;
398 static void X11DRV_XComposite_Init(void)
400 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
401 if (!xcomposite_handle)
403 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
404 usexcomposite = 0;
405 return;
408 #define LOAD_FUNCPTR(f) \
409 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
410 goto sym_not_found;
411 LOAD_FUNCPTR(XCompositeQueryExtension)
412 LOAD_FUNCPTR(XCompositeQueryVersion)
413 LOAD_FUNCPTR(XCompositeVersion)
414 LOAD_FUNCPTR(XCompositeRedirectWindow)
415 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
416 LOAD_FUNCPTR(XCompositeUnredirectWindow)
417 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
418 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
419 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
420 #undef LOAD_FUNCPTR
422 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
423 &xcomp_error_base)) {
424 TRACE("XComposite extension could not be queried; disabled\n");
425 wine_dlclose(xcomposite_handle, NULL, 0);
426 xcomposite_handle = NULL;
427 usexcomposite = 0;
428 return;
430 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
431 return;
433 sym_not_found:
434 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
435 wine_dlclose(xcomposite_handle, NULL, 0);
436 xcomposite_handle = NULL;
437 usexcomposite = 0;
439 #endif /* defined(SONAME_LIBXCOMPOSITE) */
442 /***********************************************************************
443 * X11DRV process initialisation routine
445 static BOOL process_attach(void)
447 Display *display;
448 XVisualInfo *desktop_vi = NULL;
449 const char *env;
451 setup_options();
453 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
455 /* Open display */
457 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
458 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
460 if (!(display = XOpenDisplay( NULL ))) return FALSE;
462 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
463 screen = DefaultScreenOfDisplay( display );
464 visual = DefaultVisual( display, DefaultScreen(display) );
465 root_window = DefaultRootWindow( display );
466 gdi_display = display;
467 old_error_handler = XSetErrorHandler( error_handler );
469 /* Initialize screen depth */
471 if (screen_depth) /* depth specified */
473 int depth_count, i;
474 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
475 for (i = 0; i < depth_count; i++)
476 if (depth_list[i] == screen_depth) break;
477 XFree( depth_list );
478 if (i >= depth_count)
480 WARN( "invalid depth %d, using default\n", screen_depth );
481 screen_depth = 0;
484 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
486 /* If OpenGL is available, change the default visual, etc as necessary */
487 if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
489 visual = desktop_vi->visual;
490 screen = ScreenOfDisplay(display, desktop_vi->screen);
491 screen_depth = desktop_vi->depth;
492 XFree(desktop_vi);
495 screen_bpp = screen_depth; /* TODO */
497 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
499 if (TRACE_ON(synchronous)) XSynchronize( display, True );
501 screen_width = WidthOfScreen( screen );
502 screen_height = HeightOfScreen( screen );
504 xinerama_init();
505 X11DRV_Settings_Init();
507 #ifdef HAVE_LIBXXF86VM
508 /* initialize XVidMode */
509 X11DRV_XF86VM_Init();
510 #endif
511 #ifdef SONAME_LIBXRANDR
512 /* initialize XRandR */
513 X11DRV_XRandR_Init();
514 #endif
515 #ifdef SONAME_LIBXCOMPOSITE
516 X11DRV_XComposite_Init();
517 #endif
519 X11DRV_ClipCursor( NULL );
520 X11DRV_InitKeyboard();
521 X11DRV_InitClipboard();
523 return TRUE;
527 /***********************************************************************
528 * X11DRV thread termination routine
530 static void thread_detach(void)
532 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
534 if (data)
536 X11DRV_ResetSelectionOwner();
537 wine_tsx11_lock();
538 if (data->xim) XCloseIM( data->xim );
539 XCloseDisplay( data->display );
540 wine_tsx11_unlock();
541 HeapFree( GetProcessHeap(), 0, data );
546 /***********************************************************************
547 * X11DRV process termination routine
549 static void process_detach(void)
551 #ifdef HAVE_LIBXXF86VM
552 /* cleanup XVidMode */
553 X11DRV_XF86VM_Cleanup();
554 #endif
555 if(using_client_side_fonts)
556 X11DRV_XRender_Finalize();
558 /* cleanup GDI */
559 X11DRV_GDI_Finalize();
561 DeleteCriticalSection( &X11DRV_CritSection );
562 TlsFree( thread_data_tls_index );
566 /* store the display fd into the message queue */
567 static void set_queue_display_fd( Display *display )
569 HANDLE handle;
570 int ret;
572 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
574 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
575 ExitProcess(1);
577 SERVER_START_REQ( set_queue_fd )
579 req->handle = handle;
580 ret = wine_server_call( req );
582 SERVER_END_REQ;
583 if (ret)
585 MESSAGE( "x11drv: Can't store handle for display fd\n" );
586 ExitProcess(1);
588 CloseHandle( handle );
592 /***********************************************************************
593 * X11DRV thread initialisation routine
595 struct x11drv_thread_data *x11drv_init_thread_data(void)
597 struct x11drv_thread_data *data;
599 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
601 ERR( "could not create data\n" );
602 ExitProcess(1);
604 wine_tsx11_lock();
605 if (!(data->display = XOpenDisplay(NULL)))
607 wine_tsx11_unlock();
608 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
609 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
610 ExitProcess(1);
613 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
615 #ifdef HAVE_XKB
616 if (use_xkb)
618 use_xkb = XkbUseExtension( data->display, NULL, NULL );
619 if (use_xkb)
621 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
622 /* This works around an Xlib bug where it tries to get the display lock */
623 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
624 XkbKeysymToModifiers( data->display, 'A' );
625 XkbSetDetectableAutoRepeat( data->display, True, NULL );
628 #endif
630 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
631 wine_tsx11_unlock();
633 if (!use_xim)
634 data->xim = NULL;
635 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
636 WARN("Input Method is not available\n");
638 set_queue_display_fd( data->display );
639 data->process_event_count = 0;
640 data->cursor = None;
641 data->cursor_window = None;
642 data->grab_window = None;
643 data->last_focus = 0;
644 data->selection_wnd = 0;
645 TlsSetValue( thread_data_tls_index, data );
646 return data;
650 /***********************************************************************
651 * X11DRV initialisation routine
653 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
655 BOOL ret = TRUE;
657 switch(reason)
659 case DLL_PROCESS_ATTACH:
660 ret = process_attach();
661 break;
662 case DLL_THREAD_DETACH:
663 thread_detach();
664 break;
665 case DLL_PROCESS_DETACH:
666 process_detach();
667 break;
669 return ret;
672 /***********************************************************************
673 * GetScreenSaveActive (X11DRV.@)
675 * Returns the active status of the screen saver
677 BOOL X11DRV_GetScreenSaveActive(void)
679 int timeout, temp;
680 wine_tsx11_lock();
681 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
682 wine_tsx11_unlock();
683 return timeout != 0;
686 /***********************************************************************
687 * SetScreenSaveActive (X11DRV.@)
689 * Activate/Deactivate the screen saver
691 void X11DRV_SetScreenSaveActive(BOOL bActivate)
693 int timeout, interval, prefer_blanking, allow_exposures;
694 static int last_timeout = 15 * 60;
696 wine_tsx11_lock();
697 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
698 &allow_exposures);
699 if (timeout) last_timeout = timeout;
701 timeout = bActivate ? last_timeout : 0;
702 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
703 allow_exposures);
704 wine_tsx11_unlock();