1 /*
2 * X11DRV initialization code
3 *
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2000 Alexandre Julliard
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "config.h"
23 #include "wine/port.h"
24
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
44
45 #include "windef.h"
46 #include "winbase.h"
47 #include "winreg.h"
48
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"
56
57 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
58 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
59 WINE_DECLARE_DEBUG_CHANNEL(winediag);
60
61 static CRITICAL_SECTION X11DRV_CritSection;
62 static CRITICAL_SECTION_DEBUG critsect_debug =
63 {
64 0, 0, &X11DRV_CritSection,
65 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
66 0, 0, { (DWORD_PTR)(__FILE__ ": X11DRV_CritSection") }
67 };
68 static CRITICAL_SECTION X11DRV_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 };
69
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 managed_mode = 1;
87 int decorated_mode = 1;
88 int private_color_map = 0;
89 int primary_monitor = 0;
90 int client_side_with_core = 1;
91 int client_side_with_render = 1;
92 int client_side_antialias_with_core = 1;
93 int client_side_antialias_with_render = 1;
94 int copy_default_colors = 128;
95 int alloc_system_colors = 256;
96 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
97 int xrender_error_base = 0;
98 HMODULE x11drv_module = 0;
99
100 static x11drv_error_callback err_callback; /* current callback for error */
101 static Display *err_callback_display; /* display callback is set for */
102 static void *err_callback_arg; /* error callback argument */
103 static int err_callback_result; /* error callback result */
104 static unsigned long err_serial; /* serial number of first request */
105 static int (*old_error_handler)( Display *, XErrorEvent * );
106 static int use_xim = 1;
107 static char input_style[20];
108
109 #define IS_OPTION_TRUE(ch) \
110 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
111 #define IS_OPTION_FALSE(ch) \
112 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '')
113
114 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
115
116 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
117 {
118 "CLIPBOARD",
119 "COMPOUND_TEXT",
120 "INCR",
121 "MULTIPLE",
122 "SELECTION_DATA",
123 "TARGETS",
124 "TEXT",
125 "UTF8_STRING",
126 "RAW_ASCENT",
127 "RAW_DESCENT",
128 "RAW_CAP_HEIGHT",
129 "WM_PROTOCOLS",
130 "WM_DELETE_WINDOW",
131 "WM_STATE",
132 "WM_TAKE_FOCUS",
133 "DndProtocol",
134 "DndSelection",
135 "_ICC_PROFILE",
136 "_MOTIF_WM_HINTS",
137 "_NET_STARTUP_INFO_BEGIN",
138 "_NET_STARTUP_INFO",
139 "_NET_SUPPORTED",
140 "_NET_SYSTEM_TRAY_OPCODE",
141 "_NET_SYSTEM_TRAY_S0",
142 "_NET_WM_ICON",
143 "_NET_WM_MOVERESIZE",
144 "_NET_WM_NAME",
145 "_NET_WM_PID",
146 "_NET_WM_PING",
147 "_NET_WM_STATE",
148 "_NET_WM_STATE_ABOVE",
149 "_NET_WM_STATE_FULLSCREEN",
150 "_NET_WM_STATE_MAXIMIZED_HORZ",
151 "_NET_WM_STATE_MAXIMIZED_VERT",
152 "_NET_WM_STATE_SKIP_PAGER",
153 "_NET_WM_STATE_SKIP_TASKBAR",
154 "_NET_WM_USER_TIME",
155 "_NET_WM_USER_TIME_WINDOW",
156 "_NET_WM_WINDOW_OPACITY",
157 "_NET_WM_WINDOW_TYPE",
158 "_NET_WM_WINDOW_TYPE_DIALOG",
159 "_NET_WM_WINDOW_TYPE_NORMAL",
160 "_NET_WM_WINDOW_TYPE_UTILITY",
161 "_NET_WORKAREA",
162 "_XEMBED_INFO",
163 "XdndAware",
164 "XdndEnter",
165 "XdndPosition",
166 "XdndStatus",
167 "XdndLeave",
168 "XdndFinished",
169 "XdndDrop",
170 "XdndActionCopy",
171 "XdndActionMove",
172 "XdndActionLink",
173 "XdndActionAsk",
174 "XdndActionPrivate",
175 "XdndSelection",
176 "XdndTarget",
177 "XdndTypeList",
178 "HTML Format",
179 "WCF_DIB",
180 "image/gif",
181 "image/jpeg",
182 "image/png",
183 "text/html",
184 "text/plain",
185 "text/rtf",
186 "text/richtext",
187 "text/uri-list"
188 };
189
190 /***********************************************************************
191 * ignore_error
192 *
193 * Check if the X error is one we can ignore.
194 */
195 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
196 {
197 if (event->request_code == X_SetInputFocus &&
198 (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
199
200 /* ignore a number of errors on gdi display caused by creating/destroying windows */
201 if (display == gdi_display)
202 {
203 if (event->error_code == BadDrawable ||
204 event->error_code == BadGC ||
205 event->error_code == BadWindow)
206 return TRUE;
207 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
208 if (xrender_error_base) /* check for XRender errors */
209 {
210 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
211 }
212 #endif
213 }
214 return FALSE;
215 }
216
217
218 /***********************************************************************
219 * X11DRV_expect_error
220 *
221 * Setup a callback function that will be called on an X error. The
222 * callback must return non-zero if the error is the one it expected.
223 * This function acquires the x11 lock; X11DRV_check_error must be
224 * called in all cases to release it.
225 */
226 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
227 {
228 wine_tsx11_lock();
229 err_callback = callback;
230 err_callback_display = display;
231 err_callback_arg = arg;
232 err_callback_result = 0;
233 err_serial = NextRequest(display);
234 }
235
236
237 /***********************************************************************
238 * X11DRV_check_error
239 *
240 * Check if an expected X11 error occurred; return non-zero if yes.
241 * Also release the x11 lock obtained in X11DRV_expect_error.
242 * The caller is responsible for calling XSync first if necessary.
243 */
244 int X11DRV_check_error(void)
245 {
246 int ret;
247 err_callback = NULL;
248 ret = err_callback_result;
249 wine_tsx11_unlock();
250 return ret;
251 }
252
253
254 /***********************************************************************
255 * error_handler
256 */
257 static int error_handler( Display *display, XErrorEvent *error_evt )
258 {
259 if (err_callback && display == err_callback_display &&
260 (long)(error_evt->serial - err_serial) >= 0)
261 {
262 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
263 {
264 TRACE( "got expected error %d req %d\n",
265 error_evt->error_code, error_evt->request_code );
266 return 0;
267 }
268 }
269 if (ignore_error( display, error_evt ))
270 {
271 TRACE( "got ignored error %d req %d\n",
272 error_evt->error_code, error_evt->request_code );
273 return 0;
274 }
275 if (TRACE_ON(synchronous))
276 {
277 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
278 error_evt->serial, error_evt->request_code );
279 DebugBreak(); /* force an entry in the debugger */
280 }
281 old_error_handler( display, error_evt );
282 return 0;
283 }
284
285 /***********************************************************************
286 * wine_tsx11_lock (X11DRV.@)
287 */
288 void CDECL wine_tsx11_lock(void)
289 {
290 EnterCriticalSection( &X11DRV_CritSection );
291 }
292
293 /***********************************************************************
294 * wine_tsx11_unlock (X11DRV.@)
295 */
296 void CDECL wine_tsx11_unlock(void)
297 {
298 LeaveCriticalSection( &X11DRV_CritSection );
299 }
300
301
302 /***********************************************************************
303 * depth_to_bpp
304 *
305 * Convert X11-reported depth to the BPP value that Windows apps expect to see.
306 */
307 unsigned int depth_to_bpp( unsigned int depth )
308 {
309 switch (depth)
310 {
311 case 1:
312 case 8:
313 return depth;
314 case 15:
315 case 16:
316 return 16;
317 case 24:
318 /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run
319 * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference
320 * for windowing, but gl applications can get visuals with alpha channels. So we
321 * should check the framebuffer and/or opengl formats available to find out what the
322 * framebuffer actually does
323 */
324 case 32:
325 return 32;
326 default:
327 FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth );
328 return depth;
329 }
330 }
331
332
333 /***********************************************************************
334 * get_config_key
335 *
336 * Get a config key from either the app-specific or the default config
337 */
338 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
339 char *buffer, DWORD size )
340 {
341 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
342 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
343 return ERROR_FILE_NOT_FOUND;
344 }
345
346
347 /***********************************************************************
348 * setup_options
349 *
350 * Setup the x11drv options.
351 */
352 static void setup_options(void)
353 {
354 char buffer[MAX_PATH+16];
355 HKEY hkey, appkey = 0;
356 DWORD len;
357
358 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
359 if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
360
361 /* open the app-specific key */
362
363 len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
364 if (len && len < MAX_PATH)
365 {
366 HKEY tmpkey;
367 char *p, *appname = buffer;
368 if ((p = strrchr( appname, '/' ))) appname = p + 1;
369 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
370 strcat( appname, "\\X11 Driver" );
371 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
372 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
373 {
374 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
375 RegCloseKey( tmpkey );
376 }
377 }
378
379 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
380 managed_mode = IS_OPTION_TRUE( buffer[0] );
381
382 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
383 decorated_mode = IS_OPTION_TRUE( buffer[0] );
384
385 if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
386 dxgrab = IS_OPTION_TRUE( buffer[0] );
387
388 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
389 usexvidmode = IS_OPTION_TRUE( buffer[0] );
390
391 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
392 usexrandr = IS_OPTION_TRUE( buffer[0] );
393
394 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
395 use_take_focus = IS_OPTION_TRUE( buffer[0] );
396
397 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
398 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
399
400 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
401 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
402
403 screen_depth = 0;
404 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
405 screen_depth = atoi(buffer);
406
407 if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
408 client_side_with_core = IS_OPTION_TRUE( buffer[0] );
409
410 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
411 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
412
413 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
414 client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
415
416 if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
417 client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
418
419 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
420 use_xim = IS_OPTION_TRUE( buffer[0] );
421
422 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
423 private_color_map = IS_OPTION_TRUE( buffer[0] );
424
425 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
426 primary_monitor = atoi( buffer );
427
428 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
429 copy_default_colors = atoi(buffer);
430
431 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
432 alloc_system_colors = atoi(buffer);
433
434 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
435
436 if (appkey) RegCloseKey( appkey );
437 if (hkey) RegCloseKey( hkey );
438 }
439
440 #ifdef SONAME_LIBXCOMPOSITE
441
442 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
443 MAKE_FUNCPTR(XCompositeQueryExtension)
444 MAKE_FUNCPTR(XCompositeQueryVersion)
445 MAKE_FUNCPTR(XCompositeVersion)
446 MAKE_FUNCPTR(XCompositeRedirectWindow)
447 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
448 MAKE_FUNCPTR(XCompositeUnredirectWindow)
449 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
450 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
451 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
452 #undef MAKE_FUNCPTR
453
454 static int xcomp_event_base;
455 static int xcomp_error_base;
456
457 static void X11DRV_XComposite_Init(void)
458 {
459 void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
460 if (!xcomposite_handle)
461 {
462 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
463 usexcomposite = 0;
464 return;
465 }
466
467 #define LOAD_FUNCPTR(f) \
468 if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
469 goto sym_not_found;
470 LOAD_FUNCPTR(XCompositeQueryExtension)
471 LOAD_FUNCPTR(XCompositeQueryVersion)
472 LOAD_FUNCPTR(XCompositeVersion)
473 LOAD_FUNCPTR(XCompositeRedirectWindow)
474 LOAD_FUNCPTR(XCompositeRedirectSubwindows)
475 LOAD_FUNCPTR(XCompositeUnredirectWindow)
476 LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
477 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
478 LOAD_FUNCPTR(XCompositeNameWindowPixmap)
479 #undef LOAD_FUNCPTR
480
481 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
482 &xcomp_error_base)) {
483 TRACE("XComposite extension could not be queried; disabled\n");
484 wine_dlclose(xcomposite_handle, NULL, 0);
485 xcomposite_handle = NULL;
486 usexcomposite = 0;
487 return;
488 }
489 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
490 return;
491
492 sym_not_found:
493 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
494 wine_dlclose(xcomposite_handle, NULL, 0);
495 xcomposite_handle = NULL;
496 usexcomposite = 0;
497 }
498 #endif /* defined(SONAME_LIBXCOMPOSITE) */
499
500
501 /***********************************************************************
502 * X11DRV process initialisation routine
503 */
504 static BOOL process_attach(void)
505 {
506 Display *display;
507
508 setup_options();
509
510 if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
511
512 /* Open display */
513
514 if (!(display = XOpenDisplay( NULL ))) return FALSE;
515
516 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
517 screen = DefaultScreenOfDisplay( display );
518 visual = DefaultVisual( display, DefaultScreen(display) );
519 root_window = DefaultRootWindow( display );
520 gdi_display = display;
521 old_error_handler = XSetErrorHandler( error_handler );
522
523 /* Initialize screen depth */
524
525 if (screen_depth) /* depth specified */
526 {
527 int depth_count, i;
528 int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
529 for (i = 0; i < depth_count; i++)
530 if (depth_list[i] == screen_depth) break;
531 XFree( depth_list );
532 if (i >= depth_count)
533 {
534 WARN( "invalid depth %d, using default\n", screen_depth );
535 screen_depth = 0;
536 }
537 }
538 if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
539 screen_bpp = depth_to_bpp( screen_depth );
540
541 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
542
543 if (TRACE_ON(synchronous)) XSynchronize( display, True );
544
545 xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
546 X11DRV_Settings_Init();
547
548 #ifdef SONAME_LIBXXF86VM
549 /* initialize XVidMode */
550 X11DRV_XF86VM_Init();
551 #endif
552 #ifdef SONAME_LIBXRANDR
553 /* initialize XRandR */
554 X11DRV_XRandR_Init();
555 #endif
556 #ifdef SONAME_LIBXCOMPOSITE
557 X11DRV_XComposite_Init();
558 #endif
559
560 #ifdef HAVE_XKB
561 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
562 #endif
563 X11DRV_InitKeyboard( gdi_display );
564 X11DRV_InitClipboard();
565 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
566
567 return TRUE;
568 }
569
570
571 /***********************************************************************
572 * X11DRV thread termination routine
573 */
574 static void thread_detach(void)
575 {
576 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
577
578 if (data)
579 {
580 X11DRV_ResetSelectionOwner();
581 wine_tsx11_lock();
582 if (data->xim) XCloseIM( data->xim );
583 if (data->font_set) XFreeFontSet( data->display, data->font_set );
584 XCloseDisplay( data->display );
585 wine_tsx11_unlock();
586 HeapFree( GetProcessHeap(), 0, data );
587 }
588 }
589
590
591 /***********************************************************************
592 * X11DRV process termination routine
593 */
594 static void process_detach(void)
595 {
596 X11DRV_Clipboard_Cleanup();
597 #ifdef SONAME_LIBXXF86VM
598 /* cleanup XVidMode */
599 X11DRV_XF86VM_Cleanup();
600 #endif
601 if(using_client_side_fonts)
602 X11DRV_XRender_Finalize();
603
604 /* cleanup GDI */
605 X11DRV_GDI_Finalize();
606 X11DRV_OpenGL_Cleanup();
607
608 IME_UnregisterClasses();
609 DeleteCriticalSection( &X11DRV_CritSection );
610 TlsFree( thread_data_tls_index );
611 }
612
613
614 /* store the display fd into the message queue */
615 static void set_queue_display_fd( Display *display )
616 {
617 HANDLE handle;
618 int ret;
619
620 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
621 {
622 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
623 ExitProcess(1);
624 }
625 SERVER_START_REQ( set_queue_fd )
626 {
627 req->handle = wine_server_obj_handle( handle );
628 ret = wine_server_call( req );
629 }
630 SERVER_END_REQ;
631 if (ret)
632 {
633 MESSAGE( "x11drv: Can't store handle for display fd\n" );
634 ExitProcess(1);
635 }
636 CloseHandle( handle );
637 }
638
639
640 /***********************************************************************
641 * X11DRV thread initialisation routine
642 */
643 struct x11drv_thread_data *x11drv_init_thread_data(void)
644 {
645 struct x11drv_thread_data *data = x11drv_thread_data();
646
647 if (data) return data;
648
649 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
650 {
651 ERR( "could not create data\n" );
652 ExitProcess(1);
653 }
654 wine_tsx11_lock();
655 if (!(data->display = XOpenDisplay(NULL)))
656 {
657 wine_tsx11_unlock();
658 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));
659 ExitProcess(1);
660 }
661
662 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
663
664 #ifdef HAVE_XKB
665 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
666 XkbSetDetectableAutoRepeat( data->display, True, NULL );
667 #endif
668
669 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
670 wine_tsx11_unlock();
671
672 set_queue_display_fd( data->display );
673 TlsSetValue( thread_data_tls_index, data );
674
675 if (use_xim) X11DRV_SetupXIM();
676
677 return data;
678 }
679
680
681 /***********************************************************************
682 * X11DRV initialisation routine
683 */
684 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
685 {
686 BOOL ret = TRUE;
687
688 switch(reason)
689 {
690 case DLL_PROCESS_ATTACH:
691 x11drv_module = hinst;
692 ret = process_attach();
693 break;
694 case DLL_THREAD_DETACH:
695 thread_detach();
696 break;
697 case DLL_PROCESS_DETACH:
698 process_detach();
699 break;
700 }
701 return ret;
702 }
703
704 /***********************************************************************
705 * GetScreenSaveActive (X11DRV.@)
706 *
707 * Returns the active status of the screen saver
708 */
709 BOOL CDECL X11DRV_GetScreenSaveActive(void)
710 {
711 int timeout, temp;
712 wine_tsx11_lock();
713 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
714 wine_tsx11_unlock();
715 return timeout != 0;
716 }
717
718 /***********************************************************************
719 * SetScreenSaveActive (X11DRV.@)
720 *
721 * Activate/Deactivate the screen saver
722 */
723 void CDECL X11DRV_SetScreenSaveActive(BOOL bActivate)
724 {
725 int timeout, interval, prefer_blanking, allow_exposures;
726 static int last_timeout = 15 * 60;
727
728 wine_tsx11_lock();
729 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
730 &allow_exposures);
731 if (timeout) last_timeout = timeout;
732
733 timeout = bActivate ? last_timeout : 0;
734 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
735 allow_exposures);
736 wine_tsx11_unlock();
737 }
738
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.