87f58d06d5e924f5b17cf0729acf5a03cf69ce9b
[midnight-commander.git] / lib / tty / x11conn.c
blob87f58d06d5e924f5b17cf0729acf5a03cf69ce9b
1 /*
2 X11 support for the Midnight Commander.
4 Copyright (C) 2005, 2007, 2011
5 The Free Software Foundation, Inc.
7 Written by:
8 Roland Illig <roland.illig@gmx.de>, 2005.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 /** \file x11conn.c
27 * \brief Source: X11 support
28 * \warning This code uses setjmp() and longjmp(). Before you modify _anything_ here,
29 * please read the relevant sections of the C standard.
32 #include <config.h>
34 #ifndef HAVE_TEXTMODE_X11_SUPPORT
35 typedef int dummy; /* C99 forbids empty compilation unit */
36 #else
38 #include <setjmp.h>
39 #include <X11/Xlib.h>
40 #ifdef HAVE_GMODULE
41 #include <gmodule.h>
42 #endif
44 #include "lib/global.h"
45 #include "x11conn.h"
47 /*** global variables ****************************************************************************/
49 /*** file scope macro definitions ****************************************************************/
51 #ifndef HAVE_GMODULE
52 #define func_XOpenDisplay XOpenDisplay
53 #define func_XCloseDisplay XCloseDisplay
54 #define func_XSetErrorHandler XSetErrorHandler
55 #define func_XSetIOErrorHandler XSetIOErrorHandler
56 #define func_XQueryPointer XQueryPointer
57 #endif
59 /*** file scope type declarations ****************************************************************/
61 typedef int (*mc_XErrorHandler_callback) (Display *, XErrorEvent *);
62 typedef int (*mc_XIOErrorHandler_callback) (Display *);
64 /*** file scope variables ************************************************************************/
66 #ifdef HAVE_GMODULE
67 static Display *(*func_XOpenDisplay) (_Xconst char *);
68 static int (*func_XCloseDisplay) (Display *);
69 static mc_XErrorHandler_callback (*func_XSetErrorHandler) (mc_XErrorHandler_callback);
70 static mc_XIOErrorHandler_callback (*func_XSetIOErrorHandler) (mc_XIOErrorHandler_callback);
71 static Bool (*func_XQueryPointer) (Display *, Window, Window *, Window *,
72 int *, int *, int *, int *, unsigned int *);
73 static GModule *x11_module;
74 #endif
76 static gboolean handlers_installed = FALSE;
78 /* This flag is set as soon as an X11 error is reported. Usually that
79 * means that the DISPLAY is not available anymore. We do not try to
80 * reconnect, as that would violate the X11 protocol. */
81 static gboolean lost_connection = FALSE;
83 static jmp_buf x11_exception; /* FIXME: get a better name */
84 static gboolean longjmp_allowed = FALSE;
86 /*** file scope functions ************************************************************************/
87 /* --------------------------------------------------------------------------------------------- */
89 static int
90 x_io_error_handler (Display * dpy)
92 (void) dpy;
94 lost_connection = TRUE;
95 if (longjmp_allowed)
97 longjmp_allowed = FALSE;
98 longjmp (x11_exception, 1);
100 return 0;
103 /* --------------------------------------------------------------------------------------------- */
105 static int
106 x_error_handler (Display * dpy, XErrorEvent * ee)
108 (void) ee;
109 (void) func_XCloseDisplay (dpy);
110 return x_io_error_handler (dpy);
113 /* --------------------------------------------------------------------------------------------- */
115 static void
116 install_error_handlers (void)
118 if (handlers_installed)
119 return;
121 (void) func_XSetErrorHandler (x_error_handler);
122 (void) func_XSetIOErrorHandler (x_io_error_handler);
123 handlers_installed = TRUE;
126 /* --------------------------------------------------------------------------------------------- */
128 static gboolean
129 x11_available (void)
131 #ifdef HAVE_GMODULE
132 gchar *x11_module_fname;
134 if (lost_connection)
135 return FALSE;
137 if (x11_module != NULL)
138 return TRUE;
140 x11_module_fname = g_module_build_path (NULL, "X11");
141 x11_module = g_module_open (x11_module_fname, G_MODULE_BIND_LAZY);
142 if (x11_module == NULL)
143 x11_module = g_module_open ("libX11.so.6", G_MODULE_BIND_LAZY);
145 g_free (x11_module_fname);
147 if (x11_module == NULL)
148 return FALSE;
150 if (!g_module_symbol (x11_module, "XOpenDisplay", (void *) &func_XOpenDisplay))
151 goto cleanup;
152 if (!g_module_symbol (x11_module, "XCloseDisplay", (void *) &func_XCloseDisplay))
153 goto cleanup;
154 if (!g_module_symbol (x11_module, "XQueryPointer", (void *) &func_XQueryPointer))
155 goto cleanup;
156 if (!g_module_symbol (x11_module, "XSetErrorHandler", (void *) &func_XSetErrorHandler))
157 goto cleanup;
158 if (!g_module_symbol (x11_module, "XSetIOErrorHandler", (void *) &func_XSetIOErrorHandler))
159 goto cleanup;
161 install_error_handlers ();
162 return TRUE;
164 cleanup:
165 func_XOpenDisplay = 0;
166 func_XCloseDisplay = 0;
167 func_XQueryPointer = 0;
168 func_XSetErrorHandler = 0;
169 func_XSetIOErrorHandler = 0;
170 g_module_close (x11_module);
171 x11_module = NULL;
172 return FALSE;
173 #else
174 install_error_handlers ();
175 return !(lost_connection);
176 #endif
179 /* --------------------------------------------------------------------------------------------- */
180 /*** public functions ****************************************************************************/
181 /* --------------------------------------------------------------------------------------------- */
183 Display *
184 mc_XOpenDisplay (const char *displayname)
186 Display *retval;
188 if (x11_available ())
190 if (setjmp (x11_exception) == 0)
192 longjmp_allowed = TRUE;
193 retval = func_XOpenDisplay (displayname);
194 longjmp_allowed = FALSE;
195 return retval;
198 return NULL;
201 /* --------------------------------------------------------------------------------------------- */
204 mc_XCloseDisplay (Display * display)
206 int retval;
208 if (x11_available ())
210 if (setjmp (x11_exception) == 0)
212 longjmp_allowed = TRUE;
213 retval = func_XCloseDisplay (display);
214 longjmp_allowed = FALSE;
215 return retval;
218 return 0;
221 /* --------------------------------------------------------------------------------------------- */
223 Bool
224 mc_XQueryPointer (Display * display, Window win, Window * root_return,
225 Window * child_return, int *root_x_return, int *root_y_return,
226 int *win_x_return, int *win_y_return, unsigned int *mask_return)
228 Bool retval;
230 if (x11_available ())
232 if (setjmp (x11_exception) == 0)
234 longjmp_allowed = TRUE;
235 retval = func_XQueryPointer (display, win, root_return,
236 child_return, root_x_return, root_y_return,
237 win_x_return, win_y_return, mask_return);
238 longjmp_allowed = FALSE;
239 return retval;
242 *root_return = None;
243 *child_return = None;
244 *root_x_return = 0;
245 *root_y_return = 0;
246 *win_x_return = 0;
247 *win_y_return = 0;
248 *mask_return = 0;
249 return False;
252 /* --------------------------------------------------------------------------------------------- */
254 #endif /* HAVE_TEXTMODE_X11_SUPPORT */