root/lib/tty/x11conn.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. x_io_error_handler
  2. x_error_handler
  3. install_error_handlers
  4. x11_available
  5. mc_XOpenDisplay
  6. mc_XCloseDisplay
  7. mc_XQueryPointer

   1 /*
   2    X11 support for the Midnight Commander.
   3 
   4    Copyright (C) 2005-2024
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Roland Illig <roland.illig@gmx.de>, 2005.
   9 
  10    This file is part of the Midnight Commander.
  11 
  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.
  16 
  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.
  21 
  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/>.
  24  */
  25 
  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.
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <setjmp.h>
  35 #include <X11/Xlib.h>
  36 #ifdef HAVE_GMODULE
  37 #include <gmodule.h>
  38 #endif
  39 
  40 #include "lib/global.h"
  41 #include "x11conn.h"
  42 
  43 /*** global variables ****************************************************************************/
  44 
  45 /*** file scope macro definitions ****************************************************************/
  46 
  47 #ifndef HAVE_GMODULE
  48 #define func_XOpenDisplay       XOpenDisplay
  49 #define func_XCloseDisplay      XCloseDisplay
  50 #define func_XSetErrorHandler   XSetErrorHandler
  51 #define func_XSetIOErrorHandler XSetIOErrorHandler
  52 #define func_XQueryPointer      XQueryPointer
  53 #endif
  54 
  55 /*** file scope type declarations ****************************************************************/
  56 
  57 typedef int (*mc_XErrorHandler_callback) (Display *, XErrorEvent *);
  58 typedef int (*mc_XIOErrorHandler_callback) (Display *);
  59 
  60 /*** forward declarations (file scope functions) *************************************************/
  61 
  62 /*** file scope variables ************************************************************************/
  63 
  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 
  72 static GModule *x11_module;
  73 #endif
  74 
  75 static gboolean handlers_installed = FALSE;
  76 
  77 /* This flag is set as soon as an X11 error is reported. Usually that
  78  * means that the DISPLAY is not available anymore. We do not try to
  79  * reconnect, as that would violate the X11 protocol. */
  80 static gboolean lost_connection = FALSE;
  81 
  82 static jmp_buf x11_exception;   /* FIXME: get a better name */
  83 static gboolean longjmp_allowed = FALSE;
  84 
  85 /* --------------------------------------------------------------------------------------------- */
  86 /*** file scope functions ************************************************************************/
  87 /* --------------------------------------------------------------------------------------------- */
  88 
  89 static int
  90 x_io_error_handler (Display * dpy)
     /* [previous][next][first][last][top][bottom][index][help]  */
  91 {
  92     (void) dpy;
  93 
  94     lost_connection = TRUE;
  95     if (longjmp_allowed)
  96     {
  97         longjmp_allowed = FALSE;
  98         longjmp (x11_exception, 1);
  99     }
 100     return 0;
 101 }
 102 
 103 /* --------------------------------------------------------------------------------------------- */
 104 
 105 static int
 106 x_error_handler (Display * dpy, XErrorEvent * ee)
     /* [previous][next][first][last][top][bottom][index][help]  */
 107 {
 108     (void) ee;
 109     (void) func_XCloseDisplay (dpy);
 110     return x_io_error_handler (dpy);
 111 }
 112 
 113 /* --------------------------------------------------------------------------------------------- */
 114 
 115 static void
 116 install_error_handlers (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 117 {
 118     if (handlers_installed)
 119         return;
 120 
 121     (void) func_XSetErrorHandler (x_error_handler);
 122     (void) func_XSetIOErrorHandler (x_io_error_handler);
 123     handlers_installed = TRUE;
 124 }
 125 
 126 /* --------------------------------------------------------------------------------------------- */
 127 
 128 static gboolean
 129 x11_available (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 130 {
 131 #ifdef HAVE_GMODULE
 132     gchar *x11_module_fname;
 133 
 134     if (lost_connection)
 135         return FALSE;
 136 
 137     if (x11_module != NULL)
 138         return TRUE;
 139 
 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);
 144 
 145     g_free (x11_module_fname);
 146 
 147     if (x11_module == NULL)
 148         return FALSE;
 149 
 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;
 160 
 161     install_error_handlers ();
 162     return TRUE;
 163 
 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
 177 }
 178 
 179 /* --------------------------------------------------------------------------------------------- */
 180 /*** public functions ****************************************************************************/
 181 /* --------------------------------------------------------------------------------------------- */
 182 
 183 Display *
 184 mc_XOpenDisplay (const char *displayname)
     /* [previous][next][first][last][top][bottom][index][help]  */
 185 {
 186     if (x11_available ())
 187     {
 188         if (setjmp (x11_exception) == 0)
 189         {
 190             Display *retval;
 191 
 192             /* cppcheck-suppress redundantAssignment */
 193             longjmp_allowed = TRUE;
 194 
 195             retval = func_XOpenDisplay (displayname);
 196 
 197             /* cppcheck-suppress redundantAssignment */
 198             longjmp_allowed = FALSE;
 199             return retval;
 200         }
 201     }
 202     return NULL;
 203 }
 204 
 205 /* --------------------------------------------------------------------------------------------- */
 206 
 207 int
 208 mc_XCloseDisplay (Display * display)
     /* [previous][next][first][last][top][bottom][index][help]  */
 209 {
 210     if (x11_available ())
 211     {
 212         if (setjmp (x11_exception) == 0)
 213         {
 214             int retval;
 215 
 216             /* cppcheck-suppress redundantAssignment */
 217             longjmp_allowed = TRUE;
 218 
 219             retval = func_XCloseDisplay (display);
 220 
 221             /* cppcheck-suppress redundantAssignment */
 222             longjmp_allowed = FALSE;
 223 
 224             return retval;
 225         }
 226     }
 227     return 0;
 228 }
 229 
 230 /* --------------------------------------------------------------------------------------------- */
 231 
 232 Bool
 233 mc_XQueryPointer (Display * display, Window win, Window * root_return,
     /* [previous][next][first][last][top][bottom][index][help]  */
 234                   Window * child_return, int *root_x_return, int *root_y_return,
 235                   int *win_x_return, int *win_y_return, unsigned int *mask_return)
 236 {
 237     Bool retval;
 238 
 239     if (x11_available ())
 240     {
 241         if (setjmp (x11_exception) == 0)
 242         {
 243             /* cppcheck-suppress redundantAssignment */
 244             longjmp_allowed = TRUE;
 245 
 246             retval = func_XQueryPointer (display, win, root_return,
 247                                          child_return, root_x_return, root_y_return,
 248                                          win_x_return, win_y_return, mask_return);
 249 
 250             /* cppcheck-suppress redundantAssignment */
 251             longjmp_allowed = FALSE;
 252 
 253             return retval;
 254         }
 255     }
 256     *root_return = None;
 257     *child_return = None;
 258     *root_x_return = 0;
 259     *root_y_return = 0;
 260     *win_x_return = 0;
 261     *win_y_return = 0;
 262     *mask_return = 0;
 263     return False;
 264 }
 265 
 266 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */