dlls: Remove unreachable break after return/break. Found by Smatch.
[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     "text/uri-list"
163 };
164
165 /***********************************************************************
166  *              ignore_error
167  *
168  * Check if the X error is one we can ignore.
169  */
170 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
171 {
172     if (event->request_code == X_SetInputFocus && event->error_code == BadMatch) return TRUE;
173
174     /* ignore a number of errors on gdi display caused by creating/destroying windows */
175     if (display == gdi_display)
176     {
177         if (event->error_code == BadDrawable || event->error_code == BadGC) return TRUE;
178 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
179         if (xrender_error_base)  /* check for XRender errors */
180         {
181             if (event->error_code == xrender_error_base + BadPicture) return TRUE;
182         }
183 #endif
184     }
185     return FALSE;
186 }
187
188
189 /***********************************************************************
190  *              X11DRV_expect_error
191  *
192  * Setup a callback function that will be called on an X error.  The
193  * callback must return non-zero if the error is the one it expected.
194  * This function acquires the x11 lock; X11DRV_check_error must be
195  * called in all cases to release it.
196  */
197 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
198 {
199     wine_tsx11_lock();
200     err_callback         = callback;
201     err_callback_display = display;
202     err_callback_arg     = arg;
203     err_callback_result  = 0;
204     err_serial           = NextRequest(display);
205 }
206
207
208 /***********************************************************************
209  *              X11DRV_check_error
210  *
211  * Check if an expected X11 error occurred; return non-zero if yes.
212  * Also release the x11 lock obtained in X11DRV_expect_error.
213  * The caller is responsible for calling XSync first if necessary.
214  */
215 int X11DRV_check_error(void)
216 {
217     int ret;
218     err_callback = NULL;
219     ret = err_callback_result;
220     wine_tsx11_unlock();
221     return ret;
222 }
223
224
225 /***********************************************************************
226  *              error_handler
227  */
228 static int error_handler( Display *display, XErrorEvent *error_evt )
229 {
230     if (err_callback && display == err_callback_display &&
231         (long)(error_evt->serial - err_serial) >= 0)
232     {
233         if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
234         {
235             TRACE( "got expected error %d req %d\n",
236                    error_evt->error_code, error_evt->request_code );
237             return 0;
238         }
239     }
240     if (ignore_error( display, error_evt ))
241     {
242         TRACE( "got ignored error %d req %d\n",
243                error_evt->error_code, error_evt->request_code );
244         return 0;
245     }
246     if (TRACE_ON(synchronous))
247     {
248         ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
249              error_evt->serial, error_evt->request_code );
250         DebugBreak();  /* force an entry in the debugger */
251     }
252     old_error_handler( display, error_evt );
253     return 0;
254 }
255
256 /***********************************************************************
257  *              wine_tsx11_lock   (X11DRV.@)
258  */
259 void wine_tsx11_lock(void)
260 {
261     EnterCriticalSection( &X11DRV_CritSection );
262 }
263
264 /***********************************************************************
265  *              wine_tsx11_unlock   (X11DRV.@)
266  */
267 void wine_tsx11_unlock(void)
268 {
269     LeaveCriticalSection( &X11DRV_CritSection );
270 }
271
272
273 /***********************************************************************
274  *              get_config_key
275  *
276  * Get a config key from either the app-specific or the default config
277  */
278 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
279                                     char *buffer, DWORD size )
280 {
281     if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
282     if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
283     return ERROR_FILE_NOT_FOUND;
284 }
285
286
287 /***********************************************************************
288  *              setup_options
289  *
290  * Setup the x11drv options.
291  */
292 static void setup_options(void)
293 {
294     char buffer[MAX_PATH+16];
295     HKEY hkey, appkey = 0;
296     DWORD len;
297
298     /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
299     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\X11 Driver", &hkey )) hkey = 0;
300
301     /* open the app-specific key */
302
303     len = (GetModuleFileNameA( 0, buffer, MAX_PATH ));
304     if (len && len < MAX_PATH)
305     {
306         HKEY tmpkey;
307         char *p, *appname = buffer;
308         if ((p = strrchr( appname, '/' ))) appname = p + 1;
309         if ((p = strrchr( appname, '\\' ))) appname = p + 1;
310         strcat( appname, "\\X11 Driver" );
311         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
312         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
313         {
314             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
315             RegCloseKey( tmpkey );
316         }
317     }
318
319     if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
320         managed_mode = IS_OPTION_TRUE( buffer[0] );
321
322     if (!get_config_key( hkey, appkey, "DXGrab", buffer, sizeof(buffer) ))
323         dxgrab = IS_OPTION_TRUE( buffer[0] );
324
325     if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
326         usexvidmode = IS_OPTION_TRUE( buffer[0] );
327
328     if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
329         usexrandr = IS_OPTION_TRUE( buffer[0] );
330
331     if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
332         use_take_focus = IS_OPTION_TRUE( buffer[0] );
333
334     if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
335         use_primary_selection = IS_OPTION_TRUE( buffer[0] );
336
337     screen_depth = 0;
338     if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
339         screen_depth = atoi(buffer);
340
341     if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
342         client_side_with_core = IS_OPTION_TRUE( buffer[0] );
343
344     if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
345         client_side_with_render = IS_OPTION_TRUE( buffer[0] );
346
347     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
348         client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
349
350     if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
351         client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
352
353     if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
354         use_xim = IS_OPTION_TRUE( buffer[0] );
355
356     if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
357         private_color_map = IS_OPTION_TRUE( buffer[0] );
358
359     if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
360         primary_monitor = atoi( buffer );
361
362     if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
363         copy_default_colors = atoi(buffer);
364
365     if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
366         alloc_system_colors = atoi(buffer);
367
368     get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
369
370     if (appkey) RegCloseKey( appkey );
371     if (hkey) RegCloseKey( hkey );
372 }
373
374
375 /***********************************************************************
376  *           X11DRV process initialisation routine
377  */
378 static BOOL process_attach(void)
379 {
380     Display *display;
381     XVisualInfo *desktop_vi = NULL;
382     const char *env;
383
384     setup_options();
385
386     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
387
388     /* Open display */
389
390     if (!(env = getenv("XMODIFIERS")) || !*env)  /* try to avoid the Xlib XIM locking bug */
391         if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
392
393     if (!(display = XOpenDisplay( NULL ))) return FALSE;
394
395     fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
396     screen = DefaultScreenOfDisplay( display );
397     visual = DefaultVisual( display, DefaultScreen(display) );
398     root_window = DefaultRootWindow( display );
399     gdi_display = display;
400     old_error_handler = XSetErrorHandler( error_handler );
401
402     /* Initialize screen depth */
403
404     if (screen_depth)  /* depth specified */
405     {
406         int depth_count, i;
407         int *depth_list = XListDepths(display, DefaultScreen(display), &depth_count);
408         for (i = 0; i < depth_count; i++)
409             if (depth_list[i] == screen_depth) break;
410         XFree( depth_list );
411         if (i >= depth_count)
412         {
413             WARN( "invalid depth %d, using default\n", screen_depth );
414             screen_depth = 0;
415         }
416     }
417     if (!screen_depth) screen_depth = DefaultDepthOfScreen( screen );
418
419     /* If OpenGL is available, change the default visual, etc as necessary */
420     if ((desktop_vi = X11DRV_setup_opengl_visual( display )))
421     {
422         visual       = desktop_vi->visual;
423         screen       = ScreenOfDisplay(display, desktop_vi->screen);
424         screen_depth = desktop_vi->depth;
425         XFree(desktop_vi);
426     }
427
428     XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
429
430     if (TRACE_ON(synchronous)) XSynchronize( display, True );
431
432     screen_width  = WidthOfScreen( screen );
433     screen_height = HeightOfScreen( screen );
434
435     xinerama_init();
436     X11DRV_Settings_Init();
437
438 #ifdef HAVE_LIBXXF86VM
439     /* initialize XVidMode */
440     X11DRV_XF86VM_Init();
441 #endif
442 #ifdef SONAME_LIBXRANDR
443     /* initialize XRandR */
444     X11DRV_XRandR_Init();
445 #endif
446
447     X11DRV_ClipCursor( NULL );
448     X11DRV_InitKeyboard();
449     X11DRV_InitClipboard();
450
451     return TRUE;
452 }
453
454
455 /***********************************************************************
456  *           X11DRV thread termination routine
457  */
458 static void thread_detach(void)
459 {
460     struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
461
462     if (data)
463     {
464         X11DRV_ResetSelectionOwner();
465         wine_tsx11_lock();
466         if (data->xim) XCloseIM( data->xim );
467         XCloseDisplay( data->display );
468         wine_tsx11_unlock();
469         HeapFree( GetProcessHeap(), 0, data );
470     }
471 }
472
473
474 /***********************************************************************
475  *           X11DRV process termination routine
476  */
477 static void process_detach(void)
478 {
479 #ifdef HAVE_LIBXXF86VM
480     /* cleanup XVidMode */
481     X11DRV_XF86VM_Cleanup();
482 #endif
483     if(using_client_side_fonts)
484         X11DRV_XRender_Finalize();
485
486     /* cleanup GDI */
487     X11DRV_GDI_Finalize();
488
489     DeleteCriticalSection( &X11DRV_CritSection );
490     TlsFree( thread_data_tls_index );
491 }
492
493
494 /* store the display fd into the message queue */
495 static void set_queue_display_fd( Display *display )
496 {
497     HANDLE handle;
498     int ret;
499
500     if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
501     {
502         MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
503         ExitProcess(1);
504     }
505     SERVER_START_REQ( set_queue_fd )
506     {
507         req->handle = handle;
508         ret = wine_server_call( req );
509     }
510     SERVER_END_REQ;
511     if (ret)
512     {
513         MESSAGE( "x11drv: Can't store handle for display fd\n" );
514         ExitProcess(1);
515     }
516     CloseHandle( handle );
517 }
518
519
520 /***********************************************************************
521  *           X11DRV thread initialisation routine
522  */
523 struct x11drv_thread_data *x11drv_init_thread_data(void)
524 {
525     struct x11drv_thread_data *data;
526
527     if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
528     {
529         ERR( "could not create data\n" );
530         ExitProcess(1);
531     }
532     wine_tsx11_lock();
533     if (!(data->display = XOpenDisplay(NULL)))
534     {
535         wine_tsx11_unlock();
536         MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
537         MESSAGE( "Please ensure that your X server is running and that $DISPLAY is set correctly.\n" );
538         ExitProcess(1);
539     }
540
541     fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
542
543 #ifdef HAVE_XKB
544     if (use_xkb)
545     {
546         use_xkb = XkbUseExtension( data->display, NULL, NULL );
547         if (use_xkb)
548         {
549             /* Hack: dummy call to XkbKeysymToModifiers to force initialisation of Xkb internals */
550             /* This works around an Xlib bug where it tries to get the display lock */
551             /* twice during XFilterEvents if Xkb hasn't been initialised yet. */
552             XkbKeysymToModifiers( data->display, 'A' );
553             XkbSetDetectableAutoRepeat( data->display, True, NULL );
554         }
555     }
556 #endif
557
558     if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
559     wine_tsx11_unlock();
560
561     if (!use_xim)
562         data->xim = NULL;
563     else if (!(data->xim = X11DRV_SetupXIM( data->display, input_style )))
564         WARN("Input Method is not available\n");
565
566     set_queue_display_fd( data->display );
567     data->process_event_count = 0;
568     data->cursor = None;
569     data->cursor_window = None;
570     data->grab_window = None;
571     data->last_focus = 0;
572     data->selection_wnd = 0;
573     TlsSetValue( thread_data_tls_index, data );
574     return data;
575 }
576
577
578 /***********************************************************************
579  *           X11DRV initialisation routine
580  */
581 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
582 {
583     BOOL ret = TRUE;
584
585     switch(reason)
586     {
587     case DLL_PROCESS_ATTACH:
588         ret = process_attach();
589         break;
590     case DLL_THREAD_DETACH:
591         thread_detach();
592         break;
593     case DLL_PROCESS_DETACH:
594         process_detach();
595         break;
596     }
597     return ret;
598 }
599
600 /***********************************************************************
601  *              GetScreenSaveActive (X11DRV.@)
602  *
603  * Returns the active status of the screen saver
604  */
605 BOOL X11DRV_GetScreenSaveActive(void)
606 {
607     int timeout, temp;
608     wine_tsx11_lock();
609     XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
610     wine_tsx11_unlock();
611     return timeout != 0;
612 }
613
614 /***********************************************************************
615  *              SetScreenSaveActive (X11DRV.@)
616  *
617  * Activate/Deactivate the screen saver
618  */
619 void X11DRV_SetScreenSaveActive(BOOL bActivate)
620 {
621     int timeout, interval, prefer_blanking, allow_exposures;
622     static int last_timeout = 15 * 60;
623
624     wine_tsx11_lock();
625     XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
626                     &allow_exposures);
627     if (timeout) last_timeout = timeout;
628
629     timeout = bActivate ? last_timeout : 0;
630     XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
631                     allow_exposures);
632     wine_tsx11_unlock();
633 }