Release 0.9.61.
[wine/gsoc-2012-control.git] / dlls / winex11.drv / x11drv_main.c
blob3287fea3eadf8bb918f82a961e57590ef82dffa0
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_TYPE",
149 "_NET_WM_WINDOW_TYPE_DIALOG",
150 "_NET_WM_WINDOW_TYPE_NORMAL",
151 "_NET_WM_WINDOW_TYPE_UTILITY",
152 "_XEMBED_INFO",
153 "XdndAware",
154 "XdndEnter",
155 "XdndPosition",
156 "XdndStatus",
157 "XdndLeave",
158 "XdndFinished",
159 "XdndDrop",
160 "XdndActionCopy",
161 "XdndActionMove",
162 "XdndActionLink",
163 "XdndActionAsk",
164 "XdndActionPrivate",
165 "XdndSelection",
166 "XdndTarget",
167 "XdndTypeList",
168 "WCF_DIB",
169 "image/gif",
170 "text/html",
171 "text/plain",
172 "text/rtf",
173 "text/richtext",
174 "text/uri-list"
177 /***********************************************************************
178 * ignore_error
180 * Check if the X error is one we can ignore.
182 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
184 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
186 /* ignore a number of errors on gdi display caused by creating/destroying windows */
187 if (display == gdi_display)
189 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
190 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
191 if (xrender_error_base) /* check for XRender errors */
193 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
195 #endif
197 return FALSE;
201 /***********************************************************************
202 * X11DRV_expect_error
204 * Setup a callback function that will be called on an X error. The
205 * callback must return non-zero if the error is the one it expected.
206 * This function acquires the x11 lock; X11DRV_check_error must be
207 * called in all cases to release it.
209 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
211 wine_tsx11_lock();
212 err_callback = callback;
213 err_callback_display = display;
214 err_callback_arg = arg;
215 err_callback_result = 0;
216 err_serial = NextRequest(display);
220 /***********************************************************************
221 * X11DRV_check_error
223 * Check if an expected X11 error occurred; return non-zero if yes.
224 * Also release the x11 lock obtained in X11DRV_expect_error.
225 * The caller is responsible for calling XSync first if necessary.
227 int X11DRV_check_error(void)
229 int ret;
230 err_callback = NULL;
231 ret = err_callback_result;
232 wine_tsx11_unlock();
233 return ret;
237 /***********************************************************************
238 * error_handler
240 static int error_handler( Display *display, XErrorEvent *error_evt )
242 if (err_callback && display == err_callback_display &&
243 (long)(error_evt->serial - err_serial) >= 0)
245 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
247 TRACE( "got expected error %d req %d\n",
248 error_evt->error_code, error_evt->request_code );
249 return 0;
252 if (ignore_error( display, error_evt ))
254 TRACE( "got ignored error %d req %d\n",
255 error_evt->error_code, error_evt->request_code );
256 return 0;
258 if (TRACE_ON(synchronous))
260 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
261 error_evt->serial, error_evt->request_code );
262 DebugBreak(); /* force an entry in the debugger */
264 old_error_handler( display, error_evt );
265 return 0;
268 /***********************************************************************
269 * wine_tsx11_lock (X11DRV.@)
271 void wine_tsx11_lock(void)
273 EnterCriticalSection( &X11DRV_CritSection );
276 /***********************************************************************
277 * wine_tsx11_unlock (X11DRV.@)
279 void wine_tsx11_unlock(void)
281 LeaveCriticalSection( &X11DRV_CritSection );
285 /***********************************************************************
286 * depth_to_bpp
288 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
290 unsigned int depth_to_bpp( unsigned int depth )
292 switch (depth)
294 case 1:
295 case 8:
296 return depth;
297 case 15:
298 case 16:
299 return 16;
300 case 24:
301 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
302 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
303 * for windowing, but gl applications can get visuals with alpha channels. So we
304 * should check the framebuffer and/or opengl formats available to find out what the
305 * framebuffer actually does
307 case 32:
308 return 32;
309 default:
310 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
311 return depth;
316 /***********************************************************************
317 * get_config_key
319 * Get a config key from either the app-specific or the default config
321 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
322 char *buffer, DWORD size )
324 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
325 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
326 return ERROR_FILE_NOT_FOUND;
330 /***********************************************************************
331 * setup_options
333 * Setup the x11drv options.
335 static void setup_options(void)
337 char buffer[MAX_PATH+16];
338 HKEY hkey, appkey = 0;
339 DWORD len;
341 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
342 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
344 /* open the app-specific key */
346 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
347 if (len && len < MAX_PATH)
349 HKEY tmpkey;
350 char *p, *appname = buffer;
351 if ((p = strrchr( appname, '/' ))) appname = p + 1;
352 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
353 strcat( appname, "\\X11 Driver" );
354 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
355 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
357 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
358 RegCloseKey( tmpkey );
362 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
363 managed_mode = IS_OPTION_TRUE( buffer[0] );
365 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
366 decorated_mode = IS_OPTION_TRUE( buffer[0] );
368 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
369 dxgrab = IS_OPTION_TRUE( buffer[0] );
371 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
372 usexvidmode = IS_OPTION_TRUE( buffer[0] );
374 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
375 usexrandr = IS_OPTION_TRUE( buffer[0] );
377 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
378 use_take_focus = IS_OPTION_TRUE( buffer[0] );
380 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
381 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
383 screen_depth = 0;
384 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
385 screen_depth = atoi(buffer);
387 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
388 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
390 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
391 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
393 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
394 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
396 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
397 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
399 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
400 use_xim = IS_OPTION_TRUE( buffer[0] );
402 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
403 private_color_map = IS_OPTION_TRUE( buffer[0] );
405 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
406 primary_monitor = atoi( buffer );
408 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
409 copy_default_colors = atoi(buffer);
411 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
412 alloc_system_colors = atoi(buffer);
414 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
416 if (appkey) RegCloseKey( appkey );
417 if (hkey) RegCloseKey( hkey );
420 #ifdef SONAME_LIBXCOMPOSITE
422 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
423 MAKE_FUNCPTR(XCompositeQueryExtension)
424 MAKE_FUNCPTR(XCompositeQueryVersion)
425 MAKE_FUNCPTR(XCompositeVersion)
426 MAKE_FUNCPTR(XCompositeRedirectWindow)
427 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
428 MAKE_FUNCPTR(XCompositeUnredirectWindow)
429 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
430 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
431 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
432 #undef MAKE_FUNCPTR
434 static int xcomp_event_base;
435 static int xcomp_error_base;
437 static void X11DRV_XComposite_Init(void)
439 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
440 if (!xcomposite_handle)
442 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
443 usexcomposite = 0;
444 return;
447 #define LOAD_FUNCPTR(f) \
448 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
449 goto sym_not_found;
450 LOAD_FUNCPTR(XCompositeQueryExtension)
451 LOAD_FUNCPTR(XCompositeQueryVersion)
452 LOAD_FUNCPTR(XCompositeVersion)
453 LOAD_FUNCPTR(XCompositeRedirectWindow)
454 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
455 LOAD_FUNCPTR(XCompositeUnredirectWindow)
456 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
457 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
458 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
459 #undef LOAD_FUNCPTR
461 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
462 &xcomp_error_base)) {
463 TRACE("XComposite extension could not be queried; disabled\n");
464 wine_dlclose(xcomposite_handle, NULL, 0);
465 xcomposite_handle = NULL;
466 usexcomposite = 0;
467 return;
469 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
470 return;
472 sym_not_found:
473 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
474 wine_dlclose(xcomposite_handle, NULL, 0);
475 xcomposite_handle = NULL;
476 usexcomposite = 0;
478 #endif /* defined(SONAME_LIBXCOMPOSITE) */
481 /***********************************************************************
482 * X11DRV process initialisation routine
484 static BOOL process_attach(void)
486 Display *display;
487 const char *env;
489 setup_options();
491 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
493 /* Open display */
495 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
496 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
498 if (!(display = XOpenDisplay( NULL ))) return FALSE;
500 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
501 screen = DefaultScreenOfDisplay( display );
502 visual = DefaultVisual( display, DefaultScreen(display) );
503 root_window = DefaultRootWindow( display );
504 gdi_display = display;
505 old_error_handler = XSetErrorHandler( error_handler );
507 /* Initialize screen depth */
509 if (screen_depth) /* depth specified */
511 int depth_count, i;
512 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
513 for (i = 0; i < depth_count; i++)
514 if (depth_list[i] == screen_depth) break;
515 XFree( depth_list );
516 if (i >= depth_count)
518 WARN( "invalid depth %d, using default\n", screen_depth );
519 screen_depth = 0;
522 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
523 screen_bpp = depth_to_bpp( screen_depth );
525 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
527 if (TRACE_ON(synchronous)) XSynchronize( display, True );
529 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
530 X11DRV_Settings_Init();
532 #ifdef HAVE_LIBXXF86VM
533 /* initialize XVidMode */
534 X11DRV_XF86VM_Init();
535 #endif
536 #ifdef SONAME_LIBXRANDR
537 /* initialize XRandR */
538 X11DRV_XRandR_Init();
539 #endif
540 #ifdef SONAME_LIBXCOMPOSITE
541 X11DRV_XComposite_Init();
542 #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 HAVE_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;
625 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
627 ERR( "could not create data\n" );
628 ExitProcess(1);
630 wine_tsx11_lock();
631 if (!(data->display = XOpenDisplay(NULL)))
633 wine_tsx11_unlock();
634 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
635 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
636 ExitProcess(1);
639 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
641 #ifdef HAVE_XKB
642 if (use_xkb)
644 use_xkb = XkbUseExtension( data->display, NULL, NULL );
645 if (use_xkb)
647 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
648 /* This works around an Xlib bug where it tries to get the display lock */
649 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
650 XkbKeysymToModifiers( data->display, 'A' );
651 XkbSetDetectableAutoRepeat( data->display, True, NULL );
654 #endif
656 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
657 wine_tsx11_unlock();
659 set_queue_display_fd( data->display );
660 TlsSetValue( thread_data_tls_index, data );
662 if (use_xim) X11DRV_SetupXIM();
663 X11DRV_SetCursor( NULL );
665 return data;
669 /***********************************************************************
670 * X11DRV initialisation routine
672 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
674 BOOL ret = TRUE;
676 switch(reason)
678 case DLL_PROCESS_ATTACH:
679 x11drv_module = hinst;
680 ret = process_attach();
681 break;
682 case DLL_THREAD_DETACH:
683 thread_detach();
684 break;
685 case DLL_PROCESS_DETACH:
686 process_detach();
687 break;
689 return ret;
692 /***********************************************************************
693 * GetScreenSaveActive (X11DRV.@)
695 * Returns the active status of the screen saver
697 BOOL X11DRV_GetScreenSaveActive(void)
699 int timeout, temp;
700 wine_tsx11_lock();
701 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
702 wine_tsx11_unlock();
703 return timeout != 0;
706 /***********************************************************************
707 * SetScreenSaveActive (X11DRV.@)
709 * Activate/Deactivate the screen saver
711 void X11DRV_SetScreenSaveActive(BOOL bActivate)
713 int timeout, interval, prefer_blanking, allow_exposures;
714 static int last_timeout = 15 * 60;
716 wine_tsx11_lock();
717 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
718 &allow_exposures);
719 if (timeout) last_timeout = timeout;
721 timeout = bActivate ? last_timeout : 0;
722 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
723 allow_exposures);
724 wine_tsx11_unlock();