winex11: Recreate the graphics context when setting the drawable.
[wine] / dlls / winex11.drv / x11drv_main.c
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 "xcomposite.h"
51 #include "wine/server.h"
52 #include "wine/debug.h"
53 #include "wine/library.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
56 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
57 WINE_DECLARE_DEBUG_CHANNEL(winediag);
58
59 XVisualInfo default_visual = { 0 };
60 Colormap default_colormap = None;
61 XPixmapFormatValues **pixmap_formats;
62 unsigned int screen_width;
63 unsigned int screen_height;
64 unsigned int screen_bpp;
65 RECT virtual_screen_rect;
66 Window root_window;
67 int usexvidmode = 1;
68 int usexrandr = 1;
69 int usexcomposite = 1;
70 int use_xkb = 1;
71 int use_take_focus = 1;
72 int use_primary_selection = 0;
73 int use_system_cursors = 1;
74 int show_systray = 1;
75 int grab_pointer = 1;
76 int grab_fullscreen = 0;
77 int managed_mode = 1;
78 int decorated_mode = 1;
79 int private_color_map = 0;
80 int primary_monitor = 0;
81 int client_side_graphics = 1;
82 int client_side_with_render = 1;
83 int client_side_antialias_with_core = 1;
84 int client_side_antialias_with_render = 1;
85 int copy_default_colors = 128;
86 int alloc_system_colors = 256;
87 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
88 int xrender_error_base = 0;
89 HMODULE x11drv_module = 0;
90
91 static x11drv_error_callback err_callback;   /* current callback for error */
92 static Display *err_callback_display;        /* display callback is set for */
93 static void *err_callback_arg;               /* error callback argument */
94 static int err_callback_result;              /* error callback result */
95 static unsigned long err_serial;             /* serial number of first request */
96 static int (*old_error_handler)( Display *, XErrorEvent * );
97 static int use_xim = 1;
98 static char input_style[20];
99
100 #define IS_OPTION_TRUE(ch) \
101     ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
102 #define IS_OPTION_FALSE(ch) \
103     ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
104
105 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
106
107 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
108 {
109     "CLIPBOARD",
110     "COMPOUND_TEXT",
111     "INCR",
112     "MANAGER",
113     "MULTIPLE",
114     "SELECTION_DATA",
115     "TARGETS",
116     "TEXT",
117     "UTF8_STRING",
118     "RAW_ASCENT",
119     "RAW_DESCENT",
120     "RAW_CAP_HEIGHT",
121     "Rel X",
122     "Rel Y",
123     "WM_PROTOCOLS",
124     "WM_DELETE_WINDOW",
125     "WM_STATE",
126     "WM_TAKE_FOCUS",
127     "DndProtocol",
128     "DndSelection",
129     "_ICC_PROFILE",
130     "_MOTIF_WM_HINTS",
131     "_NET_STARTUP_INFO_BEGIN",
132     "_NET_STARTUP_INFO",
133     "_NET_SUPPORTED",
134     "_NET_SYSTEM_TRAY_OPCODE",
135     "_NET_SYSTEM_TRAY_S0",
136     "_NET_WM_ICON",
137     "_NET_WM_MOVERESIZE",
138     "_NET_WM_NAME",
139     "_NET_WM_PID",
140     "_NET_WM_PING",
141     "_NET_WM_STATE",
142     "_NET_WM_STATE_ABOVE",
143     "_NET_WM_STATE_FULLSCREEN",
144     "_NET_WM_STATE_MAXIMIZED_HORZ",
145     "_NET_WM_STATE_MAXIMIZED_VERT",
146     "_NET_WM_STATE_SKIP_PAGER",
147     "_NET_WM_STATE_SKIP_TASKBAR",
148     "_NET_WM_USER_TIME",
149     "_NET_WM_USER_TIME_WINDOW",
150     "_NET_WM_WINDOW_OPACITY",
151     "_NET_WM_WINDOW_TYPE",
152     "_NET_WM_WINDOW_TYPE_DIALOG",
153     "_NET_WM_WINDOW_TYPE_NORMAL",
154     "_NET_WM_WINDOW_TYPE_UTILITY",
155     "_NET_WORKAREA",
156     "_XEMBED",
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     "HTML Format",
174     "WCF_BITMAP",
175     "WCF_DIB",
176     "WCF_DIBV5",
177     "WCF_DIF",
178     "WCF_DSPBITMAP",
179     "WCF_DSPENHMETAFILE",
180     "WCF_DSPMETAFILEPICT",
181     "WCF_DSPTEXT",
182     "WCF_ENHMETAFILE",
183     "WCF_HDROP",
184     "WCF_LOCALE",
185     "WCF_METAFILEPICT",
186     "WCF_OEMTEXT",
187     "WCF_OWNERDISPLAY",
188     "WCF_PALETTE",
189     "WCF_PENDATA",
190     "WCF_RIFF",
191     "WCF_SYLK",
192     "WCF_TIFF",
193     "WCF_WAVE",
194     "image/bmp",
195     "image/gif",
196     "image/jpeg",
197     "image/png",
198     "text/html",
199     "text/plain",
200     "text/rtf",
201     "text/richtext",
202     "text/uri-list"
203 };
204
205 /***********************************************************************
206  *              ignore_error
207  *
208  * Check if the X error is one we can ignore.
209  */
210 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
211 {
212     if ((event->request_code == X_SetInputFocus || event->request_code == X_ChangeWindowAttributes) &&
213         (event->error_code == BadMatch || event->error_code == BadWindow)) return TRUE;
214
215     /* ignore a number of errors on gdi display caused by creating/destroying windows */
216     if (display == gdi_display)
217     {
218         if (event->error_code == BadDrawable ||
219             event->error_code == BadGC ||
220             event->error_code == BadWindow)
221             return TRUE;
222 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
223         if (xrender_error_base)  /* check for XRender errors */
224         {
225             if (event->error_code == xrender_error_base + BadPicture) return TRUE;
226         }
227 #endif
228     }
229     return FALSE;
230 }
231
232
233 /***********************************************************************
234  *              X11DRV_expect_error
235  *
236  * Setup a callback function that will be called on an X error.  The
237  * callback must return non-zero if the error is the one it expected.
238  */
239 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
240 {
241     err_callback         = callback;
242     err_callback_display = display;
243     err_callback_arg     = arg;
244     err_callback_result  = 0;
245     err_serial           = NextRequest(display);
246 }
247
248
249 /***********************************************************************
250  *              X11DRV_check_error
251  *
252  * Check if an expected X11 error occurred; return non-zero if yes.
253  * The caller is responsible for calling XSync first if necessary.
254  */
255 int X11DRV_check_error(void)
256 {
257     err_callback = NULL;
258     return err_callback_result;
259 }
260
261
262 /***********************************************************************
263  *              error_handler
264  */
265 static int error_handler( Display *display, XErrorEvent *error_evt )
266 {
267     if (err_callback && display == err_callback_display &&
268         (long)(error_evt->serial - err_serial) >= 0)
269     {
270         if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
271         {
272             TRACE( "got expected error %d req %d\n",
273                    error_evt->error_code, error_evt->request_code );
274             return 0;
275         }
276     }
277     if (ignore_error( display, error_evt ))
278     {
279         TRACE( "got ignored error %d req %d\n",
280                error_evt->error_code, error_evt->request_code );
281         return 0;
282     }
283     if (TRACE_ON(synchronous))
284     {
285         ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
286              error_evt->serial, error_evt->request_code );
287         DebugBreak();  /* force an entry in the debugger */
288     }
289     old_error_handler( display, error_evt );
290     return 0;
291 }
292
293 /***********************************************************************
294  *              init_pixmap_formats
295  */
296 static void init_pixmap_formats( Display *display )
297 {
298     int i, count, max = 32;
299     XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
300
301     for (i = 0; i < count; i++)
302     {
303         TRACE( "depth %u, bpp %u, pad %u\n",
304                formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
305         if (formats[i].depth > max) max = formats[i].depth;
306     }
307     pixmap_formats = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pixmap_formats) * (max + 1) );
308     for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
309 }
310
311
312 /***********************************************************************
313  *              get_config_key
314  *
315  * Get a config key from either the app-specific or the default config
316  */
317 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
318                                     char *buffer, DWORD size )
319 {
320     if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
321     if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
322     return ERROR_FILE_NOT_FOUND;
323 }
324
325
326 /***********************************************************************
327  *              setup_options
328  *
329  * Setup the x11drv options.
330  */
331 static void setup_options(void)
332 {
333     char buffer[MAX_PATH+16];
334     HKEY hkey, appkey = 0;
335     DWORD len;
336
337     /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
338     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
339
340     /* open the app-specific key */
341
342     len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
343     if (len && len < MAX_PATH)
344     {
345         HKEY tmpkey;
346         char *p, *appname = buffer;
347         if ((p = strrchr( appname, '/' ))) appname = p + 1;
348         if ((p = strrchr( appname, '\\' ))) appname = p + 1;
349         strcat( appname, "\\X11 Driver" );
350         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
351         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
352         {
353             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
354             RegCloseKey( tmpkey );
355         }
356     }
357
358     if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
359         managed_mode = IS_OPTION_TRUE( buffer[0] );
360
361     if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
362         decorated_mode = IS_OPTION_TRUE( buffer[0] );
363
364     if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
365         usexvidmode = IS_OPTION_TRUE( buffer[0] );
366
367     if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
368         usexrandr = IS_OPTION_TRUE( buffer[0] );
369
370     if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
371         use_take_focus = IS_OPTION_TRUE( buffer[0] );
372
373     if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
374         use_primary_selection = IS_OPTION_TRUE( buffer[0] );
375
376     if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
377         use_system_cursors = IS_OPTION_TRUE( buffer[0] );
378
379     if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
380         show_systray = IS_OPTION_TRUE( buffer[0] );
381
382     if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
383         grab_pointer = IS_OPTION_TRUE( buffer[0] );
384
385     if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
386         grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
387
388     if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
389         default_visual.depth = atoi(buffer);
390
391     if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
392         client_side_graphics = IS_OPTION_TRUE( buffer[0] );
393
394     if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
395         client_side_with_render = IS_OPTION_TRUE( buffer[0] );
396
397     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
398         client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
399
400     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
401         client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
402
403     if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
404         use_xim = IS_OPTION_TRUE( buffer[0] );
405
406     if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
407         private_color_map = IS_OPTION_TRUE( buffer[0] );
408
409     if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
410         primary_monitor = atoi( buffer );
411
412     if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
413         copy_default_colors = atoi(buffer);
414
415     if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
416         alloc_system_colors = atoi(buffer);
417
418     get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
419
420     if (appkey) RegCloseKey( appkey );
421     if (hkey) RegCloseKey( hkey );
422 }
423
424 #ifdef SONAME_LIBXCOMPOSITE
425
426 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
427 MAKE_FUNCPTR(XCompositeQueryExtension)
428 MAKE_FUNCPTR(XCompositeQueryVersion)
429 MAKE_FUNCPTR(XCompositeVersion)
430 MAKE_FUNCPTR(XCompositeRedirectWindow)
431 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
432 MAKE_FUNCPTR(XCompositeUnredirectWindow)
433 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
434 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
435 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
436 #undef MAKE_FUNCPTR
437
438 static int xcomp_event_base;
439 static int xcomp_error_base;
440
441 static void X11DRV_XComposite_Init(void)
442 {
443     void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0);
444     if (!xcomposite_handle)
445     {
446         TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
447         usexcomposite = 0;
448         return;
449     }
450
451 #define LOAD_FUNCPTR(f) \
452     if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \
453         goto sym_not_found;
454     LOAD_FUNCPTR(XCompositeQueryExtension)
455     LOAD_FUNCPTR(XCompositeQueryVersion)
456     LOAD_FUNCPTR(XCompositeVersion)
457     LOAD_FUNCPTR(XCompositeRedirectWindow)
458     LOAD_FUNCPTR(XCompositeRedirectSubwindows)
459     LOAD_FUNCPTR(XCompositeUnredirectWindow)
460     LOAD_FUNCPTR(XCompositeUnredirectSubwindows)
461     LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip)
462     LOAD_FUNCPTR(XCompositeNameWindowPixmap)
463 #undef LOAD_FUNCPTR
464
465     if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
466                                   &xcomp_error_base)) {
467         TRACE("XComposite extension could not be queried; disabled\n");
468         wine_dlclose(xcomposite_handle, NULL, 0);
469         xcomposite_handle = NULL;
470         usexcomposite = 0;
471         return;
472     }
473     TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
474     return;
475
476 sym_not_found:
477     TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
478     wine_dlclose(xcomposite_handle, NULL, 0);
479     xcomposite_handle = NULL;
480     usexcomposite = 0;
481 }
482 #endif /* defined(SONAME_LIBXCOMPOSITE) */
483
484 static void init_visuals( Display *display, int screen )
485 {
486     int count;
487     XVisualInfo *info;
488
489     default_visual.screen = screen;
490     if (default_visual.depth)  /* depth specified */
491     {
492         info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count );
493         if (info)
494         {
495             default_visual = *info;
496             XFree( info );
497         }
498         else WARN( "no visual found for depth %d\n", default_visual.depth );
499     }
500
501     if (!default_visual.visual)
502     {
503         default_visual.depth         = DefaultDepth( display, screen );
504         default_visual.visual        = DefaultVisual( display, screen );
505         default_visual.visualid      = default_visual.visual->visualid;
506         default_visual.class         = default_visual.visual->class;
507         default_visual.red_mask      = default_visual.visual->red_mask;
508         default_visual.green_mask    = default_visual.visual->green_mask;
509         default_visual.blue_mask     = default_visual.visual->blue_mask;
510         default_visual.colormap_size = default_visual.visual->map_entries;
511         default_visual.bits_per_rgb  = default_visual.visual->bits_per_rgb;
512     }
513     default_colormap = XCreateColormap( gdi_display, root_window, default_visual.visual, AllocNone );
514     TRACE( "default visual %lx class %u\n", default_visual.visualid, default_visual.class );
515 }
516
517 /***********************************************************************
518  *           X11DRV process initialisation routine
519  */
520 static BOOL process_attach(void)
521 {
522     char error[1024];
523     Display *display;
524     void *libx11 = wine_dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error) );
525
526     if (!libx11)
527     {
528         ERR( "failed to load %s: %s\n", SONAME_LIBX11, error );
529         return FALSE;
530     }
531     pXGetEventData = wine_dlsym( libx11, "XGetEventData", NULL, 0 );
532     pXFreeEventData = wine_dlsym( libx11, "XFreeEventData", NULL, 0 );
533 #ifdef SONAME_LIBXEXT
534     wine_dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0 );
535 #endif
536
537     setup_options();
538
539     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
540
541     /* Open display */
542
543     if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
544     if (!(display = XOpenDisplay( NULL ))) return FALSE;
545
546     fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
547     root_window = DefaultRootWindow( display );
548     gdi_display = display;
549     old_error_handler = XSetErrorHandler( error_handler );
550
551     init_pixmap_formats( display );
552     init_visuals( display, DefaultScreen( display ));
553     screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
554
555     XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
556
557     winContext = XUniqueContext();
558     win_data_context = XUniqueContext();
559     cursor_context = XUniqueContext();
560
561     if (TRACE_ON(synchronous)) XSynchronize( display, True );
562
563     xinerama_init( DisplayWidth( display, default_visual.screen ),
564                    DisplayHeight( display, default_visual.screen ));
565     X11DRV_Settings_Init();
566
567     /* initialize XVidMode */
568     X11DRV_XF86VM_Init();
569     /* initialize XRandR */
570     X11DRV_XRandR_Init();
571 #ifdef SONAME_LIBXCOMPOSITE
572     X11DRV_XComposite_Init();
573 #endif
574     X11DRV_XInput2_Init();
575
576 #ifdef HAVE_XKB
577     if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
578 #endif
579     X11DRV_InitKeyboard( gdi_display );
580     X11DRV_InitClipboard();
581     if (use_xim) use_xim = X11DRV_InitXIM( input_style );
582
583     return TRUE;
584 }
585
586
587 /***********************************************************************
588  *           X11DRV thread termination routine
589  */
590 static void thread_detach(void)
591 {
592     struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
593
594     if (data)
595     {
596         X11DRV_ResetSelectionOwner();
597         if (data->xim) XCloseIM( data->xim );
598         if (data->font_set) XFreeFontSet( data->display, data->font_set );
599         XCloseDisplay( data->display );
600         HeapFree( GetProcessHeap(), 0, data );
601     }
602 }
603
604
605 /* store the display fd into the message queue */
606 static void set_queue_display_fd( Display *display )
607 {
608     HANDLE handle;
609     int ret;
610
611     if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
612     {
613         MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
614         ExitProcess(1);
615     }
616     SERVER_START_REQ( set_queue_fd )
617     {
618         req->handle = wine_server_obj_handle( handle );
619         ret = wine_server_call( req );
620     }
621     SERVER_END_REQ;
622     if (ret)
623     {
624         MESSAGE( "x11drv: Can't store handle for display fd\n" );
625         ExitProcess(1);
626     }
627     CloseHandle( handle );
628 }
629
630
631 /***********************************************************************
632  *           X11DRV thread initialisation routine
633  */
634 struct x11drv_thread_data *x11drv_init_thread_data(void)
635 {
636     struct x11drv_thread_data *data = x11drv_thread_data();
637
638     if (data) return data;
639
640     if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )))
641     {
642         ERR( "could not create data\n" );
643         ExitProcess(1);
644     }
645     if (!(data->display = XOpenDisplay(NULL)))
646     {
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);
649     }
650
651     fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
652
653 #ifdef HAVE_XKB
654     if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
655         XkbSetDetectableAutoRepeat( data->display, True, NULL );
656 #endif
657
658     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
659
660     set_queue_display_fd( data->display );
661     TlsSetValue( thread_data_tls_index, data );
662
663     if (use_xim) X11DRV_SetupXIM();
664
665     return data;
666 }
667
668
669 /***********************************************************************
670  *           X11DRV initialisation routine
671  */
672 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
673 {
674     BOOL ret = TRUE;
675
676     switch(reason)
677     {
678     case DLL_PROCESS_ATTACH:
679         x11drv_module = hinst;
680         ret = process_attach();
681         break;
682     case DLL_THREAD_DETACH:
683         thread_detach();
684         break;
685     }
686     return ret;
687 }
688
689 /***********************************************************************
690  *              GetScreenSaveActive (X11DRV.@)
691  *
692  * Returns the active status of the screen saver
693  */
694 BOOL CDECL X11DRV_GetScreenSaveActive(void)
695 {
696     int timeout, temp;
697     XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
698     return timeout != 0;
699 }
700
701 /***********************************************************************
702  *              SetScreenSaveActive (X11DRV.@)
703  *
704  * Activate/Deactivate the screen saver
705  */
706 void CDECL X11DRV_SetScreenSaveActive(BOOL bActivate)
707 {
708     int timeout, interval, prefer_blanking, allow_exposures;
709     static int last_timeout = 15 * 60;
710
711     XLockDisplay( gdi_display );
712     XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
713                     &allow_exposures);
714     if (timeout) last_timeout = timeout;
715
716     timeout = bActivate ? last_timeout : 0;
717     XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
718                     allow_exposures);
719     XUnlockDisplay( gdi_display );
720 }