wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / winex11.drv / x11drv_main.c
blob606bc28e78abceac2b9930485bf3e347393e6016
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 use_system_cursors = 1;
86 int show_systray = 1;
87 int managed_mode = 1;
88 int decorated_mode = 1;
89 int private_color_map = 0;
90 int primary_monitor = 0;
91 int client_side_with_core = 1;
92 int client_side_with_render = 1;
93 int client_side_antialias_with_core = 1;
94 int client_side_antialias_with_render = 1;
95 int copy_default_colors = 128;
96 int alloc_system_colors = 256;
97 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
98 int xrender_error_base = 0;
99 HMODULE x11drv_module = 0;
101 static x11drv_error_callback err_callback; /* current callback for error */
102 static Display *err_callback_display; /* display callback is set for */
103 static void *err_callback_arg; /* error callback argument */
104 static int err_callback_result; /* error callback result */
105 static unsigned long err_serial; /* serial number of first request */
106 static int (*old_error_handler)( Display *, XErrorEvent * );
107 static int use_xim = 1;
108 static char input_style[20];
110 #define IS_OPTION_TRUE(ch) \
111 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
112 #define IS_OPTION_FALSE(ch) \
113 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
115 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
117 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
119 "CLIPBOARD",
120 "COMPOUND_TEXT",
121 "INCR",
122 "MANAGER",
123 "MULTIPLE",
124 "SELECTION_DATA",
125 "TARGETS",
126 "TEXT",
127 "UTF8_STRING",
128 "RAW_ASCENT",
129 "RAW_DESCENT",
130 "RAW_CAP_HEIGHT",
131 "WM_PROTOCOLS",
132 "WM_DELETE_WINDOW",
133 "WM_STATE",
134 "WM_TAKE_FOCUS",
135 "DndProtocol",
136 "DndSelection",
137 "_ICC_PROFILE",
138 "_MOTIF_WM_HINTS",
139 "_NET_STARTUP_INFO_BEGIN",
140 "_NET_STARTUP_INFO",
141 "_NET_SUPPORTED",
142 "_NET_SYSTEM_TRAY_OPCODE",
143 "_NET_SYSTEM_TRAY_S0",
144 "_NET_WM_ICON",
145 "_NET_WM_MOVERESIZE",
146 "_NET_WM_NAME",
147 "_NET_WM_PID",
148 "_NET_WM_PING",
149 "_NET_WM_STATE",
150 "_NET_WM_STATE_ABOVE",
151 "_NET_WM_STATE_FULLSCREEN",
152 "_NET_WM_STATE_MAXIMIZED_HORZ",
153 "_NET_WM_STATE_MAXIMIZED_VERT",
154 "_NET_WM_STATE_SKIP_PAGER",
155 "_NET_WM_STATE_SKIP_TASKBAR",
156 "_NET_WM_USER_TIME",
157 "_NET_WM_USER_TIME_WINDOW",
158 "_NET_WM_WINDOW_OPACITY",
159 "_NET_WM_WINDOW_TYPE",
160 "_NET_WM_WINDOW_TYPE_DIALOG",
161 "_NET_WM_WINDOW_TYPE_NORMAL",
162 "_NET_WM_WINDOW_TYPE_UTILITY",
163 "_NET_WORKAREA",
164 "_XEMBED",
165 "_XEMBED_INFO",
166 "XdndAware",
167 "XdndEnter",
168 "XdndPosition",
169 "XdndStatus",
170 "XdndLeave",
171 "XdndFinished",
172 "XdndDrop",
173 "XdndActionCopy",
174 "XdndActionMove",
175 "XdndActionLink",
176 "XdndActionAsk",
177 "XdndActionPrivate",
178 "XdndSelection",
179 "XdndTarget",
180 "XdndTypeList",
181 "HTML Format",
182 "WCF_BITMAP",
183 "WCF_DIB",
184 "WCF_DIBV5",
185 "WCF_DIF",
186 "WCF_DSPBITMAP",
187 "WCF_DSPENHMETAFILE",
188 "WCF_DSPMETAFILEPICT",
189 "WCF_DSPTEXT",
190 "WCF_ENHMETAFILE",
191 "WCF_HDROP",
192 "WCF_LOCALE",
193 "WCF_METAFILEPICT",
194 "WCF_OEMTEXT",
195 "WCF_OWNERDISPLAY",
196 "WCF_PALETTE",
197 "WCF_PENDATA",
198 "WCF_RIFF",
199 "WCF_SYLK",
200 "WCF_TIFF",
201 "WCF_WAVE",
202 "image/bmp",
203 "image/gif",
204 "image/jpeg",
205 "image/png",
206 "text/html",
207 "text/plain",
208 "text/rtf",
209 "text/richtext",
210 "text/uri-list"
213 /***********************************************************************
214 * ignore_error
216 * Check if the X error is one we can ignore.
218 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
220 if ((event->request_code == X_SetInputFocus || event->request_code == X_ChangeWindowAttributes) &&
221 (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
223 /* ignore a number of errors on gdi display caused by creating/destroying windows */
224 if (display == gdi_display)
226 if (event->error_code == BadDrawable ||
227 event->error_code == BadGC ||
228 event->error_code == BadWindow)
229 return TRUE;
230 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
231 if (xrender_error_base) /* check for XRender errors */
233 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
235 #endif
237 return FALSE;
241 /***********************************************************************
242 * X11DRV_expect_error
244 * Setup a callback function that will be called on an X error. The
245 * callback must return non-zero if the error is the one it expected.
246 * This function acquires the x11 lock; X11DRV_check_error must be
247 * called in all cases to release it.
249 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
251 wine_tsx11_lock();
252 err_callback = callback;
253 err_callback_display = display;
254 err_callback_arg = arg;
255 err_callback_result = 0;
256 err_serial = NextRequest(display);
260 /***********************************************************************
261 * X11DRV_check_error
263 * Check if an expected X11 error occurred; return non-zero if yes.
264 * Also release the x11 lock obtained in X11DRV_expect_error.
265 * The caller is responsible for calling XSync first if necessary.
267 int X11DRV_check_error(void)
269 int ret;
270 err_callback = NULL;
271 ret = err_callback_result;
272 wine_tsx11_unlock();
273 return ret;
277 /***********************************************************************
278 * error_handler
280 static int error_handler( Display *display, XErrorEvent *error_evt )
282 if (err_callback && display == err_callback_display &&
283 (long)(error_evt->serial - err_serial) >= 0)
285 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
287 TRACE( "got expected error %d req %d\n",
288 error_evt->error_code, error_evt->request_code );
289 return 0;
292 if (ignore_error( display, error_evt ))
294 TRACE( "got ignored error %d req %d\n",
295 error_evt->error_code, error_evt->request_code );
296 return 0;
298 if (TRACE_ON(synchronous))
300 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
301 error_evt->serial, error_evt->request_code );
302 DebugBreak(); /* force an entry in the debugger */
304 old_error_handler( display, error_evt );
305 return 0;
308 /***********************************************************************
309 * wine_tsx11_lock (X11DRV.@)
311 void CDECL wine_tsx11_lock(void)
313 EnterCriticalSection( &X11DRV_CritSection );
316 /***********************************************************************
317 * wine_tsx11_unlock (X11DRV.@)
319 void CDECL wine_tsx11_unlock(void)
321 LeaveCriticalSection( &X11DRV_CritSection );
325 /***********************************************************************
326 * depth_to_bpp
328 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
330 unsigned int depth_to_bpp( unsigned int depth )
332 switch (depth)
334 case 1:
335 case 8:
336 return depth;
337 case 15:
338 case 16:
339 return 16;
340 case 24:
341 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
342 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
343 * for windowing, but gl applications can get visuals with alpha channels. So we
344 * should check the framebuffer and/or opengl formats available to find out what the
345 * framebuffer actually does
347 case 32:
348 return 32;
349 default:
350 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
351 return depth;
356 /***********************************************************************
357 * get_config_key
359 * Get a config key from either the app-specific or the default config
361 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
362 char *buffer, DWORD size )
364 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
365 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
366 return ERROR_FILE_NOT_FOUND;
370 /***********************************************************************
371 * setup_options
373 * Setup the x11drv options.
375 static void setup_options(void)
377 char buffer[MAX_PATH+16];
378 HKEY hkey, appkey = 0;
379 DWORD len;
381 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
382 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
384 /* open the app-specific key */
386 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
387 if (len && len < MAX_PATH)
389 HKEY tmpkey;
390 char *p, *appname = buffer;
391 if ((p = strrchr( appname, '/' ))) appname = p + 1;
392 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
393 strcat( appname, "\\X11 Driver" );
394 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
395 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
397 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
398 RegCloseKey( tmpkey );
402 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
403 managed_mode = IS_OPTION_TRUE( buffer[0] );
405 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
406 decorated_mode = IS_OPTION_TRUE( buffer[0] );
408 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
409 dxgrab = IS_OPTION_TRUE( buffer[0] );
411 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
412 usexvidmode = IS_OPTION_TRUE( buffer[0] );
414 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
415 usexrandr = IS_OPTION_TRUE( buffer[0] );
417 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
418 use_take_focus = IS_OPTION_TRUE( buffer[0] );
420 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
421 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
423 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
424 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
426 if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
427 show_systray = IS_OPTION_TRUE( buffer[0] );
429 screen_depth = 0;
430 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
431 screen_depth = atoi(buffer);
433 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
434 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
436 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
437 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
439 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
440 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
442 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
443 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
445 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
446 use_xim = IS_OPTION_TRUE( buffer[0] );
448 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
449 private_color_map = IS_OPTION_TRUE( buffer[0] );
451 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
452 primary_monitor = atoi( buffer );
454 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
455 copy_default_colors = atoi(buffer);
457 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
458 alloc_system_colors = atoi(buffer);
460 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
462 if (appkey) RegCloseKey( appkey );
463 if (hkey) RegCloseKey( hkey );
466 #ifdef SONAME_LIBXCOMPOSITE
468 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
469 MAKE_FUNCPTR(XCompositeQueryExtension)
470 MAKE_FUNCPTR(XCompositeQueryVersion)
471 MAKE_FUNCPTR(XCompositeVersion)
472 MAKE_FUNCPTR(XCompositeRedirectWindow)
473 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
474 MAKE_FUNCPTR(XCompositeUnredirectWindow)
475 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
476 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
477 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
478 #undef MAKE_FUNCPTR
480 static int xcomp_event_base;
481 static int xcomp_error_base;
483 static void X11DRV_XComposite_Init(void)
485 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
486 if (!xcomposite_handle)
488 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
489 usexcomposite = 0;
490 return;
493 #define LOAD_FUNCPTR(f) \
494 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
495 goto sym_not_found;
496 LOAD_FUNCPTR(XCompositeQueryExtension)
497 LOAD_FUNCPTR(XCompositeQueryVersion)
498 LOAD_FUNCPTR(XCompositeVersion)
499 LOAD_FUNCPTR(XCompositeRedirectWindow)
500 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
501 LOAD_FUNCPTR(XCompositeUnredirectWindow)
502 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
503 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
504 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
505 #undef LOAD_FUNCPTR
507 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
508 &xcomp_error_base)) {
509 TRACE("XComposite extension could not be queried; disabled\n");
510 wine_dlclose(xcomposite_handle, NULL, 0);
511 xcomposite_handle = NULL;
512 usexcomposite = 0;
513 return;
515 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
516 return;
518 sym_not_found:
519 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
520 wine_dlclose(xcomposite_handle, NULL, 0);
521 xcomposite_handle = NULL;
522 usexcomposite = 0;
524 #endif /* defined(SONAME_LIBXCOMPOSITE) */
527 /***********************************************************************
528 * X11DRV process initialisation routine
530 static BOOL process_attach(void)
532 Display *display;
534 setup_options();
536 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
538 /* Open display */
540 if (!(display = XOpenDisplay( NULL ))) return FALSE;
542 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
543 screen = DefaultScreenOfDisplay( display );
544 visual = DefaultVisual( display, DefaultScreen(display) );
545 root_window = DefaultRootWindow( display );
546 gdi_display = display;
547 old_error_handler = XSetErrorHandler( error_handler );
549 /* Initialize screen depth */
551 if (screen_depth) /* depth specified */
553 int depth_count, i;
554 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
555 for (i = 0; i < depth_count; i++)
556 if (depth_list[i] == screen_depth) break;
557 XFree( depth_list );
558 if (i >= depth_count)
560 WARN( "invalid depth %d, using default\n", screen_depth );
561 screen_depth = 0;
564 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
565 screen_bpp = depth_to_bpp( screen_depth );
567 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
569 if (TRACE_ON(synchronous)) XSynchronize( display, True );
571 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
572 X11DRV_Settings_Init();
574 #ifdef SONAME_LIBXXF86VM
575 /* initialize XVidMode */
576 X11DRV_XF86VM_Init();
577 #endif
578 #ifdef SONAME_LIBXRANDR
579 /* initialize XRandR */
580 X11DRV_XRandR_Init();
581 #endif
582 #ifdef SONAME_LIBXCOMPOSITE
583 X11DRV_XComposite_Init();
584 #endif
586 #ifdef HAVE_XKB
587 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
588 #endif
589 X11DRV_InitKeyboard( gdi_display );
590 X11DRV_InitClipboard();
591 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
593 return TRUE;
597 /***********************************************************************
598 * X11DRV thread termination routine
600 static void thread_detach(void)
602 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
604 if (data)
606 X11DRV_ResetSelectionOwner();
607 wine_tsx11_lock();
608 if (data->xim) XCloseIM( data->xim );
609 if (data->font_set) XFreeFontSet( data->display, data->font_set );
610 XCloseDisplay( data->display );
611 wine_tsx11_unlock();
612 HeapFree( GetProcessHeap(), 0, data );
617 /***********************************************************************
618 * X11DRV process termination routine
620 static void process_detach(void)
622 X11DRV_Clipboard_Cleanup();
623 #ifdef SONAME_LIBXXF86VM
624 /* cleanup XVidMode */
625 X11DRV_XF86VM_Cleanup();
626 #endif
627 if(using_client_side_fonts)
628 X11DRV_XRender_Finalize();
630 /* cleanup GDI */
631 X11DRV_GDI_Finalize();
632 X11DRV_OpenGL_Cleanup();
634 IME_UnregisterClasses();
635 DeleteCriticalSection( &X11DRV_CritSection );
636 TlsFree( thread_data_tls_index );
640 /* store the display fd into the message queue */
641 static void set_queue_display_fd( Display *display )
643 HANDLE handle;
644 int ret;
646 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
648 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
649 ExitProcess(1);
651 SERVER_START_REQ( set_queue_fd )
653 req->handle = wine_server_obj_handle( handle );
654 ret = wine_server_call( req );
656 SERVER_END_REQ;
657 if (ret)
659 MESSAGE( "x11drv: Can't store handle for display fd\n" );
660 ExitProcess(1);
662 CloseHandle( handle );
666 /***********************************************************************
667 * X11DRV thread initialisation routine
669 struct x11drv_thread_data *x11drv_init_thread_data(void)
671 struct x11drv_thread_data *data = x11drv_thread_data();
673 if (data) return data;
675 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
677 ERR( "could not create data\n" );
678 ExitProcess(1);
680 wine_tsx11_lock();
681 if (!(data->display = XOpenDisplay(NULL)))
683 wine_tsx11_unlock();
684 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));
685 ExitProcess(1);
688 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
690 #ifdef HAVE_XKB
691 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
692 XkbSetDetectableAutoRepeat( data->display, True, NULL );
693 #endif
695 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
696 wine_tsx11_unlock();
698 set_queue_display_fd( data->display );
699 TlsSetValue( thread_data_tls_index, data );
701 if (use_xim) X11DRV_SetupXIM();
703 return data;
707 /***********************************************************************
708 * X11DRV initialisation routine
710 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
712 BOOL ret = TRUE;
714 switch(reason)
716 case DLL_PROCESS_ATTACH:
717 x11drv_module = hinst;
718 ret = process_attach();
719 break;
720 case DLL_THREAD_DETACH:
721 thread_detach();
722 break;
723 case DLL_PROCESS_DETACH:
724 process_detach();
725 break;
727 return ret;
730 /***********************************************************************
731 * GetScreenSaveActive (X11DRV.@)
733 * Returns the active status of the screen saver
735 BOOL CDECL X11DRV_GetScreenSaveActive(void)
737 int timeout, temp;
738 wine_tsx11_lock();
739 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
740 wine_tsx11_unlock();
741 return timeout != 0;
744 /***********************************************************************
745 * SetScreenSaveActive (X11DRV.@)
747 * Activate/Deactivate the screen saver
749 void CDECL X11DRV_SetScreenSaveActive(BOOL bActivate)
751 int timeout, interval, prefer_blanking, allow_exposures;
752 static int last_timeout = 15 * 60;
754 wine_tsx11_lock();
755 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
756 &allow_exposures);
757 if (timeout) last_timeout = timeout;
759 timeout = bActivate ? last_timeout : 0;
760 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
761 allow_exposures);
762 wine_tsx11_unlock();