Merge branch '2621_path_encoding_and_extfs'
[midnight-commander.git] / lib / tty / x11conn.c
blob024763975b8e7971acde5fd03ec716fecab82c63
1 /*
2 X11 support for the Midnight Commander.
4 Copyright (C) 2005, 2007 Free Software Foundation, Inc.
6 Written by:
7 Roland Illig <roland.illig@gmx.de>, 2005.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 /** \file x11conn.c
25 * \brief Source: X11 support
26 * \warning This code uses setjmp() and longjmp(). Before you modify _anything_ here,
27 * please read the relevant sections of the C standard.
30 #include <config.h>
32 #ifndef HAVE_TEXTMODE_X11_SUPPORT
33 typedef int dummy; /* C99 forbids empty compilation unit */
34 #else
36 #include <setjmp.h>
37 #include <X11/Xlib.h>
38 #ifdef HAVE_GMODULE
39 #include <gmodule.h>
40 #endif
42 #include "lib/global.h"
43 #include "x11conn.h"
45 /*** global variables ****************************************************************************/
47 /*** file scope macro definitions ****************************************************************/
49 #ifndef HAVE_GMODULE
50 #define func_XOpenDisplay XOpenDisplay
51 #define func_XCloseDisplay XCloseDisplay
52 #define func_XSetErrorHandler XSetErrorHandler
53 #define func_XSetIOErrorHandler XSetIOErrorHandler
54 #define func_XQueryPointer XQueryPointer
55 #endif
57 /*** file scope type declarations ****************************************************************/
59 typedef int (*mc_XErrorHandler_callback) (Display *, XErrorEvent *);
60 typedef int (*mc_XIOErrorHandler_callback) (Display *);
62 /*** file scope variables ************************************************************************/
64 #ifdef HAVE_GMODULE
65 static Display *(*func_XOpenDisplay) (_Xconst char *);
66 static int (*func_XCloseDisplay) (Display *);
67 static mc_XErrorHandler_callback (*func_XSetErrorHandler) (mc_XErrorHandler_callback);
68 static mc_XIOErrorHandler_callback (*func_XSetIOErrorHandler) (mc_XIOErrorHandler_callback);
69 static Bool (*func_XQueryPointer) (Display *, Window, Window *, Window *,
70 int *, int *, int *, int *, unsigned int *);
71 static GModule *x11_module;
72 #endif
74 static gboolean handlers_installed = FALSE;
76 /* This flag is set as soon as an X11 error is reported. Usually that
77 * means that the DISPLAY is not available anymore. We do not try to
78 * reconnect, as that would violate the X11 protocol. */
79 static gboolean lost_connection = FALSE;
81 static jmp_buf x11_exception; /* FIXME: get a better name */
82 static gboolean longjmp_allowed = FALSE;
84 /*** file scope functions ************************************************************************/
85 /* --------------------------------------------------------------------------------------------- */
87 static int
88 x_io_error_handler (Display * dpy)
90 (void) dpy;
92 lost_connection = TRUE;
93 if (longjmp_allowed)
95 longjmp_allowed = FALSE;
96 longjmp (x11_exception, 1);
98 return 0;
101 /* --------------------------------------------------------------------------------------------- */
103 static int
104 x_error_handler (Display * dpy, XErrorEvent * ee)
106 (void) ee;
107 (void) func_XCloseDisplay (dpy);
108 return x_io_error_handler (dpy);
111 /* --------------------------------------------------------------------------------------------- */
113 static void
114 install_error_handlers (void)
116 if (handlers_installed)
117 return;
119 (void) func_XSetErrorHandler (x_error_handler);
120 (void) func_XSetIOErrorHandler (x_io_error_handler);
121 handlers_installed = TRUE;
124 /* --------------------------------------------------------------------------------------------- */
126 static gboolean
127 x11_available (void)
129 #ifdef HAVE_GMODULE
130 gchar *x11_module_fname;
132 if (lost_connection)
133 return FALSE;
135 if (x11_module != NULL)
136 return TRUE;
138 x11_module_fname = g_module_build_path (NULL, "X11");
139 x11_module = g_module_open (x11_module_fname, G_MODULE_BIND_LAZY);
140 if (x11_module == NULL)
141 x11_module = g_module_open ("libX11.so.6", G_MODULE_BIND_LAZY);
143 g_free (x11_module_fname);
145 if (x11_module == NULL)
146 return FALSE;
148 if (!g_module_symbol (x11_module, "XOpenDisplay", (void *) &func_XOpenDisplay))
149 goto cleanup;
150 if (!g_module_symbol (x11_module, "XCloseDisplay", (void *) &func_XCloseDisplay))
151 goto cleanup;
152 if (!g_module_symbol (x11_module, "XQueryPointer", (void *) &func_XQueryPointer))
153 goto cleanup;
154 if (!g_module_symbol (x11_module, "XSetErrorHandler", (void *) &func_XSetErrorHandler))
155 goto cleanup;
156 if (!g_module_symbol (x11_module, "XSetIOErrorHandler", (void *) &func_XSetIOErrorHandler))
157 goto cleanup;
159 install_error_handlers ();
160 return TRUE;
162 cleanup:
163 func_XOpenDisplay = 0;
164 func_XCloseDisplay = 0;
165 func_XQueryPointer = 0;
166 func_XSetErrorHandler = 0;
167 func_XSetIOErrorHandler = 0;
168 g_module_close (x11_module);
169 x11_module = NULL;
170 return FALSE;
171 #else
172 install_error_handlers ();
173 return !(lost_connection);
174 #endif
177 /* --------------------------------------------------------------------------------------------- */
178 /*** public functions ****************************************************************************/
179 /* --------------------------------------------------------------------------------------------- */
181 Display *
182 mc_XOpenDisplay (const char *displayname)
184 Display *retval;
186 if (x11_available ())
188 if (setjmp (x11_exception) == 0)
190 longjmp_allowed = TRUE;
191 retval = func_XOpenDisplay (displayname);
192 longjmp_allowed = FALSE;
193 return retval;
196 return NULL;
199 /* --------------------------------------------------------------------------------------------- */
202 mc_XCloseDisplay (Display * display)
204 int retval;
206 if (x11_available ())
208 if (setjmp (x11_exception) == 0)
210 longjmp_allowed = TRUE;
211 retval = func_XCloseDisplay (display);
212 longjmp_allowed = FALSE;
213 return retval;
216 return 0;
219 /* --------------------------------------------------------------------------------------------- */
221 Bool
222 mc_XQueryPointer (Display * display, Window win, Window * root_return,
223 Window * child_return, int *root_x_return, int *root_y_return,
224 int *win_x_return, int *win_y_return, unsigned int *mask_return)
226 Bool retval;
228 if (x11_available ())
230 if (setjmp (x11_exception) == 0)
232 longjmp_allowed = TRUE;
233 retval = func_XQueryPointer (display, win, root_return,
234 child_return, root_x_return, root_y_return,
235 win_x_return, win_y_return, mask_return);
236 longjmp_allowed = FALSE;
237 return retval;
240 *root_return = None;
241 *child_return = None;
242 *root_x_return = 0;
243 *root_y_return = 0;
244 *win_x_return = 0;
245 *win_y_return = 0;
246 *mask_return = 0;
247 return False;
250 /* --------------------------------------------------------------------------------------------- */
252 #endif /* HAVE_TEXTMODE_X11_SUPPORT */