push 5b1efc32b5a8acb1d5b5e60584746392dd0c436e
[wine/hacks.git] / dlls / winex11.drv / x11drv_main.c
blob3bd934b3e060158ad62c8d86d2466ada678a0374
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_MOVERESIZE",
142 "_NET_WM_NAME",
143 "_NET_WM_PID",
144 "_NET_WM_PING",
145 "_NET_WM_STATE",
146 "_NET_WM_STATE_ABOVE",
147 "_NET_WM_STATE_FULLSCREEN",
148 "_NET_WM_STATE_MAXIMIZED_HORZ",
149 "_NET_WM_STATE_MAXIMIZED_VERT",
150 "_NET_WM_STATE_SKIP_PAGER",
151 "_NET_WM_STATE_SKIP_TASKBAR",
152 "_NET_WM_WINDOW_OPACITY",
153 "_NET_WM_WINDOW_TYPE",
154 "_NET_WM_WINDOW_TYPE_DIALOG",
155 "_NET_WM_WINDOW_TYPE_NORMAL",
156 "_NET_WM_WINDOW_TYPE_UTILITY",
157 "_NET_WORKAREA",
158 "_XEMBED_INFO",
159 "XdndAware",
160 "XdndEnter",
161 "XdndPosition",
162 "XdndStatus",
163 "XdndLeave",
164 "XdndFinished",
165 "XdndDrop",
166 "XdndActionCopy",
167 "XdndActionMove",
168 "XdndActionLink",
169 "XdndActionAsk",
170 "XdndActionPrivate",
171 "XdndSelection",
172 "XdndTarget",
173 "XdndTypeList",
174 "HTML Format",
175 "WCF_DIB",
176 "image/gif",
177 "image/jpeg",
178 "image/png",
179 "text/html",
180 "text/plain",
181 "text/rtf",
182 "text/richtext",
183 "text/uri-list"
186 /***********************************************************************
187 * ignore_error
189 * Check if the X error is one we can ignore.
191 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
193 if (event->request_code == X_SetInputFocus &&
194 (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
196 /* ignore a number of errors on gdi display caused by creating/destroying windows */
197 if (display == gdi_display)
199 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
200 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
201 if (xrender_error_base) /* check for XRender errors */
203 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
205 #endif
207 return FALSE;
211 /***********************************************************************
212 * X11DRV_expect_error
214 * Setup a callback function that will be called on an X error. The
215 * callback must return non-zero if the error is the one it expected.
216 * This function acquires the x11 lock; X11DRV_check_error must be
217 * called in all cases to release it.
219 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
221 wine_tsx11_lock();
222 err_callback = callback;
223 err_callback_display = display;
224 err_callback_arg = arg;
225 err_callback_result = 0;
226 err_serial = NextRequest(display);
230 /***********************************************************************
231 * X11DRV_check_error
233 * Check if an expected X11 error occurred; return non-zero if yes.
234 * Also release the x11 lock obtained in X11DRV_expect_error.
235 * The caller is responsible for calling XSync first if necessary.
237 int X11DRV_check_error(void)
239 int ret;
240 err_callback = NULL;
241 ret = err_callback_result;
242 wine_tsx11_unlock();
243 return ret;
247 /***********************************************************************
248 * error_handler
250 static int error_handler( Display *display, XErrorEvent *error_evt )
252 if (err_callback && display == err_callback_display &&
253 (long)(error_evt->serial - err_serial) >= 0)
255 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
257 TRACE( "got expected error %d req %d\n",
258 error_evt->error_code, error_evt->request_code );
259 return 0;
262 if (ignore_error( display, error_evt ))
264 TRACE( "got ignored error %d req %d\n",
265 error_evt->error_code, error_evt->request_code );
266 return 0;
268 if (TRACE_ON(synchronous))
270 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
271 error_evt->serial, error_evt->request_code );
272 DebugBreak(); /* force an entry in the debugger */
274 old_error_handler( display, error_evt );
275 return 0;
278 /***********************************************************************
279 * wine_tsx11_lock (X11DRV.@)
281 void CDECL wine_tsx11_lock(void)
283 EnterCriticalSection( &X11DRV_CritSection );
286 /***********************************************************************
287 * wine_tsx11_unlock (X11DRV.@)
289 void CDECL wine_tsx11_unlock(void)
291 LeaveCriticalSection( &X11DRV_CritSection );
295 /***********************************************************************
296 * depth_to_bpp
298 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
300 unsigned int depth_to_bpp( unsigned int depth )
302 switch (depth)
304 case 1:
305 case 8:
306 return depth;
307 case 15:
308 case 16:
309 return 16;
310 case 24:
311 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
312 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
313 * for windowing, but gl applications can get visuals with alpha channels. So we
314 * should check the framebuffer and/or opengl formats available to find out what the
315 * framebuffer actually does
317 case 32:
318 return 32;
319 default:
320 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
321 return depth;
326 /***********************************************************************
327 * get_config_key
329 * Get a config key from either the app-specific or the default config
331 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
332 char *buffer, DWORD size )
334 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
335 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
336 return ERROR_FILE_NOT_FOUND;
340 /***********************************************************************
341 * setup_options
343 * Setup the x11drv options.
345 static void setup_options(void)
347 char buffer[MAX_PATH+16];
348 HKEY hkey, appkey = 0;
349 DWORD len;
351 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
352 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
354 /* open the app-specific key */
356 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
357 if (len && len < MAX_PATH)
359 HKEY tmpkey;
360 char *p, *appname = buffer;
361 if ((p = strrchr( appname, '/' ))) appname = p + 1;
362 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
363 strcat( appname, "\\X11 Driver" );
364 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
365 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
367 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
368 RegCloseKey( tmpkey );
372 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
373 managed_mode = IS_OPTION_TRUE( buffer[0] );
375 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
376 decorated_mode = IS_OPTION_TRUE( buffer[0] );
378 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
379 dxgrab = IS_OPTION_TRUE( buffer[0] );
381 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
382 usexvidmode = IS_OPTION_TRUE( buffer[0] );
384 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
385 usexrandr = IS_OPTION_TRUE( buffer[0] );
387 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
388 use_take_focus = IS_OPTION_TRUE( buffer[0] );
390 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
391 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
393 screen_depth = 0;
394 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
395 screen_depth = atoi(buffer);
397 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
398 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
400 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
401 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
403 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
404 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
406 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
407 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
409 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
410 use_xim = IS_OPTION_TRUE( buffer[0] );
412 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
413 private_color_map = IS_OPTION_TRUE( buffer[0] );
415 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
416 primary_monitor = atoi( buffer );
418 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
419 copy_default_colors = atoi(buffer);
421 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
422 alloc_system_colors = atoi(buffer);
424 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
426 if (appkey) RegCloseKey( appkey );
427 if (hkey) RegCloseKey( hkey );
430 #ifdef SONAME_LIBXCOMPOSITE
432 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
433 MAKE_FUNCPTR(XCompositeQueryExtension)
434 MAKE_FUNCPTR(XCompositeQueryVersion)
435 MAKE_FUNCPTR(XCompositeVersion)
436 MAKE_FUNCPTR(XCompositeRedirectWindow)
437 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
438 MAKE_FUNCPTR(XCompositeUnredirectWindow)
439 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
440 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
441 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
442 #undef MAKE_FUNCPTR
444 static int xcomp_event_base;
445 static int xcomp_error_base;
447 static void X11DRV_XComposite_Init(void)
449 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
450 if (!xcomposite_handle)
452 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
453 usexcomposite = 0;
454 return;
457 #define LOAD_FUNCPTR(f) \
458 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
459 goto sym_not_found;
460 LOAD_FUNCPTR(XCompositeQueryExtension)
461 LOAD_FUNCPTR(XCompositeQueryVersion)
462 LOAD_FUNCPTR(XCompositeVersion)
463 LOAD_FUNCPTR(XCompositeRedirectWindow)
464 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
465 LOAD_FUNCPTR(XCompositeUnredirectWindow)
466 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
467 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
468 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
469 #undef LOAD_FUNCPTR
471 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
472 &xcomp_error_base)) {
473 TRACE("XComposite extension could not be queried; disabled\n");
474 wine_dlclose(xcomposite_handle, NULL, 0);
475 xcomposite_handle = NULL;
476 usexcomposite = 0;
477 return;
479 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
480 return;
482 sym_not_found:
483 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
484 wine_dlclose(xcomposite_handle, NULL, 0);
485 xcomposite_handle = NULL;
486 usexcomposite = 0;
488 #endif /* defined(SONAME_LIBXCOMPOSITE) */
491 /***********************************************************************
492 * X11DRV process initialisation routine
494 static BOOL process_attach(void)
496 Display *display;
498 setup_options();
500 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
502 /* Open display */
504 if (!(display = XOpenDisplay( NULL ))) return FALSE;
506 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
507 screen = DefaultScreenOfDisplay( display );
508 visual = DefaultVisual( display, DefaultScreen(display) );
509 root_window = DefaultRootWindow( display );
510 gdi_display = display;
511 old_error_handler = XSetErrorHandler( error_handler );
513 /* Initialize screen depth */
515 if (screen_depth) /* depth specified */
517 int depth_count, i;
518 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
519 for (i = 0; i < depth_count; i++)
520 if (depth_list[i] == screen_depth) break;
521 XFree( depth_list );
522 if (i >= depth_count)
524 WARN( "invalid depth %d, using default\n", screen_depth );
525 screen_depth = 0;
528 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
529 screen_bpp = depth_to_bpp( screen_depth );
531 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
533 if (TRACE_ON(synchronous)) XSynchronize( display, True );
535 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
536 X11DRV_Settings_Init();
538 #ifdef SONAME_LIBXXF86VM
539 /* initialize XVidMode */
540 X11DRV_XF86VM_Init();
541 #endif
542 #ifdef SONAME_LIBXRANDR
543 /* initialize XRandR */
544 X11DRV_XRandR_Init();
545 #endif
546 #ifdef SONAME_LIBXCOMPOSITE
547 X11DRV_XComposite_Init();
548 #endif
550 #ifdef HAVE_XKB
551 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
552 #endif
553 X11DRV_InitKeyboard( gdi_display );
554 X11DRV_InitClipboard();
555 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
557 return TRUE;
561 /***********************************************************************
562 * X11DRV thread termination routine
564 static void thread_detach(void)
566 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
568 if (data)
570 X11DRV_ResetSelectionOwner();
571 wine_tsx11_lock();
572 if (data->xim) XCloseIM( data->xim );
573 if (data->font_set) XFreeFontSet( data->display, data->font_set );
574 XCloseDisplay( data->display );
575 wine_tsx11_unlock();
576 HeapFree( GetProcessHeap(), 0, data );
581 /***********************************************************************
582 * X11DRV process termination routine
584 static void process_detach(void)
586 #ifdef SONAME_LIBXXF86VM
587 /* cleanup XVidMode */
588 X11DRV_XF86VM_Cleanup();
589 #endif
590 if(using_client_side_fonts)
591 X11DRV_XRender_Finalize();
593 /* cleanup GDI */
594 X11DRV_GDI_Finalize();
595 X11DRV_OpenGL_Cleanup();
597 IME_UnregisterClasses();
598 DeleteCriticalSection( &X11DRV_CritSection );
599 TlsFree( thread_data_tls_index );
603 /* store the display fd into the message queue */
604 static void set_queue_display_fd( Display *display )
606 HANDLE handle;
607 int ret;
609 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
611 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
612 ExitProcess(1);
614 SERVER_START_REQ( set_queue_fd )
616 req->handle = wine_server_obj_handle( handle );
617 ret = wine_server_call( req );
619 SERVER_END_REQ;
620 if (ret)
622 MESSAGE( "x11drv: Can't store handle for display fd\n" );
623 ExitProcess(1);
625 CloseHandle( handle );
629 /***********************************************************************
630 * X11DRV thread initialisation routine
632 struct x11drv_thread_data *x11drv_init_thread_data(void)
634 struct x11drv_thread_data *data = x11drv_thread_data();
636 if (data) return data;
638 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
640 ERR( "could not create data\n" );
641 ExitProcess(1);
643 wine_tsx11_lock();
644 if (!(data->display = XOpenDisplay(NULL)))
646 wine_tsx11_unlock();
647 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));
648 ExitProcess(1);
651 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
653 #ifdef HAVE_XKB
654 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
655 XkbSetDetectableAutoRepeat( data->display, True, NULL );
656 #endif
658 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
659 wine_tsx11_unlock();
661 set_queue_display_fd( data->display );
662 TlsSetValue( thread_data_tls_index, data );
664 if (use_xim) X11DRV_SetupXIM();
665 X11DRV_SetCursor( NULL );
667 return data;
671 /***********************************************************************
672 * X11DRV initialisation routine
674 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
676 BOOL ret = TRUE;
678 switch(reason)
680 case DLL_PROCESS_ATTACH:
681 x11drv_module = hinst;
682 ret = process_attach();
683 break;
684 case DLL_THREAD_DETACH:
685 thread_detach();
686 break;
687 case DLL_PROCESS_DETACH:
688 process_detach();
689 break;
691 return ret;
694 /***********************************************************************
695 * GetScreenSaveActive (X11DRV.@)
697 * Returns the active status of the screen saver
699 BOOL CDECL X11DRV_GetScreenSaveActive(void)
701 int timeout, temp;
702 wine_tsx11_lock();
703 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
704 wine_tsx11_unlock();
705 return timeout != 0;
708 /***********************************************************************
709 * SetScreenSaveActive (X11DRV.@)
711 * Activate/Deactivate the screen saver
713 void CDECL X11DRV_SetScreenSaveActive(BOOL bActivate)
715 int timeout, interval, prefer_blanking, allow_exposures;
716 static int last_timeout = 15 * 60;
718 wine_tsx11_lock();
719 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
720 &allow_exposures);
721 if (timeout) last_timeout = timeout;
723 timeout = bActivate ? last_timeout : 0;
724 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
725 allow_exposures);
726 wine_tsx11_unlock();