usp10: Add Syriac contextual shaping.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blobb07061c47d3115438b0692f9b6d8ae2ce59a20f9
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_USER_TIME",
154 "_NET_WM_USER_TIME_WINDOW",
155 "_NET_WM_WINDOW_OPACITY",
156 "_NET_WM_WINDOW_TYPE",
157 "_NET_WM_WINDOW_TYPE_DIALOG",
158 "_NET_WM_WINDOW_TYPE_NORMAL",
159 "_NET_WM_WINDOW_TYPE_UTILITY",
160 "_NET_WORKAREA",
161 "_XEMBED_INFO",
162 "XdndAware",
163 "XdndEnter",
164 "XdndPosition",
165 "XdndStatus",
166 "XdndLeave",
167 "XdndFinished",
168 "XdndDrop",
169 "XdndActionCopy",
170 "XdndActionMove",
171 "XdndActionLink",
172 "XdndActionAsk",
173 "XdndActionPrivate",
174 "XdndSelection",
175 "XdndTarget",
176 "XdndTypeList",
177 "HTML Format",
178 "WCF_DIB",
179 "image/gif",
180 "image/jpeg",
181 "image/png",
182 "text/html",
183 "text/plain",
184 "text/rtf",
185 "text/richtext",
186 "text/uri-list"
189 /***********************************************************************
190 * ignore_error
192 * Check if the X error is one we can ignore.
194 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
196 if (event->request_code == X_SetInputFocus &&
197 (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
199 /* ignore a number of errors on gdi display caused by creating/destroying windows */
200 if (display == gdi_display)
202 if (event->error_code == BadDrawable ||
203 event->error_code == BadGC ||
204 event->error_code == BadWindow)
205 return TRUE;
206 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
207 if (xrender_error_base) /* check for XRender errors */
209 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
211 #endif
213 return FALSE;
217 /***********************************************************************
218 * X11DRV_expect_error
220 * Setup a callback function that will be called on an X error. The
221 * callback must return non-zero if the error is the one it expected.
222 * This function acquires the x11 lock; X11DRV_check_error must be
223 * called in all cases to release it.
225 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
227 wine_tsx11_lock();
228 err_callback = callback;
229 err_callback_display = display;
230 err_callback_arg = arg;
231 err_callback_result = 0;
232 err_serial = NextRequest(display);
236 /***********************************************************************
237 * X11DRV_check_error
239 * Check if an expected X11 error occurred; return non-zero if yes.
240 * Also release the x11 lock obtained in X11DRV_expect_error.
241 * The caller is responsible for calling XSync first if necessary.
243 int X11DRV_check_error(void)
245 int ret;
246 err_callback = NULL;
247 ret = err_callback_result;
248 wine_tsx11_unlock();
249 return ret;
253 /***********************************************************************
254 * error_handler
256 static int error_handler( Display *display, XErrorEvent *error_evt )
258 if (err_callback && display == err_callback_display &&
259 (long)(error_evt->serial - err_serial) >= 0)
261 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
263 TRACE( "got expected error %d req %d\n",
264 error_evt->error_code, error_evt->request_code );
265 return 0;
268 if (ignore_error( display, error_evt ))
270 TRACE( "got ignored error %d req %d\n",
271 error_evt->error_code, error_evt->request_code );
272 return 0;
274 if (TRACE_ON(synchronous))
276 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
277 error_evt->serial, error_evt->request_code );
278 DebugBreak(); /* force an entry in the debugger */
280 old_error_handler( display, error_evt );
281 return 0;
284 /***********************************************************************
285 * wine_tsx11_lock (X11DRV.@)
287 void CDECL wine_tsx11_lock(void)
289 EnterCriticalSection( &X11DRV_CritSection );
292 /***********************************************************************
293 * wine_tsx11_unlock (X11DRV.@)
295 void CDECL wine_tsx11_unlock(void)
297 LeaveCriticalSection( &X11DRV_CritSection );
301 /***********************************************************************
302 * depth_to_bpp
304 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
306 unsigned int depth_to_bpp( unsigned int depth )
308 switch (depth)
310 case 1:
311 case 8:
312 return depth;
313 case 15:
314 case 16:
315 return 16;
316 case 24:
317 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
318 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
319 * for windowing, but gl applications can get visuals with alpha channels. So we
320 * should check the framebuffer and/or opengl formats available to find out what the
321 * framebuffer actually does
323 case 32:
324 return 32;
325 default:
326 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
327 return depth;
332 /***********************************************************************
333 * get_config_key
335 * Get a config key from either the app-specific or the default config
337 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
338 char *buffer, DWORD size )
340 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
341 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
342 return ERROR_FILE_NOT_FOUND;
346 /***********************************************************************
347 * setup_options
349 * Setup the x11drv options.
351 static void setup_options(void)
353 char buffer[MAX_PATH+16];
354 HKEY hkey, appkey = 0;
355 DWORD len;
357 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
358 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
360 /* open the app-specific key */
362 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
363 if (len && len < MAX_PATH)
365 HKEY tmpkey;
366 char *p, *appname = buffer;
367 if ((p = strrchr( appname, '/' ))) appname = p + 1;
368 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
369 strcat( appname, "\\X11 Driver" );
370 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
371 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
373 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
374 RegCloseKey( tmpkey );
378 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
379 managed_mode = IS_OPTION_TRUE( buffer[0] );
381 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
382 decorated_mode = IS_OPTION_TRUE( buffer[0] );
384 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
385 dxgrab = IS_OPTION_TRUE( buffer[0] );
387 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
388 usexvidmode = IS_OPTION_TRUE( buffer[0] );
390 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
391 usexrandr = IS_OPTION_TRUE( buffer[0] );
393 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
394 use_take_focus = IS_OPTION_TRUE( buffer[0] );
396 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
397 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
399 screen_depth = 0;
400 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
401 screen_depth = atoi(buffer);
403 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
404 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
406 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
407 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
409 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
410 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
412 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
413 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
415 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
416 use_xim = IS_OPTION_TRUE( buffer[0] );
418 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
419 private_color_map = IS_OPTION_TRUE( buffer[0] );
421 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
422 primary_monitor = atoi( buffer );
424 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
425 copy_default_colors = atoi(buffer);
427 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
428 alloc_system_colors = atoi(buffer);
430 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
432 if (appkey) RegCloseKey( appkey );
433 if (hkey) RegCloseKey( hkey );
436 #ifdef SONAME_LIBXCOMPOSITE
438 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
439 MAKE_FUNCPTR(XCompositeQueryExtension)
440 MAKE_FUNCPTR(XCompositeQueryVersion)
441 MAKE_FUNCPTR(XCompositeVersion)
442 MAKE_FUNCPTR(XCompositeRedirectWindow)
443 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
444 MAKE_FUNCPTR(XCompositeUnredirectWindow)
445 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
446 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
447 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
448 #undef MAKE_FUNCPTR
450 static int xcomp_event_base;
451 static int xcomp_error_base;
453 static void X11DRV_XComposite_Init(void)
455 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
456 if (!xcomposite_handle)
458 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
459 usexcomposite = 0;
460 return;
463 #define LOAD_FUNCPTR(f) \
464 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
465 goto sym_not_found;
466 LOAD_FUNCPTR(XCompositeQueryExtension)
467 LOAD_FUNCPTR(XCompositeQueryVersion)
468 LOAD_FUNCPTR(XCompositeVersion)
469 LOAD_FUNCPTR(XCompositeRedirectWindow)
470 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
471 LOAD_FUNCPTR(XCompositeUnredirectWindow)
472 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
473 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
474 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
475 #undef LOAD_FUNCPTR
477 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
478 &xcomp_error_base)) {
479 TRACE("XComposite extension could not be queried; disabled\n");
480 wine_dlclose(xcomposite_handle, NULL, 0);
481 xcomposite_handle = NULL;
482 usexcomposite = 0;
483 return;
485 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
486 return;
488 sym_not_found:
489 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
490 wine_dlclose(xcomposite_handle, NULL, 0);
491 xcomposite_handle = NULL;
492 usexcomposite = 0;
494 #endif /* defined(SONAME_LIBXCOMPOSITE) */
497 /***********************************************************************
498 * X11DRV process initialisation routine
500 static BOOL process_attach(void)
502 Display *display;
504 setup_options();
506 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
508 /* Open display */
510 if (!(display = XOpenDisplay( NULL ))) return FALSE;
512 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
513 screen = DefaultScreenOfDisplay( display );
514 visual = DefaultVisual( display, DefaultScreen(display) );
515 root_window = DefaultRootWindow( display );
516 gdi_display = display;
517 old_error_handler = XSetErrorHandler( error_handler );
519 /* Initialize screen depth */
521 if (screen_depth) /* depth specified */
523 int depth_count, i;
524 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
525 for (i = 0; i < depth_count; i++)
526 if (depth_list[i] == screen_depth) break;
527 XFree( depth_list );
528 if (i >= depth_count)
530 WARN( "invalid depth %d, using default\n", screen_depth );
531 screen_depth = 0;
534 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
535 screen_bpp = depth_to_bpp( screen_depth );
537 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
539 if (TRACE_ON(synchronous)) XSynchronize( display, True );
541 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
542 X11DRV_Settings_Init();
544 #ifdef SONAME_LIBXXF86VM
545 /* initialize XVidMode */
546 X11DRV_XF86VM_Init();
547 #endif
548 #ifdef SONAME_LIBXRANDR
549 /* initialize XRandR */
550 X11DRV_XRandR_Init();
551 #endif
552 #ifdef SONAME_LIBXCOMPOSITE
553 X11DRV_XComposite_Init();
554 #endif
556 #ifdef HAVE_XKB
557 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
558 #endif
559 X11DRV_InitKeyboard( gdi_display );
560 X11DRV_InitClipboard();
561 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
563 return TRUE;
567 /***********************************************************************
568 * X11DRV thread termination routine
570 static void thread_detach(void)
572 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
574 if (data)
576 X11DRV_ResetSelectionOwner();
577 wine_tsx11_lock();
578 if (data->xim) XCloseIM( data->xim );
579 if (data->font_set) XFreeFontSet( data->display, data->font_set );
580 XCloseDisplay( data->display );
581 wine_tsx11_unlock();
582 HeapFree( GetProcessHeap(), 0, data );
587 /***********************************************************************
588 * X11DRV process termination routine
590 static void process_detach(void)
592 X11DRV_Clipboard_Cleanup();
593 #ifdef SONAME_LIBXXF86VM
594 /* cleanup XVidMode */
595 X11DRV_XF86VM_Cleanup();
596 #endif
597 if(using_client_side_fonts)
598 X11DRV_XRender_Finalize();
600 /* cleanup GDI */
601 X11DRV_GDI_Finalize();
602 X11DRV_OpenGL_Cleanup();
604 IME_UnregisterClasses();
605 DeleteCriticalSection( &X11DRV_CritSection );
606 TlsFree( thread_data_tls_index );
610 /* store the display fd into the message queue */
611 static void set_queue_display_fd( Display *display )
613 HANDLE handle;
614 int ret;
616 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
618 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
619 ExitProcess(1);
621 SERVER_START_REQ( set_queue_fd )
623 req->handle = wine_server_obj_handle( handle );
624 ret = wine_server_call( req );
626 SERVER_END_REQ;
627 if (ret)
629 MESSAGE( "x11drv: Can't store handle for display fd\n" );
630 ExitProcess(1);
632 CloseHandle( handle );
636 /***********************************************************************
637 * X11DRV thread initialisation routine
639 struct x11drv_thread_data *x11drv_init_thread_data(void)
641 struct x11drv_thread_data *data = x11drv_thread_data();
643 if (data) return data;
645 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
647 ERR( "could not create data\n" );
648 ExitProcess(1);
650 wine_tsx11_lock();
651 if (!(data->display = XOpenDisplay(NULL)))
653 wine_tsx11_unlock();
654 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));
655 ExitProcess(1);
658 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
660 #ifdef HAVE_XKB
661 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
662 XkbSetDetectableAutoRepeat( data->display, True, NULL );
663 #endif
665 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
666 wine_tsx11_unlock();
668 set_queue_display_fd( data->display );
669 TlsSetValue( thread_data_tls_index, data );
671 if (use_xim) X11DRV_SetupXIM();
673 return data;
677 /***********************************************************************
678 * X11DRV initialisation routine
680 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
682 BOOL ret = TRUE;
684 switch(reason)
686 case DLL_PROCESS_ATTACH:
687 x11drv_module = hinst;
688 ret = process_attach();
689 break;
690 case DLL_THREAD_DETACH:
691 thread_detach();
692 break;
693 case DLL_PROCESS_DETACH:
694 process_detach();
695 break;
697 return ret;
700 /***********************************************************************
701 * GetScreenSaveActive (X11DRV.@)
703 * Returns the active status of the screen saver
705 BOOL CDECL X11DRV_GetScreenSaveActive(void)
707 int timeout, temp;
708 wine_tsx11_lock();
709 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
710 wine_tsx11_unlock();
711 return timeout != 0;
714 /***********************************************************************
715 * SetScreenSaveActive (X11DRV.@)
717 * Activate/Deactivate the screen saver
719 void CDECL X11DRV_SetScreenSaveActive(BOOL bActivate)
721 int timeout, interval, prefer_blanking, allow_exposures;
722 static int last_timeout = 15 * 60;
724 wine_tsx11_lock();
725 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
726 &allow_exposures);
727 if (timeout) last_timeout = timeout;
729 timeout = bActivate ? last_timeout : 0;
730 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
731 allow_exposures);
732 wine_tsx11_unlock();