push ad05fa8ea86b4a1581adad6c24ad723042d385d2
[wine/hacks.git] / dlls / winex11.drv / x11drv_main.c
blobd26fa8be2b822b3718e842d5ed429a487d9bf8e8
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_ABOVE",
139 "_NET_WM_STATE_FULLSCREEN",
140 "_NET_WM_STATE_SKIP_PAGER",
141 "_NET_WM_STATE_SKIP_TASKBAR",
142 "_NET_WM_WINDOW_TYPE",
143 "_NET_WM_WINDOW_TYPE_DIALOG",
144 "_NET_WM_WINDOW_TYPE_NORMAL",
145 "_NET_WM_WINDOW_TYPE_UTILITY",
146 "_XEMBED_INFO",
147 "XdndAware",
148 "XdndEnter",
149 "XdndPosition",
150 "XdndStatus",
151 "XdndLeave",
152 "XdndFinished",
153 "XdndDrop",
154 "XdndActionCopy",
155 "XdndActionMove",
156 "XdndActionLink",
157 "XdndActionAsk",
158 "XdndActionPrivate",
159 "XdndSelection",
160 "XdndTarget",
161 "XdndTypeList",
162 "WCF_DIB",
163 "image/gif",
164 "text/html",
165 "text/plain",
166 "text/rtf",
167 "text/richtext",
168 "text/uri-list"
171 /***********************************************************************
172 * ignore_error
174 * Check if the X error is one we can ignore.
176 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
178 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
180 /* ignore a number of errors on gdi display caused by creating/destroying windows */
181 if (display == gdi_display)
183 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
184 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
185 if (xrender_error_base) /* check for XRender errors */
187 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
189 #endif
191 return FALSE;
195 /***********************************************************************
196 * X11DRV_expect_error
198 * Setup a callback function that will be called on an X error. The
199 * callback must return non-zero if the error is the one it expected.
200 * This function acquires the x11 lock; X11DRV_check_error must be
201 * called in all cases to release it.
203 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
205 wine_tsx11_lock();
206 err_callback = callback;
207 err_callback_display = display;
208 err_callback_arg = arg;
209 err_callback_result = 0;
210 err_serial = NextRequest(display);
214 /***********************************************************************
215 * X11DRV_check_error
217 * Check if an expected X11 error occurred; return non-zero if yes.
218 * Also release the x11 lock obtained in X11DRV_expect_error.
219 * The caller is responsible for calling XSync first if necessary.
221 int X11DRV_check_error(void)
223 int ret;
224 err_callback = NULL;
225 ret = err_callback_result;
226 wine_tsx11_unlock();
227 return ret;
231 /***********************************************************************
232 * error_handler
234 static int error_handler( Display *display, XErrorEvent *error_evt )
236 if (err_callback && display == err_callback_display &&
237 (long)(error_evt->serial - err_serial) >= 0)
239 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
241 TRACE( "got expected error %d req %d\n",
242 error_evt->error_code, error_evt->request_code );
243 return 0;
246 if (ignore_error( display, error_evt ))
248 TRACE( "got ignored error %d req %d\n",
249 error_evt->error_code, error_evt->request_code );
250 return 0;
252 if (TRACE_ON(synchronous))
254 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
255 error_evt->serial, error_evt->request_code );
256 DebugBreak(); /* force an entry in the debugger */
258 old_error_handler( display, error_evt );
259 return 0;
262 /***********************************************************************
263 * wine_tsx11_lock (X11DRV.@)
265 void wine_tsx11_lock(void)
267 EnterCriticalSection( &X11DRV_CritSection );
270 /***********************************************************************
271 * wine_tsx11_unlock (X11DRV.@)
273 void wine_tsx11_unlock(void)
275 LeaveCriticalSection( &X11DRV_CritSection );
279 /***********************************************************************
280 * get_config_key
282 * Get a config key from either the app-specific or the default config
284 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
285 char *buffer, DWORD size )
287 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
288 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
289 return ERROR_FILE_NOT_FOUND;
293 /***********************************************************************
294 * setup_options
296 * Setup the x11drv options.
298 static void setup_options(void)
300 char buffer[MAX_PATH+16];
301 HKEY hkey, appkey = 0;
302 DWORD len;
304 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
305 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
307 /* open the app-specific key */
309 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
310 if (len && len < MAX_PATH)
312 HKEY tmpkey;
313 char *p, *appname = buffer;
314 if ((p = strrchr( appname, '/' ))) appname = p + 1;
315 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
316 strcat( appname, "\\X11 Driver" );
317 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
318 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
320 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
321 RegCloseKey( tmpkey );
325 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
326 managed_mode = IS_OPTION_TRUE( buffer[0] );
328 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
329 dxgrab = IS_OPTION_TRUE( buffer[0] );
331 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
332 usexvidmode = IS_OPTION_TRUE( buffer[0] );
334 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
335 usexrandr = IS_OPTION_TRUE( buffer[0] );
337 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
338 use_take_focus = IS_OPTION_TRUE( buffer[0] );
340 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
341 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
343 screen_depth = 0;
344 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
345 screen_depth = atoi(buffer);
347 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
348 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
350 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
351 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
353 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
354 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
356 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
357 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
359 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
360 use_xim = IS_OPTION_TRUE( buffer[0] );
362 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
363 private_color_map = IS_OPTION_TRUE( buffer[0] );
365 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
366 primary_monitor = atoi( buffer );
368 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
369 copy_default_colors = atoi(buffer);
371 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
372 alloc_system_colors = atoi(buffer);
374 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
376 if (appkey) RegCloseKey( appkey );
377 if (hkey) RegCloseKey( hkey );
380 #ifdef SONAME_LIBXCOMPOSITE
382 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
383 MAKE_FUNCPTR(XCompositeQueryExtension)
384 MAKE_FUNCPTR(XCompositeQueryVersion)
385 MAKE_FUNCPTR(XCompositeVersion)
386 MAKE_FUNCPTR(XCompositeRedirectWindow)
387 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
388 MAKE_FUNCPTR(XCompositeUnredirectWindow)
389 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
390 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
391 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
392 #undef MAKE_FUNCPTR
394 static int xcomp_event_base;
395 static int xcomp_error_base;
397 static void X11DRV_XComposite_Init(void)
399 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
400 if (!xcomposite_handle)
402 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
403 usexcomposite = 0;
404 return;
407 #define LOAD_FUNCPTR(f) \
408 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
409 goto sym_not_found;
410 LOAD_FUNCPTR(XCompositeQueryExtension)
411 LOAD_FUNCPTR(XCompositeQueryVersion)
412 LOAD_FUNCPTR(XCompositeVersion)
413 LOAD_FUNCPTR(XCompositeRedirectWindow)
414 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
415 LOAD_FUNCPTR(XCompositeUnredirectWindow)
416 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
417 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
418 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
419 #undef LOAD_FUNCPTR
421 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
422 &xcomp_error_base)) {
423 TRACE("XComposite extension could not be queried; disabled\n");
424 wine_dlclose(xcomposite_handle, NULL, 0);
425 xcomposite_handle = NULL;
426 usexcomposite = 0;
427 return;
429 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
430 return;
432 sym_not_found:
433 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
434 wine_dlclose(xcomposite_handle, NULL, 0);
435 xcomposite_handle = NULL;
436 usexcomposite = 0;
438 #endif /* defined(SONAME_LIBXCOMPOSITE) */
441 /***********************************************************************
442 * X11DRV process initialisation routine
444 static BOOL process_attach(void)
446 Display *display;
447 XVisualInfo *desktop_vi = NULL;
448 const char *env;
450 setup_options();
452 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
454 /* Open display */
456 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
457 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
459 if (!(display = XOpenDisplay( NULL ))) return FALSE;
461 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
462 screen = DefaultScreenOfDisplay( display );
463 visual = DefaultVisual( display, DefaultScreen(display) );
464 root_window = DefaultRootWindow( display );
465 gdi_display = display;
466 old_error_handler = XSetErrorHandler( error_handler );
468 /* Initialize screen depth */
470 if (screen_depth) /* depth specified */
472 int depth_count, i;
473 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
474 for (i = 0; i < depth_count; i++)
475 if (depth_list[i] == screen_depth) break;
476 XFree( depth_list );
477 if (i >= depth_count)
479 WARN( "invalid depth %d, using default\n", screen_depth );
480 screen_depth = 0;
483 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
485 /* If OpenGL is available, change the default visual, etc as necessary */
486 if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
488 visual = desktop_vi->visual;
489 screen = ScreenOfDisplay(display, desktop_vi->screen);
490 screen_depth = desktop_vi->depth;
491 XFree(desktop_vi);
494 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
496 if (TRACE_ON(synchronous)) XSynchronize( display, True );
498 screen_width = WidthOfScreen( screen );
499 screen_height = HeightOfScreen( screen );
501 xinerama_init();
502 X11DRV_Settings_Init();
504 #ifdef HAVE_LIBXXF86VM
505 /* initialize XVidMode */
506 X11DRV_XF86VM_Init();
507 #endif
508 #ifdef SONAME_LIBXRANDR
509 /* initialize XRandR */
510 X11DRV_XRandR_Init();
511 #endif
512 #ifdef SONAME_LIBXCOMPOSITE
513 X11DRV_XComposite_Init();
514 #endif
516 X11DRV_ClipCursor( NULL );
517 X11DRV_InitKeyboard();
518 X11DRV_InitClipboard();
520 return TRUE;
524 /***********************************************************************
525 * X11DRV thread termination routine
527 static void thread_detach(void)
529 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
531 if (data)
533 X11DRV_ResetSelectionOwner();
534 wine_tsx11_lock();
535 if (data->xim) XCloseIM( data->xim );
536 XCloseDisplay( data->display );
537 wine_tsx11_unlock();
538 HeapFree( GetProcessHeap(), 0, data );
543 /***********************************************************************
544 * X11DRV process termination routine
546 static void process_detach(void)
548 #ifdef HAVE_LIBXXF86VM
549 /* cleanup XVidMode */
550 X11DRV_XF86VM_Cleanup();
551 #endif
552 if(using_client_side_fonts)
553 X11DRV_XRender_Finalize();
555 /* cleanup GDI */
556 X11DRV_GDI_Finalize();
558 DeleteCriticalSection( &X11DRV_CritSection );
559 TlsFree( thread_data_tls_index );
563 /* store the display fd into the message queue */
564 static void set_queue_display_fd( Display *display )
566 HANDLE handle;
567 int ret;
569 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
571 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
572 ExitProcess(1);
574 SERVER_START_REQ( set_queue_fd )
576 req->handle = handle;
577 ret = wine_server_call( req );
579 SERVER_END_REQ;
580 if (ret)
582 MESSAGE( "x11drv: Can't store handle for display fd\n" );
583 ExitProcess(1);
585 CloseHandle( handle );
589 /***********************************************************************
590 * X11DRV thread initialisation routine
592 struct x11drv_thread_data *x11drv_init_thread_data(void)
594 struct x11drv_thread_data *data;
596 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
598 ERR( "could not create data\n" );
599 ExitProcess(1);
601 wine_tsx11_lock();
602 if (!(data->display = XOpenDisplay(NULL)))
604 wine_tsx11_unlock();
605 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
606 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
607 ExitProcess(1);
610 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
612 #ifdef HAVE_XKB
613 if (use_xkb)
615 use_xkb = XkbUseExtension( data->display, NULL, NULL );
616 if (use_xkb)
618 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
619 /* This works around an Xlib bug where it tries to get the display lock */
620 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
621 XkbKeysymToModifiers( data->display, 'A' );
622 XkbSetDetectableAutoRepeat( data->display, True, NULL );
625 #endif
627 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
628 wine_tsx11_unlock();
630 if (!use_xim)
631 data->xim = NULL;
632 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
633 WARN("Input Method is not available\n");
635 set_queue_display_fd( data->display );
636 data->process_event_count = 0;
637 data->cursor = None;
638 data->cursor_window = None;
639 data->grab_window = None;
640 data->last_focus = 0;
641 data->selection_wnd = 0;
642 TlsSetValue( thread_data_tls_index, data );
643 return data;
647 /***********************************************************************
648 * X11DRV initialisation routine
650 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
652 BOOL ret = TRUE;
654 switch(reason)
656 case DLL_PROCESS_ATTACH:
657 ret = process_attach();
658 break;
659 case DLL_THREAD_DETACH:
660 thread_detach();
661 break;
662 case DLL_PROCESS_DETACH:
663 process_detach();
664 break;
666 return ret;
669 /***********************************************************************
670 * GetScreenSaveActive (X11DRV.@)
672 * Returns the active status of the screen saver
674 BOOL X11DRV_GetScreenSaveActive(void)
676 int timeout, temp;
677 wine_tsx11_lock();
678 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
679 wine_tsx11_unlock();
680 return timeout != 0;
683 /***********************************************************************
684 * SetScreenSaveActive (X11DRV.@)
686 * Activate/Deactivate the screen saver
688 void X11DRV_SetScreenSaveActive(BOOL bActivate)
690 int timeout, interval, prefer_blanking, allow_exposures;
691 static int last_timeout = 15 * 60;
693 wine_tsx11_lock();
694 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
695 &allow_exposures);
696 if (timeout) last_timeout = timeout;
698 timeout = bActivate ? last_timeout : 0;
699 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
700 allow_exposures);
701 wine_tsx11_unlock();