push 8edcbf8579c1d48dd3fb4c679acf4b3012a9efac
[wine/hacks.git] / dlls / winex11.drv / x11drv_main.c
blob25a86f013b94eae5b00d36e2183fb8cc1ba088e1
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 decorated_mode = 1;
86 int private_color_map = 0;
87 int primary_monitor = 0;
88 int client_side_with_core = 1;
89 int client_side_with_render = 1;
90 int client_side_antialias_with_core = 1;
91 int client_side_antialias_with_render = 1;
92 int copy_default_colors = 128;
93 int alloc_system_colors = 256;
94 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
95 int xrender_error_base = 0;
96 HMODULE x11drv_module = 0;
98 static x11drv_error_callback err_callback; /* current callback for error */
99 static Display *err_callback_display; /* display callback is set for */
100 static void *err_callback_arg; /* error callback argument */
101 static int err_callback_result; /* error callback result */
102 static unsigned long err_serial; /* serial number of first request */
103 static int (*old_error_handler)( Display *, XErrorEvent * );
104 static int use_xim = 1;
105 static char input_style[20];
107 #define IS_OPTION_TRUE(ch) \
108 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
109 #define IS_OPTION_FALSE(ch) \
110 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
112 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
114 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
116 "CLIPBOARD",
117 "COMPOUND_TEXT",
118 "MULTIPLE",
119 "SELECTION_DATA",
120 "TARGETS",
121 "TEXT",
122 "UTF8_STRING",
123 "RAW_ASCENT",
124 "RAW_DESCENT",
125 "RAW_CAP_HEIGHT",
126 "WM_PROTOCOLS",
127 "WM_DELETE_WINDOW",
128 "WM_STATE",
129 "WM_TAKE_FOCUS",
130 "DndProtocol",
131 "DndSelection",
132 "_ICC_PROFILE",
133 "_MOTIF_WM_HINTS",
134 "_NET_SUPPORTED",
135 "_NET_SYSTEM_TRAY_OPCODE",
136 "_NET_SYSTEM_TRAY_S0",
137 "_NET_WM_MOVERESIZE",
138 "_NET_WM_NAME",
139 "_NET_WM_PID",
140 "_NET_WM_PING",
141 "_NET_WM_STATE",
142 "_NET_WM_STATE_ABOVE",
143 "_NET_WM_STATE_FULLSCREEN",
144 "_NET_WM_STATE_MAXIMIZED_HORZ",
145 "_NET_WM_STATE_MAXIMIZED_VERT",
146 "_NET_WM_STATE_SKIP_PAGER",
147 "_NET_WM_STATE_SKIP_TASKBAR",
148 "_NET_WM_WINDOW_OPACITY",
149 "_NET_WM_WINDOW_TYPE",
150 "_NET_WM_WINDOW_TYPE_DIALOG",
151 "_NET_WM_WINDOW_TYPE_NORMAL",
152 "_NET_WM_WINDOW_TYPE_UTILITY",
153 "_XEMBED_INFO",
154 "XdndAware",
155 "XdndEnter",
156 "XdndPosition",
157 "XdndStatus",
158 "XdndLeave",
159 "XdndFinished",
160 "XdndDrop",
161 "XdndActionCopy",
162 "XdndActionMove",
163 "XdndActionLink",
164 "XdndActionAsk",
165 "XdndActionPrivate",
166 "XdndSelection",
167 "XdndTarget",
168 "XdndTypeList",
169 "WCF_DIB",
170 "image/gif",
171 "text/html",
172 "text/plain",
173 "text/rtf",
174 "text/richtext",
175 "text/uri-list"
178 /***********************************************************************
179 * ignore_error
181 * Check if the X error is one we can ignore.
183 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
185 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
187 /* ignore a number of errors on gdi display caused by creating/destroying windows */
188 if (display == gdi_display)
190 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
191 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
192 if (xrender_error_base) /* check for XRender errors */
194 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
196 #endif
198 return FALSE;
202 /***********************************************************************
203 * X11DRV_expect_error
205 * Setup a callback function that will be called on an X error. The
206 * callback must return non-zero if the error is the one it expected.
207 * This function acquires the x11 lock; X11DRV_check_error must be
208 * called in all cases to release it.
210 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
212 wine_tsx11_lock();
213 err_callback = callback;
214 err_callback_display = display;
215 err_callback_arg = arg;
216 err_callback_result = 0;
217 err_serial = NextRequest(display);
221 /***********************************************************************
222 * X11DRV_check_error
224 * Check if an expected X11 error occurred; return non-zero if yes.
225 * Also release the x11 lock obtained in X11DRV_expect_error.
226 * The caller is responsible for calling XSync first if necessary.
228 int X11DRV_check_error(void)
230 int ret;
231 err_callback = NULL;
232 ret = err_callback_result;
233 wine_tsx11_unlock();
234 return ret;
238 /***********************************************************************
239 * error_handler
241 static int error_handler( Display *display, XErrorEvent *error_evt )
243 if (err_callback && display == err_callback_display &&
244 (long)(error_evt->serial - err_serial) >= 0)
246 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
248 TRACE( "got expected error %d req %d\n",
249 error_evt->error_code, error_evt->request_code );
250 return 0;
253 if (ignore_error( display, error_evt ))
255 TRACE( "got ignored error %d req %d\n",
256 error_evt->error_code, error_evt->request_code );
257 return 0;
259 if (TRACE_ON(synchronous))
261 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
262 error_evt->serial, error_evt->request_code );
263 DebugBreak(); /* force an entry in the debugger */
265 old_error_handler( display, error_evt );
266 return 0;
269 /***********************************************************************
270 * wine_tsx11_lock (X11DRV.@)
272 void wine_tsx11_lock(void)
274 EnterCriticalSection( &X11DRV_CritSection );
277 /***********************************************************************
278 * wine_tsx11_unlock (X11DRV.@)
280 void wine_tsx11_unlock(void)
282 LeaveCriticalSection( &X11DRV_CritSection );
286 /***********************************************************************
287 * depth_to_bpp
289 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
291 unsigned int depth_to_bpp( unsigned int depth )
293 switch (depth)
295 case 1:
296 case 8:
297 return depth;
298 case 15:
299 case 16:
300 return 16;
301 case 24:
302 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
303 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
304 * for windowing, but gl applications can get visuals with alpha channels. So we
305 * should check the framebuffer and/or opengl formats available to find out what the
306 * framebuffer actually does
308 case 32:
309 return 32;
310 default:
311 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
312 return depth;
317 /***********************************************************************
318 * get_config_key
320 * Get a config key from either the app-specific or the default config
322 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
323 char *buffer, DWORD size )
325 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
326 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
327 return ERROR_FILE_NOT_FOUND;
331 /***********************************************************************
332 * setup_options
334 * Setup the x11drv options.
336 static void setup_options(void)
338 char buffer[MAX_PATH+16];
339 HKEY hkey, appkey = 0;
340 DWORD len;
342 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
343 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
345 /* open the app-specific key */
347 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
348 if (len && len < MAX_PATH)
350 HKEY tmpkey;
351 char *p, *appname = buffer;
352 if ((p = strrchr( appname, '/' ))) appname = p + 1;
353 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
354 strcat( appname, "\\X11 Driver" );
355 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
356 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
358 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
359 RegCloseKey( tmpkey );
363 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
364 managed_mode = IS_OPTION_TRUE( buffer[0] );
366 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
367 decorated_mode = IS_OPTION_TRUE( buffer[0] );
369 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
370 dxgrab = IS_OPTION_TRUE( buffer[0] );
372 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
373 usexvidmode = IS_OPTION_TRUE( buffer[0] );
375 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
376 usexrandr = IS_OPTION_TRUE( buffer[0] );
378 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
379 use_take_focus = IS_OPTION_TRUE( buffer[0] );
381 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
382 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
384 screen_depth = 0;
385 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
386 screen_depth = atoi(buffer);
388 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
389 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
391 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
392 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
394 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
395 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
397 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
398 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
400 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
401 use_xim = IS_OPTION_TRUE( buffer[0] );
403 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
404 private_color_map = IS_OPTION_TRUE( buffer[0] );
406 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
407 primary_monitor = atoi( buffer );
409 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
410 copy_default_colors = atoi(buffer);
412 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
413 alloc_system_colors = atoi(buffer);
415 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
417 if (appkey) RegCloseKey( appkey );
418 if (hkey) RegCloseKey( hkey );
421 #ifdef SONAME_LIBXCOMPOSITE
423 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
424 MAKE_FUNCPTR(XCompositeQueryExtension)
425 MAKE_FUNCPTR(XCompositeQueryVersion)
426 MAKE_FUNCPTR(XCompositeVersion)
427 MAKE_FUNCPTR(XCompositeRedirectWindow)
428 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
429 MAKE_FUNCPTR(XCompositeUnredirectWindow)
430 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
431 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
432 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
433 #undef MAKE_FUNCPTR
435 static int xcomp_event_base;
436 static int xcomp_error_base;
438 static void X11DRV_XComposite_Init(void)
440 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
441 if (!xcomposite_handle)
443 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
444 usexcomposite = 0;
445 return;
448 #define LOAD_FUNCPTR(f) \
449 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
450 goto sym_not_found;
451 LOAD_FUNCPTR(XCompositeQueryExtension)
452 LOAD_FUNCPTR(XCompositeQueryVersion)
453 LOAD_FUNCPTR(XCompositeVersion)
454 LOAD_FUNCPTR(XCompositeRedirectWindow)
455 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
456 LOAD_FUNCPTR(XCompositeUnredirectWindow)
457 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
458 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
459 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
460 #undef LOAD_FUNCPTR
462 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
463 &xcomp_error_base)) {
464 TRACE("XComposite extension could not be queried; disabled\n");
465 wine_dlclose(xcomposite_handle, NULL, 0);
466 xcomposite_handle = NULL;
467 usexcomposite = 0;
468 return;
470 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
471 return;
473 sym_not_found:
474 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
475 wine_dlclose(xcomposite_handle, NULL, 0);
476 xcomposite_handle = NULL;
477 usexcomposite = 0;
479 #endif /* defined(SONAME_LIBXCOMPOSITE) */
482 /***********************************************************************
483 * X11DRV process initialisation routine
485 static BOOL process_attach(void)
487 Display *display;
489 setup_options();
491 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
493 /* Open display */
495 if (!(display = XOpenDisplay( NULL ))) return FALSE;
497 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
498 screen = DefaultScreenOfDisplay( display );
499 visual = DefaultVisual( display, DefaultScreen(display) );
500 root_window = DefaultRootWindow( display );
501 gdi_display = display;
502 old_error_handler = XSetErrorHandler( error_handler );
504 /* Initialize screen depth */
506 if (screen_depth) /* depth specified */
508 int depth_count, i;
509 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
510 for (i = 0; i < depth_count; i++)
511 if (depth_list[i] == screen_depth) break;
512 XFree( depth_list );
513 if (i >= depth_count)
515 WARN( "invalid depth %d, using default\n", screen_depth );
516 screen_depth = 0;
519 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
520 screen_bpp = depth_to_bpp( screen_depth );
522 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
524 if (TRACE_ON(synchronous)) XSynchronize( display, True );
526 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
527 X11DRV_Settings_Init();
529 #ifdef SONAME_LIBXXF86VM
530 /* initialize XVidMode */
531 X11DRV_XF86VM_Init();
532 #endif
533 #ifdef SONAME_LIBXRANDR
534 /* initialize XRandR */
535 X11DRV_XRandR_Init();
536 #endif
537 #ifdef SONAME_LIBXCOMPOSITE
538 X11DRV_XComposite_Init();
539 #endif
541 #ifdef HAVE_XKB
542 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
543 #endif
544 X11DRV_InitKeyboard( gdi_display );
545 X11DRV_InitClipboard();
546 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
548 return TRUE;
552 /***********************************************************************
553 * X11DRV thread termination routine
555 static void thread_detach(void)
557 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
559 if (data)
561 X11DRV_ResetSelectionOwner();
562 wine_tsx11_lock();
563 if (data->xim) XCloseIM( data->xim );
564 XCloseDisplay( data->display );
565 wine_tsx11_unlock();
566 HeapFree( GetProcessHeap(), 0, data );
571 /***********************************************************************
572 * X11DRV process termination routine
574 static void process_detach(void)
576 #ifdef SONAME_LIBXXF86VM
577 /* cleanup XVidMode */
578 X11DRV_XF86VM_Cleanup();
579 #endif
580 if(using_client_side_fonts)
581 X11DRV_XRender_Finalize();
583 /* cleanup GDI */
584 X11DRV_GDI_Finalize();
586 IME_UnregisterClasses();
587 DeleteCriticalSection( &X11DRV_CritSection );
588 TlsFree( thread_data_tls_index );
592 /* store the display fd into the message queue */
593 static void set_queue_display_fd( Display *display )
595 HANDLE handle;
596 int ret;
598 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
600 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
601 ExitProcess(1);
603 SERVER_START_REQ( set_queue_fd )
605 req->handle = handle;
606 ret = wine_server_call( req );
608 SERVER_END_REQ;
609 if (ret)
611 MESSAGE( "x11drv: Can't store handle for display fd\n" );
612 ExitProcess(1);
614 CloseHandle( handle );
618 /***********************************************************************
619 * X11DRV thread initialisation routine
621 struct x11drv_thread_data *x11drv_init_thread_data(void)
623 struct x11drv_thread_data *data = x11drv_thread_data();
625 if (data) return data;
627 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
629 ERR( "could not create data\n" );
630 ExitProcess(1);
632 wine_tsx11_lock();
633 if (!(data->display = XOpenDisplay(NULL)))
635 wine_tsx11_unlock();
636 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
637 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
638 ExitProcess(1);
641 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
643 #ifdef HAVE_XKB
644 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
645 XkbSetDetectableAutoRepeat( data->display, True, NULL );
646 #endif
648 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
649 wine_tsx11_unlock();
651 set_queue_display_fd( data->display );
652 TlsSetValue( thread_data_tls_index, data );
654 if (use_xim) X11DRV_SetupXIM();
655 X11DRV_SetCursor( NULL );
657 return data;
661 /***********************************************************************
662 * X11DRV initialisation routine
664 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
666 BOOL ret = TRUE;
668 switch(reason)
670 case DLL_PROCESS_ATTACH:
671 x11drv_module = hinst;
672 ret = process_attach();
673 break;
674 case DLL_THREAD_DETACH:
675 thread_detach();
676 break;
677 case DLL_PROCESS_DETACH:
678 process_detach();
679 break;
681 return ret;
684 /***********************************************************************
685 * GetScreenSaveActive (X11DRV.@)
687 * Returns the active status of the screen saver
689 BOOL X11DRV_GetScreenSaveActive(void)
691 int timeout, temp;
692 wine_tsx11_lock();
693 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
694 wine_tsx11_unlock();
695 return timeout != 0;
698 /***********************************************************************
699 * SetScreenSaveActive (X11DRV.@)
701 * Activate/Deactivate the screen saver
703 void X11DRV_SetScreenSaveActive(BOOL bActivate)
705 int timeout, interval, prefer_blanking, allow_exposures;
706 static int last_timeout = 15 * 60;
708 wine_tsx11_lock();
709 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
710 &allow_exposures);
711 if (timeout) last_timeout = timeout;
713 timeout = bActivate ? last_timeout : 0;
714 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
715 allow_exposures);
716 wine_tsx11_unlock();