push 014043c4937c940c54cd1214c96e33a3b3c8cf7d
[wine/hacks.git] / dlls / winex11.drv / x11drv_main.c
blob8982716271c32f20e3294b948e1cff77bbe74e94
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_STATE",
127 "WM_TAKE_FOCUS",
128 "KWM_DOCKWINDOW",
129 "DndProtocol",
130 "DndSelection",
131 "_MOTIF_WM_HINTS",
132 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
133 "_NET_SYSTEM_TRAY_OPCODE",
134 "_NET_SYSTEM_TRAY_S0",
135 "_NET_WM_MOVERESIZE",
136 "_NET_WM_NAME",
137 "_NET_WM_PID",
138 "_NET_WM_PING",
139 "_NET_WM_STATE",
140 "_NET_WM_STATE_ABOVE",
141 "_NET_WM_STATE_FULLSCREEN",
142 "_NET_WM_STATE_SKIP_PAGER",
143 "_NET_WM_STATE_SKIP_TASKBAR",
144 "_NET_WM_WINDOW_TYPE",
145 "_NET_WM_WINDOW_TYPE_DIALOG",
146 "_NET_WM_WINDOW_TYPE_NORMAL",
147 "_NET_WM_WINDOW_TYPE_UTILITY",
148 "_XEMBED_INFO",
149 "XdndAware",
150 "XdndEnter",
151 "XdndPosition",
152 "XdndStatus",
153 "XdndLeave",
154 "XdndFinished",
155 "XdndDrop",
156 "XdndActionCopy",
157 "XdndActionMove",
158 "XdndActionLink",
159 "XdndActionAsk",
160 "XdndActionPrivate",
161 "XdndSelection",
162 "XdndTarget",
163 "XdndTypeList",
164 "WCF_DIB",
165 "image/gif",
166 "text/html",
167 "text/plain",
168 "text/rtf",
169 "text/richtext",
170 "text/uri-list"
173 /***********************************************************************
174 * ignore_error
176 * Check if the X error is one we can ignore.
178 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
180 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
182 /* ignore a number of errors on gdi display caused by creating/destroying windows */
183 if (display == gdi_display)
185 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
186 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
187 if (xrender_error_base) /* check for XRender errors */
189 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
191 #endif
193 return FALSE;
197 /***********************************************************************
198 * X11DRV_expect_error
200 * Setup a callback function that will be called on an X error. The
201 * callback must return non-zero if the error is the one it expected.
202 * This function acquires the x11 lock; X11DRV_check_error must be
203 * called in all cases to release it.
205 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
207 wine_tsx11_lock();
208 err_callback = callback;
209 err_callback_display = display;
210 err_callback_arg = arg;
211 err_callback_result = 0;
212 err_serial = NextRequest(display);
216 /***********************************************************************
217 * X11DRV_check_error
219 * Check if an expected X11 error occurred; return non-zero if yes.
220 * Also release the x11 lock obtained in X11DRV_expect_error.
221 * The caller is responsible for calling XSync first if necessary.
223 int X11DRV_check_error(void)
225 int ret;
226 err_callback = NULL;
227 ret = err_callback_result;
228 wine_tsx11_unlock();
229 return ret;
233 /***********************************************************************
234 * error_handler
236 static int error_handler( Display *display, XErrorEvent *error_evt )
238 if (err_callback && display == err_callback_display &&
239 (long)(error_evt->serial - err_serial) >= 0)
241 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
243 TRACE( "got expected error %d req %d\n",
244 error_evt->error_code, error_evt->request_code );
245 return 0;
248 if (ignore_error( display, error_evt ))
250 TRACE( "got ignored error %d req %d\n",
251 error_evt->error_code, error_evt->request_code );
252 return 0;
254 if (TRACE_ON(synchronous))
256 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
257 error_evt->serial, error_evt->request_code );
258 DebugBreak(); /* force an entry in the debugger */
260 old_error_handler( display, error_evt );
261 return 0;
264 /***********************************************************************
265 * wine_tsx11_lock (X11DRV.@)
267 void wine_tsx11_lock(void)
269 EnterCriticalSection( &X11DRV_CritSection );
272 /***********************************************************************
273 * wine_tsx11_unlock (X11DRV.@)
275 void wine_tsx11_unlock(void)
277 LeaveCriticalSection( &X11DRV_CritSection );
281 /***********************************************************************
282 * depth_to_bpp
284 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
286 unsigned int depth_to_bpp( unsigned int depth )
288 switch (depth)
290 case 1:
291 case 8:
292 return depth;
293 case 15:
294 case 16:
295 return 16;
296 case 24:
297 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
298 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
299 * for windowing, but gl applications can get visuals with alpha channels. So we
300 * should check the framebuffer and/or opengl formats available to find out what the
301 * framebuffer actually does
303 case 32:
304 return 32;
305 default:
306 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
307 return depth;
312 /***********************************************************************
313 * get_config_key
315 * Get a config key from either the app-specific or the default config
317 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
318 char *buffer, DWORD size )
320 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
321 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
322 return ERROR_FILE_NOT_FOUND;
326 /***********************************************************************
327 * setup_options
329 * Setup the x11drv options.
331 static void setup_options(void)
333 char buffer[MAX_PATH+16];
334 HKEY hkey, appkey = 0;
335 DWORD len;
337 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
338 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
340 /* open the app-specific key */
342 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
343 if (len && len < MAX_PATH)
345 HKEY tmpkey;
346 char *p, *appname = buffer;
347 if ((p = strrchr( appname, '/' ))) appname = p + 1;
348 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
349 strcat( appname, "\\X11 Driver" );
350 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
351 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
353 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
354 RegCloseKey( tmpkey );
358 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
359 managed_mode = IS_OPTION_TRUE( buffer[0] );
361 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
362 dxgrab = IS_OPTION_TRUE( buffer[0] );
364 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
365 usexvidmode = IS_OPTION_TRUE( buffer[0] );
367 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
368 usexrandr = IS_OPTION_TRUE( buffer[0] );
370 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
371 use_take_focus = IS_OPTION_TRUE( buffer[0] );
373 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
374 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
376 screen_depth = 0;
377 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
378 screen_depth = atoi(buffer);
380 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
381 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
383 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
384 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
386 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
387 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
389 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
390 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
392 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
393 use_xim = IS_OPTION_TRUE( buffer[0] );
395 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
396 private_color_map = IS_OPTION_TRUE( buffer[0] );
398 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
399 primary_monitor = atoi( buffer );
401 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
402 copy_default_colors = atoi(buffer);
404 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
405 alloc_system_colors = atoi(buffer);
407 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
409 if (appkey) RegCloseKey( appkey );
410 if (hkey) RegCloseKey( hkey );
413 #ifdef SONAME_LIBXCOMPOSITE
415 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
416 MAKE_FUNCPTR(XCompositeQueryExtension)
417 MAKE_FUNCPTR(XCompositeQueryVersion)
418 MAKE_FUNCPTR(XCompositeVersion)
419 MAKE_FUNCPTR(XCompositeRedirectWindow)
420 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
421 MAKE_FUNCPTR(XCompositeUnredirectWindow)
422 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
423 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
424 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
425 #undef MAKE_FUNCPTR
427 static int xcomp_event_base;
428 static int xcomp_error_base;
430 static void X11DRV_XComposite_Init(void)
432 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
433 if (!xcomposite_handle)
435 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
436 usexcomposite = 0;
437 return;
440 #define LOAD_FUNCPTR(f) \
441 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
442 goto sym_not_found;
443 LOAD_FUNCPTR(XCompositeQueryExtension)
444 LOAD_FUNCPTR(XCompositeQueryVersion)
445 LOAD_FUNCPTR(XCompositeVersion)
446 LOAD_FUNCPTR(XCompositeRedirectWindow)
447 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
448 LOAD_FUNCPTR(XCompositeUnredirectWindow)
449 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
450 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
451 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
452 #undef LOAD_FUNCPTR
454 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
455 &xcomp_error_base)) {
456 TRACE("XComposite extension could not be queried; disabled\n");
457 wine_dlclose(xcomposite_handle, NULL, 0);
458 xcomposite_handle = NULL;
459 usexcomposite = 0;
460 return;
462 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
463 return;
465 sym_not_found:
466 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
467 wine_dlclose(xcomposite_handle, NULL, 0);
468 xcomposite_handle = NULL;
469 usexcomposite = 0;
471 #endif /* defined(SONAME_LIBXCOMPOSITE) */
474 /***********************************************************************
475 * X11DRV process initialisation routine
477 static BOOL process_attach(void)
479 Display *display;
480 const char *env;
482 setup_options();
484 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
486 /* Open display */
488 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
489 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
491 if (!(display = XOpenDisplay( NULL ))) return FALSE;
493 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
494 screen = DefaultScreenOfDisplay( display );
495 visual = DefaultVisual( display, DefaultScreen(display) );
496 root_window = DefaultRootWindow( display );
497 gdi_display = display;
498 old_error_handler = XSetErrorHandler( error_handler );
500 /* Initialize screen depth */
502 if (screen_depth) /* depth specified */
504 int depth_count, i;
505 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
506 for (i = 0; i < depth_count; i++)
507 if (depth_list[i] == screen_depth) break;
508 XFree( depth_list );
509 if (i >= depth_count)
511 WARN( "invalid depth %d, using default\n", screen_depth );
512 screen_depth = 0;
515 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
516 screen_bpp = depth_to_bpp( screen_depth );
518 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
520 if (TRACE_ON(synchronous)) XSynchronize( display, True );
522 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
523 X11DRV_Settings_Init();
525 #ifdef HAVE_LIBXXF86VM
526 /* initialize XVidMode */
527 X11DRV_XF86VM_Init();
528 #endif
529 #ifdef SONAME_LIBXRANDR
530 /* initialize XRandR */
531 X11DRV_XRandR_Init();
532 #endif
533 #ifdef SONAME_LIBXCOMPOSITE
534 X11DRV_XComposite_Init();
535 #endif
537 X11DRV_InitKeyboard( gdi_display );
538 X11DRV_InitClipboard();
540 return TRUE;
544 /***********************************************************************
545 * X11DRV thread termination routine
547 static void thread_detach(void)
549 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
551 if (data)
553 X11DRV_ResetSelectionOwner();
554 wine_tsx11_lock();
555 if (data->xim) XCloseIM( data->xim );
556 XCloseDisplay( data->display );
557 wine_tsx11_unlock();
558 HeapFree( GetProcessHeap(), 0, data );
563 /***********************************************************************
564 * X11DRV process termination routine
566 static void process_detach(void)
568 #ifdef HAVE_LIBXXF86VM
569 /* cleanup XVidMode */
570 X11DRV_XF86VM_Cleanup();
571 #endif
572 if(using_client_side_fonts)
573 X11DRV_XRender_Finalize();
575 /* cleanup GDI */
576 X11DRV_GDI_Finalize();
578 DeleteCriticalSection( &X11DRV_CritSection );
579 TlsFree( thread_data_tls_index );
583 /* store the display fd into the message queue */
584 static void set_queue_display_fd( Display *display )
586 HANDLE handle;
587 int ret;
589 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
591 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
592 ExitProcess(1);
594 SERVER_START_REQ( set_queue_fd )
596 req->handle = handle;
597 ret = wine_server_call( req );
599 SERVER_END_REQ;
600 if (ret)
602 MESSAGE( "x11drv: Can't store handle for display fd\n" );
603 ExitProcess(1);
605 CloseHandle( handle );
609 /***********************************************************************
610 * X11DRV thread initialisation routine
612 struct x11drv_thread_data *x11drv_init_thread_data(void)
614 struct x11drv_thread_data *data;
616 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
618 ERR( "could not create data\n" );
619 ExitProcess(1);
621 wine_tsx11_lock();
622 if (!(data->display = XOpenDisplay(NULL)))
624 wine_tsx11_unlock();
625 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
626 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
627 ExitProcess(1);
630 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
632 #ifdef HAVE_XKB
633 if (use_xkb)
635 use_xkb = XkbUseExtension( data->display, NULL, NULL );
636 if (use_xkb)
638 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
639 /* This works around an Xlib bug where it tries to get the display lock */
640 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
641 XkbKeysymToModifiers( data->display, 'A' );
642 XkbSetDetectableAutoRepeat( data->display, True, NULL );
645 #endif
647 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
648 wine_tsx11_unlock();
650 if (!use_xim)
651 data->xim = NULL;
652 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
653 WARN("Input Method is not available\n");
655 set_queue_display_fd( data->display );
656 data->process_event_count = 0;
657 data->cursor = None;
658 data->cursor_window = None;
659 data->grab_window = None;
660 data->last_focus = 0;
661 data->selection_wnd = 0;
662 TlsSetValue( thread_data_tls_index, data );
663 X11DRV_SetCursor( NULL );
664 return data;
668 /***********************************************************************
669 * X11DRV initialisation routine
671 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
673 BOOL ret = TRUE;
675 switch(reason)
677 case DLL_PROCESS_ATTACH:
678 ret = process_attach();
679 break;
680 case DLL_THREAD_DETACH:
681 thread_detach();
682 break;
683 case DLL_PROCESS_DETACH:
684 process_detach();
685 break;
687 return ret;
690 /***********************************************************************
691 * GetScreenSaveActive (X11DRV.@)
693 * Returns the active status of the screen saver
695 BOOL X11DRV_GetScreenSaveActive(void)
697 int timeout, temp;
698 wine_tsx11_lock();
699 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
700 wine_tsx11_unlock();
701 return timeout != 0;
704 /***********************************************************************
705 * SetScreenSaveActive (X11DRV.@)
707 * Activate/Deactivate the screen saver
709 void X11DRV_SetScreenSaveActive(BOOL bActivate)
711 int timeout, interval, prefer_blanking, allow_exposures;
712 static int last_timeout = 15 * 60;
714 wine_tsx11_lock();
715 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
716 &allow_exposures);
717 if (timeout) last_timeout = timeout;
719 timeout = bActivate ? last_timeout : 0;
720 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
721 allow_exposures);
722 wine_tsx11_unlock();