msi: Move string loading and saving to string.c.
[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
24 #include <fcntl.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #ifdef HAVE_SYS_TIME_H
30 # include <sys/time.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
35 #include <X11/cursorfont.h>
36 #include <X11/Xlib.h>
37 #ifdef HAVE_XKB
38 #include <X11/XKBlib.h>
39 #endif
40 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
41 #include <X11/extensions/Xrender.h>
42 #endif
43
44 #include "windef.h"
45 #include "winbase.h"
46 #include "wine/winbase16.h"
47 #include "winreg.h"
48
49 #include "x11drv.h"
50 #include "xvidmode.h"
51 #include "xrandr.h"
52 #include "wine/server.h"
53 #include "wine/debug.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
56 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
57
58 static CRITICAL_SECTION X11DRV_CritSection;
59 static CRITICAL_SECTION_DEBUG critsect_debug =
60 {
61     0, 0, &X11DRV_CritSection,
62     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
63       0, 0, { (DWORD_PTR)(__FILE__ ": X11DRV_CritSection") }
64 };
65 static CRITICAL_SECTION X11DRV_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 };
66
67 Screen *screen;
68 Visual *visual;
69 unsigned int screen_width;
70 unsigned int screen_height;
71 unsigned int screen_depth;
72 RECT virtual_screen_rect;
73 Window root_window;
74 int dxgrab = 0;
75 int usexvidmode = 1;
76 int usexrandr = 1;
77 int use_xkb = 1;
78 int use_take_focus = 1;
79 int use_primary_selection = 0;
80 int managed_mode = 1;
81 int private_color_map = 0;
82 int primary_monitor = 0;
83 int client_side_with_core = 1;
84 int client_side_with_render = 1;
85 int client_side_antialias_with_core = 1;
86 int client_side_antialias_with_render = 1;
87 int copy_default_colors = 128;
88 int alloc_system_colors = 256;
89 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
90 int xrender_error_base = 0;
91
92 static x11drv_error_callback err_callback;   /* current callback for error */
93 static Display *err_callback_display;        /* display callback is set for */
94 static void *err_callback_arg;               /* error callback argument */
95 static int err_callback_result;              /* error callback result */
96 static unsigned long err_serial;             /* serial number of first request */
97 static int (*old_error_handler)( Display *, XErrorEvent * );
98 static int use_xim = 1;
99 static char input_style[20];
100
101 #define IS_OPTION_TRUE(ch) \
102     ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
103 #define IS_OPTION_FALSE(ch) \
104     ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
105
106 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
107
108 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
109 {
110     "CLIPBOARD",
111     "COMPOUND_TEXT",
112     "MULTIPLE",
113     "SELECTION_DATA",
114     "TARGETS",
115     "TEXT",
116     "UTF8_STRING",
117     "RAW_ASCENT",
118     "RAW_DESCENT",
119     "RAW_CAP_HEIGHT",
120     "WM_PROTOCOLS",
121     "WM_DELETE_WINDOW",
122     "WM_TAKE_FOCUS",
123     "KWM_DOCKWINDOW",
124     "DndProtocol",
125     "DndSelection",
126     "_MOTIF_WM_HINTS",
127     "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
128     "_NET_SYSTEM_TRAY_OPCODE",
129     "_NET_SYSTEM_TRAY_S0",
130     "_NET_WM_MOVERESIZE",
131     "_NET_WM_NAME",
132     "_NET_WM_PID",
133     "_NET_WM_PING",
134     "_NET_WM_STATE",
135     "_NET_WM_STATE_FULLSCREEN",
136     "_NET_WM_WINDOW_TYPE",
137     "_NET_WM_WINDOW_TYPE_DIALOG",
138     "_NET_WM_WINDOW_TYPE_NORMAL",
139     "_NET_WM_WINDOW_TYPE_UTILITY",
140     "_XEMBED_INFO",
141     "XdndAware",
142     "XdndEnter",
143     "XdndPosition",
144     "XdndStatus",
145     "XdndLeave",
146     "XdndFinished",
147     "XdndDrop",
148     "XdndActionCopy",
149     "XdndActionMove",
150     "XdndActionLink",
151     "XdndActionAsk",
152     "XdndActionPrivate",
153     "XdndSelection",
154     "XdndTarget",
155     "XdndTypeList",
156     "WCF_DIB",
157     "image/gif",
158     "text/html",
159     "text/plain",
160     "text/rtf",
161     "text/richtext"
162 };
163
164 /***********************************************************************
165  *              ignore_error
166  *
167  * Check if the X error is one we can ignore.
168  */
169 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
170 {
171     if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
172
173     /* ignore a number of errors on gdi display caused by creating/destroying windows */
174     if (display == gdi_display)
175     {
176         if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
177 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
178         if (xrender_error_base)  /* check for XRender errors */
179         {
180             if (event->error_code == xrender_error_base + BadPicture) return TRUE;
181         }
182 #endif
183     }
184     return FALSE;
185 }
186
187
188 /***********************************************************************
189  *              X11DRV_expect_error
190  *
191  * Setup a callback function that will be called on an X error.  The
192  * callback must return non-zero if the error is the one it expected.
193  * This function acquires the x11 lock; X11DRV_check_error must be
194  * called in all cases to release it.
195  */
196 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
197 {
198     wine_tsx11_lock();
199     err_callback         = callback;
200     err_callback_display = display;
201     err_callback_arg     = arg;
202     err_callback_result  = 0;
203     err_serial           = NextRequest(display);
204 }
205
206
207 /***********************************************************************
208  *              X11DRV_check_error
209  *
210  * Check if an expected X11 error occurred; return non-zero if yes.
211  * Also release the x11 lock obtained in X11DRV_expect_error.
212  * The caller is responsible for calling XSync first if necessary.
213  */
214 int X11DRV_check_error(void)
215 {
216     int ret;
217     err_callback = NULL;
218     ret = err_callback_result;
219     wine_tsx11_unlock();
220     return ret;
221 }
222
223
224 /***********************************************************************
225  *              error_handler
226  */
227 static int error_handler( Display *display, XErrorEvent *error_evt )
228 {
229     if (err_callback && display == err_callback_display &&
230         (long)(error_evt->serial - err_serial) >= 0)
231     {
232         if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
233         {
234             TRACE( "got expected error %d req %d\n",
235                    error_evt->error_code, error_evt->request_code );
236             return 0;
237         }
238     }
239     if (ignore_error( display, error_evt ))
240     {
241         TRACE( "got ignored error %d req %d\n",
242                error_evt->error_code, error_evt->request_code );
243         return 0;
244     }
245     if (TRACE_ON(synchronous))
246     {
247         ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
248              error_evt->serial, error_evt->request_code );
249         DebugBreak();  /* force an entry in the debugger */
250     }
251     old_error_handler( display, error_evt );
252     return 0;
253 }
254
255 /***********************************************************************
256  *              wine_tsx11_lock   (X11DRV.@)
257  */
258 void wine_tsx11_lock(void)
259 {
260     EnterCriticalSection( &X11DRV_CritSection );
261 }
262
263 /***********************************************************************
264  *              wine_tsx11_unlock   (X11DRV.@)
265  */
266 void wine_tsx11_unlock(void)
267 {
268     LeaveCriticalSection( &X11DRV_CritSection );
269 }
270
271
272 /***********************************************************************
273  *              get_config_key
274  *
275  * Get a config key from either the app-specific or the default config
276  */
277 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
278                                     char *buffer, DWORD size )
279 {
280     if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
281     if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
282     return ERROR_FILE_NOT_FOUND;
283 }
284
285
286 /***********************************************************************
287  *              setup_options
288  *
289  * Setup the x11drv options.
290  */
291 static void setup_options(void)
292 {
293     char buffer[MAX_PATH+16];
294     HKEY hkey, appkey = 0;
295     DWORD len;
296
297     /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
298     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
299
300     /* open the app-specific key */
301
302     len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
303     if (len && len < MAX_PATH)
304     {
305         HKEY tmpkey;
306         char *p, *appname = buffer;
307         if ((p = strrchr( appname, '/' ))) appname = p + 1;
308         if ((p = strrchr( appname, '\\' ))) appname = p + 1;
309         strcat( appname, "\\X11 Driver" );
310         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
311         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
312         {
313             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
314             RegCloseKey( tmpkey );
315         }
316     }
317
318     if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
319         managed_mode = IS_OPTION_TRUE( buffer[0] );
320
321     if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
322         dxgrab = IS_OPTION_TRUE( buffer[0] );
323
324     if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
325         usexvidmode = IS_OPTION_TRUE( buffer[0] );
326
327     if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
328         usexrandr = IS_OPTION_TRUE( buffer[0] );
329
330     if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
331         use_take_focus = IS_OPTION_TRUE( buffer[0] );
332
333     if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
334         use_primary_selection = IS_OPTION_TRUE( buffer[0] );
335
336     screen_depth = 0;
337     if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
338         screen_depth = atoi(buffer);
339
340     if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
341         client_side_with_core = IS_OPTION_TRUE( buffer[0] );
342
343     if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
344         client_side_with_render = IS_OPTION_TRUE( buffer[0] );
345
346     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
347         client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
348
349     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
350         client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
351
352     if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
353         use_xim = IS_OPTION_TRUE( buffer[0] );
354
355     if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
356         private_color_map = IS_OPTION_TRUE( buffer[0] );
357
358     if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
359         primary_monitor = atoi( buffer );
360
361     if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
362         copy_default_colors = atoi(buffer);
363
364     if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
365         alloc_system_colors = atoi(buffer);
366
367     get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
368
369     if (appkey) RegCloseKey( appkey );
370     if (hkey) RegCloseKey( hkey );
371 }
372
373
374 /***********************************************************************
375  *           X11DRV process initialisation routine
376  */
377 static BOOL process_attach(void)
378 {
379     Display *display;
380     XVisualInfo *desktop_vi = NULL;
381     const char *env;
382
383     setup_options();
384
385     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
386
387     /* Open display */
388
389     if (!(env = getenv("XMODIFIERS")) || !*env)  /* try to avoid the Xlib XIM locking bug */
390         if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
391
392     if (!(display = XOpenDisplay( NULL ))) return FALSE;
393
394     fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
395     screen = DefaultScreenOfDisplay( display );
396     visual = DefaultVisual( display, DefaultScreen(display) );
397     root_window = DefaultRootWindow( display );
398     gdi_display = display;
399     old_error_handler = XSetErrorHandler( error_handler );
400
401     /* Initialize screen depth */
402
403     if (screen_depth)  /* depth specified */
404     {
405         int depth_count, i;
406         int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
407         for (i = 0; i < depth_count; i++)
408             if (depth_list[i] == screen_depth) break;
409         XFree( depth_list );
410         if (i >= depth_count)
411         {
412             WARN( "invalid depth %d, using default\n", screen_depth );
413             screen_depth = 0;
414         }
415     }
416     if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
417
418     /* If OpenGL is available, change the default visual, etc as necessary */
419     if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
420     {
421         visual       = desktop_vi->visual;
422         screen       = ScreenOfDisplay(display, desktop_vi->screen);
423         screen_depth = desktop_vi->depth;
424         XFree(desktop_vi);
425     }
426
427     XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
428
429     if (TRACE_ON(synchronous)) XSynchronize( display, True );
430
431     screen_width  = WidthOfScreen( screen );
432     screen_height = HeightOfScreen( screen );
433
434     xinerama_init();
435     X11DRV_Settings_Init();
436
437 #ifdef HAVE_LIBXXF86VM
438     /* initialize XVidMode */
439     X11DRV_XF86VM_Init();
440 #endif
441 #ifdef HAVE_LIBXRANDR
442     /* initialize XRandR */
443     X11DRV_XRandR_Init();
444 #endif
445
446     X11DRV_ClipCursor( NULL );
447     X11DRV_InitKeyboard();
448     X11DRV_InitClipboard();
449
450     return TRUE;
451 }
452
453
454 /***********************************************************************
455  *           X11DRV thread termination routine
456  */
457 static void thread_detach(void)
458 {
459     struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
460
461     if (data)
462     {
463         X11DRV_ResetSelectionOwner();
464         wine_tsx11_lock();
465         if (data->xim) XCloseIM( data->xim );
466         XCloseDisplay( data->display );
467         wine_tsx11_unlock();
468         HeapFree( GetProcessHeap(), 0, data );
469     }
470 }
471
472
473 /***********************************************************************
474  *           X11DRV process termination routine
475  */
476 static void process_detach(void)
477 {
478 #ifdef HAVE_LIBXXF86VM
479     /* cleanup XVidMode */
480     X11DRV_XF86VM_Cleanup();
481 #endif
482     if(using_client_side_fonts)
483         X11DRV_XRender_Finalize();
484
485     /* cleanup GDI */
486     X11DRV_GDI_Finalize();
487
488     DeleteCriticalSection( &X11DRV_CritSection );
489     TlsFree( thread_data_tls_index );
490 }
491
492
493 /* store the display fd into the message queue */
494 static void set_queue_display_fd( Display *display )
495 {
496     HANDLE handle;
497     int ret;
498
499     if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
500     {
501         MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
502         ExitProcess(1);
503     }
504     SERVER_START_REQ( set_queue_fd )
505     {
506         req->handle = handle;
507         ret = wine_server_call( req );
508     }
509     SERVER_END_REQ;
510     if (ret)
511     {
512         MESSAGE( "x11drv: Can't store handle for display fd\n" );
513         ExitProcess(1);
514     }
515     CloseHandle( handle );
516 }
517
518
519 /***********************************************************************
520  *           X11DRV thread initialisation routine
521  */
522 struct x11drv_thread_data *x11drv_init_thread_data(void)
523 {
524     struct x11drv_thread_data *data;
525
526     if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
527     {
528         ERR( "could not create data\n" );
529         ExitProcess(1);
530     }
531     wine_tsx11_lock();
532     if (!(data->display = XOpenDisplay(NULL)))
533     {
534         wine_tsx11_unlock();
535         MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
536         MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
537         ExitProcess(1);
538     }
539
540     fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
541
542 #ifdef HAVE_XKB
543     if (use_xkb)
544     {
545         use_xkb = XkbUseExtension( data->display, NULL, NULL );
546         if (use_xkb)
547         {
548             /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
549             /* This works around an Xlib bug where it tries to get the display lock */
550             /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
551             XkbKeysymToModifiers( data->display, 'A' );
552             XkbSetDetectableAutoRepeat( data->display, True, NULL );
553         }
554     }
555 #endif
556
557     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
558     wine_tsx11_unlock();
559
560     if (!use_xim)
561         data->xim = NULL;
562     else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
563         WARN("Input Method is not available\n");
564
565     set_queue_display_fd( data->display );
566     data->process_event_count = 0;
567     data->cursor = None;
568     data->cursor_window = None;
569     data->grab_window = None;
570     data->last_focus = 0;
571     data->selection_wnd = 0;
572     TlsSetValue( thread_data_tls_index, data );
573     return data;
574 }
575
576
577 /***********************************************************************
578  *           X11DRV initialisation routine
579  */
580 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
581 {
582     BOOL ret = TRUE;
583
584     switch(reason)
585     {
586     case DLL_PROCESS_ATTACH:
587         ret = process_attach();
588         break;
589     case DLL_THREAD_DETACH:
590         thread_detach();
591         break;
592     case DLL_PROCESS_DETACH:
593         process_detach();
594         break;
595     }
596     return ret;
597 }
598
599 /***********************************************************************
600  *              GetScreenSaveActive (X11DRV.@)
601  *
602  * Returns the active status of the screen saver
603  */
604 BOOL X11DRV_GetScreenSaveActive(void)
605 {
606     int timeout, temp;
607     wine_tsx11_lock();
608     XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
609     wine_tsx11_unlock();
610     return timeout != 0;
611 }
612
613 /***********************************************************************
614  *              SetScreenSaveActive (X11DRV.@)
615  *
616  * Activate/Deactivate the screen saver
617  */
618 void X11DRV_SetScreenSaveActive(BOOL bActivate)
619 {
620     int timeout, interval, prefer_blanking, allow_exposures;
621     static int last_timeout = 15 * 60;
622
623     wine_tsx11_lock();
624     XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
625                     &allow_exposures);
626     if (timeout) last_timeout = timeout;
627
628     timeout = bActivate ? last_timeout : 0;
629     XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
630                     allow_exposures);
631     wine_tsx11_unlock();
632 }