comctl32: Implement imagelist drag functions, GetOverlayImage.
[wine/multimedia.git] / dlls / winex11.drv / x11drv_main.c
blobb97426ebd2737e564df5d2d2eb921e46a59e66bf
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 "INCR",
119 "MULTIPLE",
120 "SELECTION_DATA",
121 "TARGETS",
122 "TEXT",
123 "UTF8_STRING",
124 "RAW_ASCENT",
125 "RAW_DESCENT",
126 "RAW_CAP_HEIGHT",
127 "WM_PROTOCOLS",
128 "WM_DELETE_WINDOW",
129 "WM_STATE",
130 "WM_TAKE_FOCUS",
131 "DndProtocol",
132 "DndSelection",
133 "_ICC_PROFILE",
134 "_MOTIF_WM_HINTS",
135 "_NET_STARTUP_INFO_BEGIN",
136 "_NET_STARTUP_INFO",
137 "_NET_SUPPORTED",
138 "_NET_SYSTEM_TRAY_OPCODE",
139 "_NET_SYSTEM_TRAY_S0",
140 "_NET_WM_MOVERESIZE",
141 "_NET_WM_NAME",
142 "_NET_WM_PID",
143 "_NET_WM_PING",
144 "_NET_WM_STATE",
145 "_NET_WM_STATE_ABOVE",
146 "_NET_WM_STATE_FULLSCREEN",
147 "_NET_WM_STATE_MAXIMIZED_HORZ",
148 "_NET_WM_STATE_MAXIMIZED_VERT",
149 "_NET_WM_STATE_SKIP_PAGER",
150 "_NET_WM_STATE_SKIP_TASKBAR",
151 "_NET_WM_WINDOW_OPACITY",
152 "_NET_WM_WINDOW_TYPE",
153 "_NET_WM_WINDOW_TYPE_DIALOG",
154 "_NET_WM_WINDOW_TYPE_NORMAL",
155 "_NET_WM_WINDOW_TYPE_UTILITY",
156 "_NET_WORKAREA",
157 "_XEMBED_INFO",
158 "XdndAware",
159 "XdndEnter",
160 "XdndPosition",
161 "XdndStatus",
162 "XdndLeave",
163 "XdndFinished",
164 "XdndDrop",
165 "XdndActionCopy",
166 "XdndActionMove",
167 "XdndActionLink",
168 "XdndActionAsk",
169 "XdndActionPrivate",
170 "XdndSelection",
171 "XdndTarget",
172 "XdndTypeList",
173 "WCF_DIB",
174 "image/gif",
175 "image/jpeg",
176 "image/png",
177 "text/html",
178 "text/plain",
179 "text/rtf",
180 "text/richtext",
181 "text/uri-list"
184 /***********************************************************************
185 * ignore_error
187 * Check if the X error is one we can ignore.
189 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
191 if (event->request_code == X_SetInputFocus &&
192 (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
194 /* ignore a number of errors on gdi display caused by creating/destroying windows */
195 if (display == gdi_display)
197 if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
198 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
199 if (xrender_error_base) /* check for XRender errors */
201 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
203 #endif
205 return FALSE;
209 /***********************************************************************
210 * X11DRV_expect_error
212 * Setup a callback function that will be called on an X error. The
213 * callback must return non-zero if the error is the one it expected.
214 * This function acquires the x11 lock; X11DRV_check_error must be
215 * called in all cases to release it.
217 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
219 wine_tsx11_lock();
220 err_callback = callback;
221 err_callback_display = display;
222 err_callback_arg = arg;
223 err_callback_result = 0;
224 err_serial = NextRequest(display);
228 /***********************************************************************
229 * X11DRV_check_error
231 * Check if an expected X11 error occurred; return non-zero if yes.
232 * Also release the x11 lock obtained in X11DRV_expect_error.
233 * The caller is responsible for calling XSync first if necessary.
235 int X11DRV_check_error(void)
237 int ret;
238 err_callback = NULL;
239 ret = err_callback_result;
240 wine_tsx11_unlock();
241 return ret;
245 /***********************************************************************
246 * error_handler
248 static int error_handler( Display *display, XErrorEvent *error_evt )
250 if (err_callback && display == err_callback_display &&
251 (long)(error_evt->serial - err_serial) >= 0)
253 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
255 TRACE( "got expected error %d req %d\n",
256 error_evt->error_code, error_evt->request_code );
257 return 0;
260 if (ignore_error( display, error_evt ))
262 TRACE( "got ignored error %d req %d\n",
263 error_evt->error_code, error_evt->request_code );
264 return 0;
266 if (TRACE_ON(synchronous))
268 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
269 error_evt->serial, error_evt->request_code );
270 DebugBreak(); /* force an entry in the debugger */
272 old_error_handler( display, error_evt );
273 return 0;
276 /***********************************************************************
277 * wine_tsx11_lock (X11DRV.@)
279 void CDECL wine_tsx11_lock(void)
281 EnterCriticalSection( &X11DRV_CritSection );
284 /***********************************************************************
285 * wine_tsx11_unlock (X11DRV.@)
287 void CDECL wine_tsx11_unlock(void)
289 LeaveCriticalSection( &X11DRV_CritSection );
293 /***********************************************************************
294 * depth_to_bpp
296 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
298 unsigned int depth_to_bpp( unsigned int depth )
300 switch (depth)
302 case 1:
303 case 8:
304 return depth;
305 case 15:
306 case 16:
307 return 16;
308 case 24:
309 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
310 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
311 * for windowing, but gl applications can get visuals with alpha channels. So we
312 * should check the framebuffer and/or opengl formats available to find out what the
313 * framebuffer actually does
315 case 32:
316 return 32;
317 default:
318 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
319 return depth;
324 /***********************************************************************
325 * get_config_key
327 * Get a config key from either the app-specific or the default config
329 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
330 char *buffer, DWORD size )
332 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
333 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
334 return ERROR_FILE_NOT_FOUND;
338 /***********************************************************************
339 * setup_options
341 * Setup the x11drv options.
343 static void setup_options(void)
345 char buffer[MAX_PATH+16];
346 HKEY hkey, appkey = 0;
347 DWORD len;
349 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
350 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
352 /* open the app-specific key */
354 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
355 if (len && len < MAX_PATH)
357 HKEY tmpkey;
358 char *p, *appname = buffer;
359 if ((p = strrchr( appname, '/' ))) appname = p + 1;
360 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
361 strcat( appname, "\\X11 Driver" );
362 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
363 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
365 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
366 RegCloseKey( tmpkey );
370 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
371 managed_mode = IS_OPTION_TRUE( buffer[0] );
373 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
374 decorated_mode = IS_OPTION_TRUE( buffer[0] );
376 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
377 dxgrab = IS_OPTION_TRUE( buffer[0] );
379 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
380 usexvidmode = IS_OPTION_TRUE( buffer[0] );
382 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
383 usexrandr = IS_OPTION_TRUE( buffer[0] );
385 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
386 use_take_focus = IS_OPTION_TRUE( buffer[0] );
388 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
389 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
391 screen_depth = 0;
392 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
393 screen_depth = atoi(buffer);
395 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
396 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
398 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
399 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
401 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
402 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
404 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
405 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
407 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
408 use_xim = IS_OPTION_TRUE( buffer[0] );
410 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
411 private_color_map = IS_OPTION_TRUE( buffer[0] );
413 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
414 primary_monitor = atoi( buffer );
416 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
417 copy_default_colors = atoi(buffer);
419 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
420 alloc_system_colors = atoi(buffer);
422 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
424 if (appkey) RegCloseKey( appkey );
425 if (hkey) RegCloseKey( hkey );
428 #ifdef SONAME_LIBXCOMPOSITE
430 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
431 MAKE_FUNCPTR(XCompositeQueryExtension)
432 MAKE_FUNCPTR(XCompositeQueryVersion)
433 MAKE_FUNCPTR(XCompositeVersion)
434 MAKE_FUNCPTR(XCompositeRedirectWindow)
435 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
436 MAKE_FUNCPTR(XCompositeUnredirectWindow)
437 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
438 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
439 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
440 #undef MAKE_FUNCPTR
442 static int xcomp_event_base;
443 static int xcomp_error_base;
445 static void X11DRV_XComposite_Init(void)
447 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
448 if (!xcomposite_handle)
450 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
451 usexcomposite = 0;
452 return;
455 #define LOAD_FUNCPTR(f) \
456 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
457 goto sym_not_found;
458 LOAD_FUNCPTR(XCompositeQueryExtension)
459 LOAD_FUNCPTR(XCompositeQueryVersion)
460 LOAD_FUNCPTR(XCompositeVersion)
461 LOAD_FUNCPTR(XCompositeRedirectWindow)
462 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
463 LOAD_FUNCPTR(XCompositeUnredirectWindow)
464 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
465 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
466 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
467 #undef LOAD_FUNCPTR
469 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
470 &xcomp_error_base)) {
471 TRACE("XComposite extension could not be queried; disabled\n");
472 wine_dlclose(xcomposite_handle, NULL, 0);
473 xcomposite_handle = NULL;
474 usexcomposite = 0;
475 return;
477 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
478 return;
480 sym_not_found:
481 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
482 wine_dlclose(xcomposite_handle, NULL, 0);
483 xcomposite_handle = NULL;
484 usexcomposite = 0;
486 #endif /* defined(SONAME_LIBXCOMPOSITE) */
489 /***********************************************************************
490 * X11DRV process initialisation routine
492 static BOOL process_attach(void)
494 Display *display;
496 setup_options();
498 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
500 /* Open display */
502 if (!(display = XOpenDisplay( NULL ))) return FALSE;
504 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
505 screen = DefaultScreenOfDisplay( display );
506 visual = DefaultVisual( display, DefaultScreen(display) );
507 root_window = DefaultRootWindow( display );
508 gdi_display = display;
509 old_error_handler = XSetErrorHandler( error_handler );
511 /* Initialize screen depth */
513 if (screen_depth) /* depth specified */
515 int depth_count, i;
516 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
517 for (i = 0; i < depth_count; i++)
518 if (depth_list[i] == screen_depth) break;
519 XFree( depth_list );
520 if (i >= depth_count)
522 WARN( "invalid depth %d, using default\n", screen_depth );
523 screen_depth = 0;
526 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
527 screen_bpp = depth_to_bpp( screen_depth );
529 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
531 if (TRACE_ON(synchronous)) XSynchronize( display, True );
533 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
534 X11DRV_Settings_Init();
536 #ifdef SONAME_LIBXXF86VM
537 /* initialize XVidMode */
538 X11DRV_XF86VM_Init();
539 #endif
540 #ifdef SONAME_LIBXRANDR
541 /* initialize XRandR */
542 X11DRV_XRandR_Init();
543 #endif
544 #ifdef SONAME_LIBXCOMPOSITE
545 X11DRV_XComposite_Init();
546 #endif
548 #ifdef HAVE_XKB
549 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
550 #endif
551 X11DRV_InitKeyboard( gdi_display );
552 X11DRV_InitClipboard();
553 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
555 return TRUE;
559 /***********************************************************************
560 * X11DRV thread termination routine
562 static void thread_detach(void)
564 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
566 if (data)
568 X11DRV_ResetSelectionOwner();
569 wine_tsx11_lock();
570 if (data->xim) XCloseIM( data->xim );
571 if (data->font_set) XFreeFontSet( data->display, data->font_set );
572 XCloseDisplay( data->display );
573 wine_tsx11_unlock();
574 HeapFree( GetProcessHeap(), 0, data );
579 /***********************************************************************
580 * X11DRV process termination routine
582 static void process_detach(void)
584 #ifdef SONAME_LIBXXF86VM
585 /* cleanup XVidMode */
586 X11DRV_XF86VM_Cleanup();
587 #endif
588 if(using_client_side_fonts)
589 X11DRV_XRender_Finalize();
591 /* cleanup GDI */
592 X11DRV_GDI_Finalize();
593 X11DRV_OpenGL_Cleanup();
595 IME_UnregisterClasses();
596 DeleteCriticalSection( &X11DRV_CritSection );
597 TlsFree( thread_data_tls_index );
601 /* store the display fd into the message queue */
602 static void set_queue_display_fd( Display *display )
604 HANDLE handle;
605 int ret;
607 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
609 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
610 ExitProcess(1);
612 SERVER_START_REQ( set_queue_fd )
614 req->handle = wine_server_obj_handle( handle );
615 ret = wine_server_call( req );
617 SERVER_END_REQ;
618 if (ret)
620 MESSAGE( "x11drv: Can't store handle for display fd\n" );
621 ExitProcess(1);
623 CloseHandle( handle );
627 /***********************************************************************
628 * X11DRV thread initialisation routine
630 struct x11drv_thread_data *x11drv_init_thread_data(void)
632 struct x11drv_thread_data *data = x11drv_thread_data();
634 if (data) return data;
636 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
638 ERR( "could not create data\n" );
639 ExitProcess(1);
641 wine_tsx11_lock();
642 if (!(data->display = XOpenDisplay(NULL)))
644 wine_tsx11_unlock();
645 MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
646 MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
647 ExitProcess(1);
650 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
652 #ifdef HAVE_XKB
653 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
654 XkbSetDetectableAutoRepeat( data->display, True, NULL );
655 #endif
657 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
658 wine_tsx11_unlock();
660 set_queue_display_fd( data->display );
661 TlsSetValue( thread_data_tls_index, data );
663 if (use_xim) X11DRV_SetupXIM();
664 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 x11drv_module = hinst;
681 ret = process_attach();
682 break;
683 case DLL_THREAD_DETACH:
684 thread_detach();
685 break;
686 case DLL_PROCESS_DETACH:
687 process_detach();
688 break;
690 return ret;
693 /***********************************************************************
694 * GetScreenSaveActive (X11DRV.@)
696 * Returns the active status of the screen saver
698 BOOL CDECL X11DRV_GetScreenSaveActive(void)
700 int timeout, temp;
701 wine_tsx11_lock();
702 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
703 wine_tsx11_unlock();
704 return timeout != 0;
707 /***********************************************************************
708 * SetScreenSaveActive (X11DRV.@)
710 * Activate/Deactivate the screen saver
712 void CDECL X11DRV_SetScreenSaveActive(BOOL bActivate)
714 int timeout, interval, prefer_blanking, allow_exposures;
715 static int last_timeout = 15 * 60;
717 wine_tsx11_lock();
718 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
719 &allow_exposures);
720 if (timeout) last_timeout = timeout;
722 timeout = bActivate ? last_timeout : 0;
723 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
724 allow_exposures);
725 wine_tsx11_unlock();