push 9cc132ec6c678833a0b16cc6a61d52a23f072314
[wine/hacks.git] / dlls / winex11.drv / x11drv_main.c
blob3a1fa3fac7332030f0d819199a334084617d0ad8
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);
59 WINE_DECLARE_DEBUG_CHANNEL(winediag);
61 static CRITICAL_SECTION X11DRV_CritSection;
62 static CRITICAL_SECTION_DEBUG critsect_debug =
64 0, 0, &X11DRV_CritSection,
65 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
66 0, 0, { (DWORD_PTR)(__FILE__ ": X11DRV_CritSection") }
68 static CRITICAL_SECTION X11DRV_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 };
70 Screen *screen;
71 Visual *visual;
72 unsigned int screen_width;
73 unsigned int screen_height;
74 unsigned int screen_bpp;
75 unsigned int screen_depth;
76 RECT virtual_screen_rect;
77 Window root_window;
78 int dxgrab = 0;
79 int usexvidmode = 1;
80 int usexrandr = 1;
81 int usexcomposite = 1;
82 int use_xkb = 1;
83 int use_take_focus = 1;
84 int use_primary_selection = 0;
85 int managed_mode = 1;
86 int decorated_mode = 1;
87 int private_color_map = 0;
88 int primary_monitor = 0;
89 int client_side_with_core = 1;
90 int client_side_with_render = 1;
91 int client_side_antialias_with_core = 1;
92 int client_side_antialias_with_render = 1;
93 int copy_default_colors = 128;
94 int alloc_system_colors = 256;
95 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
96 int xrender_error_base = 0;
97 HMODULE x11drv_module = 0;
99 static x11drv_error_callback err_callback; /* current callback for error */
100 static Display *err_callback_display; /* display callback is set for */
101 static void *err_callback_arg; /* error callback argument */
102 static int err_callback_result; /* error callback result */
103 static unsigned long err_serial; /* serial number of first request */
104 static int (*old_error_handler)( Display *, XErrorEvent * );
105 static int use_xim = 1;
106 static char input_style[20];
108 #define IS_OPTION_TRUE(ch) \
109 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
110 #define IS_OPTION_FALSE(ch) \
111 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
113 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
115 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
117 "CLIPBOARD",
118 "COMPOUND_TEXT",
119 "INCR",
120 "MULTIPLE",
121 "SELECTION_DATA",
122 "TARGETS",
123 "TEXT",
124 "UTF8_STRING",
125 "RAW_ASCENT",
126 "RAW_DESCENT",
127 "RAW_CAP_HEIGHT",
128 "WM_PROTOCOLS",
129 "WM_DELETE_WINDOW",
130 "WM_STATE",
131 "WM_TAKE_FOCUS",
132 "DndProtocol",
133 "DndSelection",
134 "_ICC_PROFILE",
135 "_MOTIF_WM_HINTS",
136 "_NET_STARTUP_INFO_BEGIN",
137 "_NET_STARTUP_INFO",
138 "_NET_SUPPORTED",
139 "_NET_SYSTEM_TRAY_OPCODE",
140 "_NET_SYSTEM_TRAY_S0",
141 "_NET_WM_ICON",
142 "_NET_WM_MOVERESIZE",
143 "_NET_WM_NAME",
144 "_NET_WM_PID",
145 "_NET_WM_PING",
146 "_NET_WM_STATE",
147 "_NET_WM_STATE_ABOVE",
148 "_NET_WM_STATE_FULLSCREEN",
149 "_NET_WM_STATE_MAXIMIZED_HORZ",
150 "_NET_WM_STATE_MAXIMIZED_VERT",
151 "_NET_WM_STATE_SKIP_PAGER",
152 "_NET_WM_STATE_SKIP_TASKBAR",
153 "_NET_WM_WINDOW_OPACITY",
154 "_NET_WM_WINDOW_TYPE",
155 "_NET_WM_WINDOW_TYPE_DIALOG",
156 "_NET_WM_WINDOW_TYPE_NORMAL",
157 "_NET_WM_WINDOW_TYPE_UTILITY",
158 "_NET_WORKAREA",
159 "_XEMBED_INFO",
160 "XdndAware",
161 "XdndEnter",
162 "XdndPosition",
163 "XdndStatus",
164 "XdndLeave",
165 "XdndFinished",
166 "XdndDrop",
167 "XdndActionCopy",
168 "XdndActionMove",
169 "XdndActionLink",
170 "XdndActionAsk",
171 "XdndActionPrivate",
172 "XdndSelection",
173 "XdndTarget",
174 "XdndTypeList",
175 "HTML Format",
176 "WCF_DIB",
177 "image/gif",
178 "image/jpeg",
179 "image/png",
180 "text/html",
181 "text/plain",
182 "text/rtf",
183 "text/richtext",
184 "text/uri-list"
187 /***********************************************************************
188 * ignore_error
190 * Check if the X error is one we can ignore.
192 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
194 if (event->request_code == X_SetInputFocus &&
195 (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
197 /* ignore a number of errors on gdi display caused by creating/destroying windows */
198 if (display == gdi_display)
200 if (event->error_code == BadDrawable ||
201 event->error_code == BadGC ||
202 event->error_code == BadWindow)
203 return TRUE;
204 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
205 if (xrender_error_base) /* check for XRender errors */
207 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
209 #endif
211 return FALSE;
215 /***********************************************************************
216 * X11DRV_expect_error
218 * Setup a callback function that will be called on an X error. The
219 * callback must return non-zero if the error is the one it expected.
220 * This function acquires the x11 lock; X11DRV_check_error must be
221 * called in all cases to release it.
223 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
225 wine_tsx11_lock();
226 err_callback = callback;
227 err_callback_display = display;
228 err_callback_arg = arg;
229 err_callback_result = 0;
230 err_serial = NextRequest(display);
234 /***********************************************************************
235 * X11DRV_check_error
237 * Check if an expected X11 error occurred; return non-zero if yes.
238 * Also release the x11 lock obtained in X11DRV_expect_error.
239 * The caller is responsible for calling XSync first if necessary.
241 int X11DRV_check_error(void)
243 int ret;
244 err_callback = NULL;
245 ret = err_callback_result;
246 wine_tsx11_unlock();
247 return ret;
251 /***********************************************************************
252 * error_handler
254 static int error_handler( Display *display, XErrorEvent *error_evt )
256 if (err_callback && display == err_callback_display &&
257 (long)(error_evt->serial - err_serial) >= 0)
259 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
261 TRACE( "got expected error %d req %d\n",
262 error_evt->error_code, error_evt->request_code );
263 return 0;
266 if (ignore_error( display, error_evt ))
268 TRACE( "got ignored error %d req %d\n",
269 error_evt->error_code, error_evt->request_code );
270 return 0;
272 if (TRACE_ON(synchronous))
274 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
275 error_evt->serial, error_evt->request_code );
276 DebugBreak(); /* force an entry in the debugger */
278 old_error_handler( display, error_evt );
279 return 0;
282 /***********************************************************************
283 * wine_tsx11_lock (X11DRV.@)
285 void CDECL wine_tsx11_lock(void)
287 EnterCriticalSection( &X11DRV_CritSection );
290 /***********************************************************************
291 * wine_tsx11_unlock (X11DRV.@)
293 void CDECL wine_tsx11_unlock(void)
295 LeaveCriticalSection( &X11DRV_CritSection );
299 /***********************************************************************
300 * depth_to_bpp
302 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
304 unsigned int depth_to_bpp( unsigned int depth )
306 switch (depth)
308 case 1:
309 case 8:
310 return depth;
311 case 15:
312 case 16:
313 return 16;
314 case 24:
315 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
316 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
317 * for windowing, but gl applications can get visuals with alpha channels. So we
318 * should check the framebuffer and/or opengl formats available to find out what the
319 * framebuffer actually does
321 case 32:
322 return 32;
323 default:
324 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
325 return depth;
330 /***********************************************************************
331 * get_config_key
333 * Get a config key from either the app-specific or the default config
335 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
336 char *buffer, DWORD size )
338 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
339 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
340 return ERROR_FILE_NOT_FOUND;
344 /***********************************************************************
345 * setup_options
347 * Setup the x11drv options.
349 static void setup_options(void)
351 char buffer[MAX_PATH+16];
352 HKEY hkey, appkey = 0;
353 DWORD len;
355 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
356 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
358 /* open the app-specific key */
360 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
361 if (len && len < MAX_PATH)
363 HKEY tmpkey;
364 char *p, *appname = buffer;
365 if ((p = strrchr( appname, '/' ))) appname = p + 1;
366 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
367 strcat( appname, "\\X11 Driver" );
368 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
369 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
371 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
372 RegCloseKey( tmpkey );
376 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
377 managed_mode = IS_OPTION_TRUE( buffer[0] );
379 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
380 decorated_mode = IS_OPTION_TRUE( buffer[0] );
382 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
383 dxgrab = IS_OPTION_TRUE( buffer[0] );
385 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
386 usexvidmode = IS_OPTION_TRUE( buffer[0] );
388 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
389 usexrandr = IS_OPTION_TRUE( buffer[0] );
391 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
392 use_take_focus = IS_OPTION_TRUE( buffer[0] );
394 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
395 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
397 screen_depth = 0;
398 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
399 screen_depth = atoi(buffer);
401 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
402 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
404 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
405 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
407 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
408 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
410 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
411 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
413 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
414 use_xim = IS_OPTION_TRUE( buffer[0] );
416 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
417 private_color_map = IS_OPTION_TRUE( buffer[0] );
419 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
420 primary_monitor = atoi( buffer );
422 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
423 copy_default_colors = atoi(buffer);
425 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
426 alloc_system_colors = atoi(buffer);
428 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
430 if (appkey) RegCloseKey( appkey );
431 if (hkey) RegCloseKey( hkey );
434 #ifdef SONAME_LIBXCOMPOSITE
436 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
437 MAKE_FUNCPTR(XCompositeQueryExtension)
438 MAKE_FUNCPTR(XCompositeQueryVersion)
439 MAKE_FUNCPTR(XCompositeVersion)
440 MAKE_FUNCPTR(XCompositeRedirectWindow)
441 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
442 MAKE_FUNCPTR(XCompositeUnredirectWindow)
443 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
444 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
445 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
446 #undef MAKE_FUNCPTR
448 static int xcomp_event_base;
449 static int xcomp_error_base;
451 static void X11DRV_XComposite_Init(void)
453 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
454 if (!xcomposite_handle)
456 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
457 usexcomposite = 0;
458 return;
461 #define LOAD_FUNCPTR(f) \
462 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
463 goto sym_not_found;
464 LOAD_FUNCPTR(XCompositeQueryExtension)
465 LOAD_FUNCPTR(XCompositeQueryVersion)
466 LOAD_FUNCPTR(XCompositeVersion)
467 LOAD_FUNCPTR(XCompositeRedirectWindow)
468 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
469 LOAD_FUNCPTR(XCompositeUnredirectWindow)
470 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
471 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
472 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
473 #undef LOAD_FUNCPTR
475 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
476 &xcomp_error_base)) {
477 TRACE("XComposite extension could not be queried; disabled\n");
478 wine_dlclose(xcomposite_handle, NULL, 0);
479 xcomposite_handle = NULL;
480 usexcomposite = 0;
481 return;
483 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
484 return;
486 sym_not_found:
487 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
488 wine_dlclose(xcomposite_handle, NULL, 0);
489 xcomposite_handle = NULL;
490 usexcomposite = 0;
492 #endif /* defined(SONAME_LIBXCOMPOSITE) */
495 /***********************************************************************
496 * X11DRV process initialisation routine
498 static BOOL process_attach(void)
500 Display *display;
502 setup_options();
504 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
506 /* Open display */
508 if (!(display = XOpenDisplay( NULL ))) return FALSE;
510 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
511 screen = DefaultScreenOfDisplay( display );
512 visual = DefaultVisual( display, DefaultScreen(display) );
513 root_window = DefaultRootWindow( display );
514 gdi_display = display;
515 old_error_handler = XSetErrorHandler( error_handler );
517 /* Initialize screen depth */
519 if (screen_depth) /* depth specified */
521 int depth_count, i;
522 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
523 for (i = 0; i < depth_count; i++)
524 if (depth_list[i] == screen_depth) break;
525 XFree( depth_list );
526 if (i >= depth_count)
528 WARN( "invalid depth %d, using default\n", screen_depth );
529 screen_depth = 0;
532 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
533 screen_bpp = depth_to_bpp( screen_depth );
535 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
537 if (TRACE_ON(synchronous)) XSynchronize( display, True );
539 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
540 X11DRV_Settings_Init();
542 #ifdef SONAME_LIBXXF86VM
543 /* initialize XVidMode */
544 X11DRV_XF86VM_Init();
545 #endif
546 #ifdef SONAME_LIBXRANDR
547 /* initialize XRandR */
548 X11DRV_XRandR_Init();
549 #endif
550 #ifdef SONAME_LIBXCOMPOSITE
551 X11DRV_XComposite_Init();
552 #endif
554 #ifdef HAVE_XKB
555 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
556 #endif
557 X11DRV_InitKeyboard( gdi_display );
558 X11DRV_InitClipboard();
559 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
561 return TRUE;
565 /***********************************************************************
566 * X11DRV thread termination routine
568 static void thread_detach(void)
570 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
572 if (data)
574 X11DRV_ResetSelectionOwner();
575 wine_tsx11_lock();
576 if (data->xim) XCloseIM( data->xim );
577 if (data->font_set) XFreeFontSet( data->display, data->font_set );
578 XCloseDisplay( data->display );
579 wine_tsx11_unlock();
580 HeapFree( GetProcessHeap(), 0, data );
585 /***********************************************************************
586 * X11DRV process termination routine
588 static void process_detach(void)
590 X11DRV_Clipboard_Cleanup();
591 #ifdef SONAME_LIBXXF86VM
592 /* cleanup XVidMode */
593 X11DRV_XF86VM_Cleanup();
594 #endif
595 if(using_client_side_fonts)
596 X11DRV_XRender_Finalize();
598 /* cleanup GDI */
599 X11DRV_GDI_Finalize();
600 X11DRV_OpenGL_Cleanup();
602 IME_UnregisterClasses();
603 DeleteCriticalSection( &X11DRV_CritSection );
604 TlsFree( thread_data_tls_index );
608 /* store the display fd into the message queue */
609 static void set_queue_display_fd( Display *display )
611 HANDLE handle;
612 int ret;
614 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
616 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
617 ExitProcess(1);
619 SERVER_START_REQ( set_queue_fd )
621 req->handle = wine_server_obj_handle( handle );
622 ret = wine_server_call( req );
624 SERVER_END_REQ;
625 if (ret)
627 MESSAGE( "x11drv: Can't store handle for display fd\n" );
628 ExitProcess(1);
630 CloseHandle( handle );
634 /***********************************************************************
635 * X11DRV thread initialisation routine
637 struct x11drv_thread_data *x11drv_init_thread_data(void)
639 struct x11drv_thread_data *data = x11drv_thread_data();
641 if (data) return data;
643 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
645 ERR( "could not create data\n" );
646 ExitProcess(1);
648 wine_tsx11_lock();
649 if (!(data->display = XOpenDisplay(NULL)))
651 wine_tsx11_unlock();
652 ERR_(winediag)( "x11drv: Can't open display: %s. Please ensure that your X server is running and that $DISPLAY is set correctly.\n", XDisplayName(NULL));
653 ExitProcess(1);
656 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
658 #ifdef HAVE_XKB
659 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
660 XkbSetDetectableAutoRepeat( data->display, True, NULL );
661 #endif
663 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
664 wine_tsx11_unlock();
666 set_queue_display_fd( data->display );
667 TlsSetValue( thread_data_tls_index, data );
669 if (use_xim) X11DRV_SetupXIM();
671 return data;
675 /***********************************************************************
676 * X11DRV initialisation routine
678 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
680 BOOL ret = TRUE;
682 switch(reason)
684 case DLL_PROCESS_ATTACH:
685 x11drv_module = hinst;
686 ret = process_attach();
687 break;
688 case DLL_THREAD_DETACH:
689 thread_detach();
690 break;
691 case DLL_PROCESS_DETACH:
692 process_detach();
693 break;
695 return ret;
698 /***********************************************************************
699 * GetScreenSaveActive (X11DRV.@)
701 * Returns the active status of the screen saver
703 BOOL CDECL X11DRV_GetScreenSaveActive(void)
705 int timeout, temp;
706 wine_tsx11_lock();
707 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
708 wine_tsx11_unlock();
709 return timeout != 0;
712 /***********************************************************************
713 * SetScreenSaveActive (X11DRV.@)
715 * Activate/Deactivate the screen saver
717 void CDECL X11DRV_SetScreenSaveActive(BOOL bActivate)
719 int timeout, interval, prefer_blanking, allow_exposures;
720 static int last_timeout = 15 * 60;
722 wine_tsx11_lock();
723 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
724 &allow_exposures);
725 if (timeout) last_timeout = timeout;
727 timeout = bActivate ? last_timeout : 0;
728 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
729 allow_exposures);
730 wine_tsx11_unlock();