winex11: Set the appropriate _NET_WM_STATE properties for maximized windows.
[wine/wine64.git] / dlls / winex11.drv / x11drv_main.c
blob50d45464919c8b2ac4a9e2e84f98f70f30258970
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_MAXIMIZED_HORZ",
143 "_NET_WM_STATE_MAXIMIZED_VERT",
144 "_NET_WM_STATE_SKIP_PAGER",
145 "_NET_WM_STATE_SKIP_TASKBAR",
146 "_NET_WM_WINDOW_TYPE",
147 "_NET_WM_WINDOW_TYPE_DIALOG",
148 "_NET_WM_WINDOW_TYPE_NORMAL",
149 "_NET_WM_WINDOW_TYPE_UTILITY",
150 "_XEMBED_INFO",
151 "XdndAware",
152 "XdndEnter",
153 "XdndPosition",
154 "XdndStatus",
155 "XdndLeave",
156 "XdndFinished",
157 "XdndDrop",
158 "XdndActionCopy",
159 "XdndActionMove",
160 "XdndActionLink",
161 "XdndActionAsk",
162 "XdndActionPrivate",
163 "XdndSelection",
164 "XdndTarget",
165 "XdndTypeList",
166 "WCF_DIB",
167 "image/gif",
168 "text/html",
169 "text/plain",
170 "text/rtf",
171 "text/richtext",
172 "text/uri-list"
175 /***********************************************************************
176 * ignore_error
178 * Check if the X error is one we can ignore.
180 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
182 if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
184 /* ignore a number of errors on gdi display caused by creating/destroying windows */
185 if (display == gdi_display)
187 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
188 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
189 if (xrender_error_base) /* check for XRender errors */
191 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
193 #endif
195 return FALSE;
199 /***********************************************************************
200 * X11DRV_expect_error
202 * Setup a callback function that will be called on an X error. The
203 * callback must return non-zero if the error is the one it expected.
204 * This function acquires the x11 lock; X11DRV_check_error must be
205 * called in all cases to release it.
207 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
209 wine_tsx11_lock();
210 err_callback = callback;
211 err_callback_display = display;
212 err_callback_arg = arg;
213 err_callback_result = 0;
214 err_serial = NextRequest(display);
218 /***********************************************************************
219 * X11DRV_check_error
221 * Check if an expected X11 error occurred; return non-zero if yes.
222 * Also release the x11 lock obtained in X11DRV_expect_error.
223 * The caller is responsible for calling XSync first if necessary.
225 int X11DRV_check_error(void)
227 int ret;
228 err_callback = NULL;
229 ret = err_callback_result;
230 wine_tsx11_unlock();
231 return ret;
235 /***********************************************************************
236 * error_handler
238 static int error_handler( Display *display, XErrorEvent *error_evt )
240 if (err_callback && display == err_callback_display &&
241 (long)(error_evt->serial - err_serial) >= 0)
243 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
245 TRACE( "got expected error %d req %d\n",
246 error_evt->error_code, error_evt->request_code );
247 return 0;
250 if (ignore_error( display, error_evt ))
252 TRACE( "got ignored error %d req %d\n",
253 error_evt->error_code, error_evt->request_code );
254 return 0;
256 if (TRACE_ON(synchronous))
258 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
259 error_evt->serial, error_evt->request_code );
260 DebugBreak(); /* force an entry in the debugger */
262 old_error_handler( display, error_evt );
263 return 0;
266 /***********************************************************************
267 * wine_tsx11_lock (X11DRV.@)
269 void wine_tsx11_lock(void)
271 EnterCriticalSection( &X11DRV_CritSection );
274 /***********************************************************************
275 * wine_tsx11_unlock (X11DRV.@)
277 void wine_tsx11_unlock(void)
279 LeaveCriticalSection( &X11DRV_CritSection );
283 /***********************************************************************
284 * depth_to_bpp
286 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
288 unsigned int depth_to_bpp( unsigned int depth )
290 switch (depth)
292 case 1:
293 case 8:
294 return depth;
295 case 15:
296 case 16:
297 return 16;
298 case 24:
299 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
300 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
301 * for windowing, but gl applications can get visuals with alpha channels. So we
302 * should check the framebuffer and/or opengl formats available to find out what the
303 * framebuffer actually does
305 case 32:
306 return 32;
307 default:
308 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
309 return depth;
314 /***********************************************************************
315 * get_config_key
317 * Get a config key from either the app-specific or the default config
319 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
320 char *buffer, DWORD size )
322 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
323 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
324 return ERROR_FILE_NOT_FOUND;
328 /***********************************************************************
329 * setup_options
331 * Setup the x11drv options.
333 static void setup_options(void)
335 char buffer[MAX_PATH+16];
336 HKEY hkey, appkey = 0;
337 DWORD len;
339 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
340 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
342 /* open the app-specific key */
344 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
345 if (len && len < MAX_PATH)
347 HKEY tmpkey;
348 char *p, *appname = buffer;
349 if ((p = strrchr( appname, '/' ))) appname = p + 1;
350 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
351 strcat( appname, "\\X11 Driver" );
352 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
353 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
355 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
356 RegCloseKey( tmpkey );
360 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
361 managed_mode = IS_OPTION_TRUE( buffer[0] );
363 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
364 dxgrab = IS_OPTION_TRUE( buffer[0] );
366 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
367 usexvidmode = IS_OPTION_TRUE( buffer[0] );
369 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
370 usexrandr = IS_OPTION_TRUE( buffer[0] );
372 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
373 use_take_focus = IS_OPTION_TRUE( buffer[0] );
375 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
376 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
378 screen_depth = 0;
379 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
380 screen_depth = atoi(buffer);
382 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
383 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
385 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
386 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
388 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
389 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
391 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
392 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
394 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
395 use_xim = IS_OPTION_TRUE( buffer[0] );
397 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
398 private_color_map = IS_OPTION_TRUE( buffer[0] );
400 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
401 primary_monitor = atoi( buffer );
403 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
404 copy_default_colors = atoi(buffer);
406 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
407 alloc_system_colors = atoi(buffer);
409 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
411 if (appkey) RegCloseKey( appkey );
412 if (hkey) RegCloseKey( hkey );
415 #ifdef SONAME_LIBXCOMPOSITE
417 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
418 MAKE_FUNCPTR(XCompositeQueryExtension)
419 MAKE_FUNCPTR(XCompositeQueryVersion)
420 MAKE_FUNCPTR(XCompositeVersion)
421 MAKE_FUNCPTR(XCompositeRedirectWindow)
422 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
423 MAKE_FUNCPTR(XCompositeUnredirectWindow)
424 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
425 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
426 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
427 #undef MAKE_FUNCPTR
429 static int xcomp_event_base;
430 static int xcomp_error_base;
432 static void X11DRV_XComposite_Init(void)
434 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
435 if (!xcomposite_handle)
437 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
438 usexcomposite = 0;
439 return;
442 #define LOAD_FUNCPTR(f) \
443 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
444 goto sym_not_found;
445 LOAD_FUNCPTR(XCompositeQueryExtension)
446 LOAD_FUNCPTR(XCompositeQueryVersion)
447 LOAD_FUNCPTR(XCompositeVersion)
448 LOAD_FUNCPTR(XCompositeRedirectWindow)
449 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
450 LOAD_FUNCPTR(XCompositeUnredirectWindow)
451 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
452 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
453 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
454 #undef LOAD_FUNCPTR
456 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
457 &xcomp_error_base)) {
458 TRACE("XComposite extension could not be queried; disabled\n");
459 wine_dlclose(xcomposite_handle, NULL, 0);
460 xcomposite_handle = NULL;
461 usexcomposite = 0;
462 return;
464 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
465 return;
467 sym_not_found:
468 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
469 wine_dlclose(xcomposite_handle, NULL, 0);
470 xcomposite_handle = NULL;
471 usexcomposite = 0;
473 #endif /* defined(SONAME_LIBXCOMPOSITE) */
476 /***********************************************************************
477 * X11DRV process initialisation routine
479 static BOOL process_attach(void)
481 Display *display;
482 const char *env;
484 setup_options();
486 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
488 /* Open display */
490 if (!(env = getenv("XMODIFIERS")) || !*env) /* try to avoid the Xlib XIM locking bug */
491 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
493 if (!(display = XOpenDisplay( NULL ))) return FALSE;
495 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
496 screen = DefaultScreenOfDisplay( display );
497 visual = DefaultVisual( display, DefaultScreen(display) );
498 root_window = DefaultRootWindow( display );
499 gdi_display = display;
500 old_error_handler = XSetErrorHandler( error_handler );
502 /* Initialize screen depth */
504 if (screen_depth) /* depth specified */
506 int depth_count, i;
507 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
508 for (i = 0; i < depth_count; i++)
509 if (depth_list[i] == screen_depth) break;
510 XFree( depth_list );
511 if (i >= depth_count)
513 WARN( "invalid depth %d, using default\n", screen_depth );
514 screen_depth = 0;
517 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
518 screen_bpp = depth_to_bpp( screen_depth );
520 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
522 if (TRACE_ON(synchronous)) XSynchronize( display, True );
524 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
525 X11DRV_Settings_Init();
527 #ifdef HAVE_LIBXXF86VM
528 /* initialize XVidMode */
529 X11DRV_XF86VM_Init();
530 #endif
531 #ifdef SONAME_LIBXRANDR
532 /* initialize XRandR */
533 X11DRV_XRandR_Init();
534 #endif
535 #ifdef SONAME_LIBXCOMPOSITE
536 X11DRV_XComposite_Init();
537 #endif
539 X11DRV_InitKeyboard( gdi_display );
540 X11DRV_InitClipboard();
542 return TRUE;
546 /***********************************************************************
547 * X11DRV thread termination routine
549 static void thread_detach(void)
551 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
553 if (data)
555 X11DRV_ResetSelectionOwner();
556 wine_tsx11_lock();
557 if (data->xim) XCloseIM( data->xim );
558 XCloseDisplay( data->display );
559 wine_tsx11_unlock();
560 HeapFree( GetProcessHeap(), 0, data );
565 /***********************************************************************
566 * X11DRV process termination routine
568 static void process_detach(void)
570 #ifdef HAVE_LIBXXF86VM
571 /* cleanup XVidMode */
572 X11DRV_XF86VM_Cleanup();
573 #endif
574 if(using_client_side_fonts)
575 X11DRV_XRender_Finalize();
577 /* cleanup GDI */
578 X11DRV_GDI_Finalize();
580 DeleteCriticalSection( &X11DRV_CritSection );
581 TlsFree( thread_data_tls_index );
585 /* store the display fd into the message queue */
586 static void set_queue_display_fd( Display *display )
588 HANDLE handle;
589 int ret;
591 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
593 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
594 ExitProcess(1);
596 SERVER_START_REQ( set_queue_fd )
598 req->handle = handle;
599 ret = wine_server_call( req );
601 SERVER_END_REQ;
602 if (ret)
604 MESSAGE( "x11drv: Can't store handle for display fd\n" );
605 ExitProcess(1);
607 CloseHandle( handle );
611 /***********************************************************************
612 * X11DRV thread initialisation routine
614 struct x11drv_thread_data *x11drv_init_thread_data(void)
616 struct x11drv_thread_data *data;
618 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
620 ERR( "could not create data\n" );
621 ExitProcess(1);
623 wine_tsx11_lock();
624 if (!(data->display = XOpenDisplay(NULL)))
626 wine_tsx11_unlock();
627 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
628 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
629 ExitProcess(1);
632 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
634 #ifdef HAVE_XKB
635 if (use_xkb)
637 use_xkb = XkbUseExtension( data->display, NULL, NULL );
638 if (use_xkb)
640 /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
641 /* This works around an Xlib bug where it tries to get the display lock */
642 /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
643 XkbKeysymToModifiers( data->display, 'A' );
644 XkbSetDetectableAutoRepeat( data->display, True, NULL );
647 #endif
649 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
650 wine_tsx11_unlock();
652 if (!use_xim)
653 data->xim = NULL;
654 else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
655 WARN("Input Method is not available\n");
657 set_queue_display_fd( data->display );
658 data->process_event_count = 0;
659 data->cursor = None;
660 data->cursor_window = None;
661 data->grab_window = None;
662 data->last_focus = 0;
663 data->selection_wnd = 0;
664 TlsSetValue( thread_data_tls_index, data );
665 X11DRV_SetCursor( NULL );
666 return data;
670 /***********************************************************************
671 * X11DRV initialisation routine
673 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
675 BOOL ret = TRUE;
677 switch(reason)
679 case DLL_PROCESS_ATTACH:
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();