configure: Explicitly mention that we need 32-bit libraries to try to avoid some...
[wine/multimedia.git] / dlls / winex11.drv / x11drv_main.c
blob15694816876d8e66137454283facc363bb2ba994
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 "_NET_WORKAREA",
154 "_XEMBED_INFO",
155 "XdndAware",
156 "XdndEnter",
157 "XdndPosition",
158 "XdndStatus",
159 "XdndLeave",
160 "XdndFinished",
161 "XdndDrop",
162 "XdndActionCopy",
163 "XdndActionMove",
164 "XdndActionLink",
165 "XdndActionAsk",
166 "XdndActionPrivate",
167 "XdndSelection",
168 "XdndTarget",
169 "XdndTypeList",
170 "WCF_DIB",
171 "image/gif",
172 "text/html",
173 "text/plain",
174 "text/rtf",
175 "text/richtext",
176 "text/uri-list"
179 /***********************************************************************
180 * ignore_error
182 * Check if the X error is one we can ignore.
184 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
186 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
188 /* ignore a number of errors on gdi display caused by creating/destroying windows */
189 if (display == gdi_display)
191 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
192 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
193 if (xrender_error_base) /* check for XRender errors */
195 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
197 #endif
199 return FALSE;
203 /***********************************************************************
204 * X11DRV_expect_error
206 * Setup a callback function that will be called on an X error. The
207 * callback must return non-zero if the error is the one it expected.
208 * This function acquires the x11 lock; X11DRV_check_error must be
209 * called in all cases to release it.
211 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
213 wine_tsx11_lock();
214 err_callback = callback;
215 err_callback_display = display;
216 err_callback_arg = arg;
217 err_callback_result = 0;
218 err_serial = NextRequest(display);
222 /***********************************************************************
223 * X11DRV_check_error
225 * Check if an expected X11 error occurred; return non-zero if yes.
226 * Also release the x11 lock obtained in X11DRV_expect_error.
227 * The caller is responsible for calling XSync first if necessary.
229 int X11DRV_check_error(void)
231 int ret;
232 err_callback = NULL;
233 ret = err_callback_result;
234 wine_tsx11_unlock();
235 return ret;
239 /***********************************************************************
240 * error_handler
242 static int error_handler( Display *display, XErrorEvent *error_evt )
244 if (err_callback && display == err_callback_display &&
245 (long)(error_evt->serial - err_serial) >= 0)
247 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
249 TRACE( "got expected error %d req %d\n",
250 error_evt->error_code, error_evt->request_code );
251 return 0;
254 if (ignore_error( display, error_evt ))
256 TRACE( "got ignored error %d req %d\n",
257 error_evt->error_code, error_evt->request_code );
258 return 0;
260 if (TRACE_ON(synchronous))
262 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
263 error_evt->serial, error_evt->request_code );
264 DebugBreak(); /* force an entry in the debugger */
266 old_error_handler( display, error_evt );
267 return 0;
270 /***********************************************************************
271 * wine_tsx11_lock (X11DRV.@)
273 void wine_tsx11_lock(void)
275 EnterCriticalSection( &X11DRV_CritSection );
278 /***********************************************************************
279 * wine_tsx11_unlock (X11DRV.@)
281 void wine_tsx11_unlock(void)
283 LeaveCriticalSection( &X11DRV_CritSection );
287 /***********************************************************************
288 * depth_to_bpp
290 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
292 unsigned int depth_to_bpp( unsigned int depth )
294 switch (depth)
296 case 1:
297 case 8:
298 return depth;
299 case 15:
300 case 16:
301 return 16;
302 case 24:
303 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
304 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
305 * for windowing, but gl applications can get visuals with alpha channels. So we
306 * should check the framebuffer and/or opengl formats available to find out what the
307 * framebuffer actually does
309 case 32:
310 return 32;
311 default:
312 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
313 return depth;
318 /***********************************************************************
319 * get_config_key
321 * Get a config key from either the app-specific or the default config
323 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
324 char *buffer, DWORD size )
326 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
327 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
328 return ERROR_FILE_NOT_FOUND;
332 /***********************************************************************
333 * setup_options
335 * Setup the x11drv options.
337 static void setup_options(void)
339 char buffer[MAX_PATH+16];
340 HKEY hkey, appkey = 0;
341 DWORD len;
343 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
344 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
346 /* open the app-specific key */
348 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
349 if (len && len < MAX_PATH)
351 HKEY tmpkey;
352 char *p, *appname = buffer;
353 if ((p = strrchr( appname, '/' ))) appname = p + 1;
354 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
355 strcat( appname, "\\X11 Driver" );
356 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
357 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
359 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
360 RegCloseKey( tmpkey );
364 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
365 managed_mode = IS_OPTION_TRUE( buffer[0] );
367 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
368 decorated_mode = IS_OPTION_TRUE( buffer[0] );
370 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
371 dxgrab = IS_OPTION_TRUE( buffer[0] );
373 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
374 usexvidmode = IS_OPTION_TRUE( buffer[0] );
376 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
377 usexrandr = IS_OPTION_TRUE( buffer[0] );
379 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
380 use_take_focus = IS_OPTION_TRUE( buffer[0] );
382 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
383 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
385 screen_depth = 0;
386 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
387 screen_depth = atoi(buffer);
389 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
390 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
392 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
393 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
395 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
396 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
398 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
399 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
401 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
402 use_xim = IS_OPTION_TRUE( buffer[0] );
404 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
405 private_color_map = IS_OPTION_TRUE( buffer[0] );
407 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
408 primary_monitor = atoi( buffer );
410 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
411 copy_default_colors = atoi(buffer);
413 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
414 alloc_system_colors = atoi(buffer);
416 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
418 if (appkey) RegCloseKey( appkey );
419 if (hkey) RegCloseKey( hkey );
422 #ifdef SONAME_LIBXCOMPOSITE
424 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
425 MAKE_FUNCPTR(XCompositeQueryExtension)
426 MAKE_FUNCPTR(XCompositeQueryVersion)
427 MAKE_FUNCPTR(XCompositeVersion)
428 MAKE_FUNCPTR(XCompositeRedirectWindow)
429 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
430 MAKE_FUNCPTR(XCompositeUnredirectWindow)
431 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
432 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
433 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
434 #undef MAKE_FUNCPTR
436 static int xcomp_event_base;
437 static int xcomp_error_base;
439 static void X11DRV_XComposite_Init(void)
441 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
442 if (!xcomposite_handle)
444 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
445 usexcomposite = 0;
446 return;
449 #define LOAD_FUNCPTR(f) \
450 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
451 goto sym_not_found;
452 LOAD_FUNCPTR(XCompositeQueryExtension)
453 LOAD_FUNCPTR(XCompositeQueryVersion)
454 LOAD_FUNCPTR(XCompositeVersion)
455 LOAD_FUNCPTR(XCompositeRedirectWindow)
456 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
457 LOAD_FUNCPTR(XCompositeUnredirectWindow)
458 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
459 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
460 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
461 #undef LOAD_FUNCPTR
463 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
464 &xcomp_error_base)) {
465 TRACE("XComposite extension could not be queried; disabled\n");
466 wine_dlclose(xcomposite_handle, NULL, 0);
467 xcomposite_handle = NULL;
468 usexcomposite = 0;
469 return;
471 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
472 return;
474 sym_not_found:
475 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
476 wine_dlclose(xcomposite_handle, NULL, 0);
477 xcomposite_handle = NULL;
478 usexcomposite = 0;
480 #endif /* defined(SONAME_LIBXCOMPOSITE) */
483 /***********************************************************************
484 * X11DRV process initialisation routine
486 static BOOL process_attach(void)
488 Display *display;
490 setup_options();
492 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
494 /* Open display */
496 if (!(display = XOpenDisplay( NULL ))) return FALSE;
498 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
499 screen = DefaultScreenOfDisplay( display );
500 visual = DefaultVisual( display, DefaultScreen(display) );
501 root_window = DefaultRootWindow( display );
502 gdi_display = display;
503 old_error_handler = XSetErrorHandler( error_handler );
505 /* Initialize screen depth */
507 if (screen_depth) /* depth specified */
509 int depth_count, i;
510 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
511 for (i = 0; i < depth_count; i++)
512 if (depth_list[i] == screen_depth) break;
513 XFree( depth_list );
514 if (i >= depth_count)
516 WARN( "invalid depth %d, using default\n", screen_depth );
517 screen_depth = 0;
520 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
521 screen_bpp = depth_to_bpp( screen_depth );
523 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
525 if (TRACE_ON(synchronous)) XSynchronize( display, True );
527 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
528 X11DRV_Settings_Init();
530 #ifdef SONAME_LIBXXF86VM
531 /* initialize XVidMode */
532 X11DRV_XF86VM_Init();
533 #endif
534 #ifdef SONAME_LIBXRANDR
535 /* initialize XRandR */
536 X11DRV_XRandR_Init();
537 #endif
538 #ifdef SONAME_LIBXCOMPOSITE
539 X11DRV_XComposite_Init();
540 #endif
542 #ifdef HAVE_XKB
543 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
544 #endif
545 X11DRV_InitKeyboard( gdi_display );
546 X11DRV_InitClipboard();
547 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
549 return TRUE;
553 /***********************************************************************
554 * X11DRV thread termination routine
556 static void thread_detach(void)
558 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
560 if (data)
562 X11DRV_ResetSelectionOwner();
563 wine_tsx11_lock();
564 if (data->xim) XCloseIM( data->xim );
565 if (data->font_set) XFreeFontSet( data->display, data->font_set );
566 XCloseDisplay( data->display );
567 wine_tsx11_unlock();
568 HeapFree( GetProcessHeap(), 0, data );
573 /***********************************************************************
574 * X11DRV process termination routine
576 static void process_detach(void)
578 #ifdef SONAME_LIBXXF86VM
579 /* cleanup XVidMode */
580 X11DRV_XF86VM_Cleanup();
581 #endif
582 if(using_client_side_fonts)
583 X11DRV_XRender_Finalize();
585 /* cleanup GDI */
586 X11DRV_GDI_Finalize();
588 IME_UnregisterClasses();
589 DeleteCriticalSection( &X11DRV_CritSection );
590 TlsFree( thread_data_tls_index );
594 /* store the display fd into the message queue */
595 static void set_queue_display_fd( Display *display )
597 HANDLE handle;
598 int ret;
600 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
602 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
603 ExitProcess(1);
605 SERVER_START_REQ( set_queue_fd )
607 req->handle = handle;
608 ret = wine_server_call( req );
610 SERVER_END_REQ;
611 if (ret)
613 MESSAGE( "x11drv: Can't store handle for display fd\n" );
614 ExitProcess(1);
616 CloseHandle( handle );
620 /***********************************************************************
621 * X11DRV thread initialisation routine
623 struct x11drv_thread_data *x11drv_init_thread_data(void)
625 struct x11drv_thread_data *data = x11drv_thread_data();
627 if (data) return data;
629 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
631 ERR( "could not create data\n" );
632 ExitProcess(1);
634 wine_tsx11_lock();
635 if (!(data->display = XOpenDisplay(NULL)))
637 wine_tsx11_unlock();
638 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
639 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
640 ExitProcess(1);
643 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
645 #ifdef HAVE_XKB
646 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
647 XkbSetDetectableAutoRepeat( data->display, True, NULL );
648 #endif
650 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
651 wine_tsx11_unlock();
653 set_queue_display_fd( data->display );
654 TlsSetValue( thread_data_tls_index, data );
656 if (use_xim) X11DRV_SetupXIM();
657 X11DRV_SetCursor( NULL );
659 return data;
663 /***********************************************************************
664 * X11DRV initialisation routine
666 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
668 BOOL ret = TRUE;
670 switch(reason)
672 case DLL_PROCESS_ATTACH:
673 x11drv_module = hinst;
674 ret = process_attach();
675 break;
676 case DLL_THREAD_DETACH:
677 thread_detach();
678 break;
679 case DLL_PROCESS_DETACH:
680 process_detach();
681 break;
683 return ret;
686 /***********************************************************************
687 * GetScreenSaveActive (X11DRV.@)
689 * Returns the active status of the screen saver
691 BOOL X11DRV_GetScreenSaveActive(void)
693 int timeout, temp;
694 wine_tsx11_lock();
695 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
696 wine_tsx11_unlock();
697 return timeout != 0;
700 /***********************************************************************
701 * SetScreenSaveActive (X11DRV.@)
703 * Activate/Deactivate the screen saver
705 void X11DRV_SetScreenSaveActive(BOOL bActivate)
707 int timeout, interval, prefer_blanking, allow_exposures;
708 static int last_timeout = 15 * 60;
710 wine_tsx11_lock();
711 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
712 &allow_exposures);
713 if (timeout) last_timeout = timeout;
715 timeout = bActivate ? last_timeout : 0;
716 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
717 allow_exposures);
718 wine_tsx11_unlock();