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-2025
   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     if (lost_connection)
 133         return FALSE;
 134 
 135     if (x11_module != NULL)
 136         return TRUE;
 137 
 138     x11_module = g_module_open ("X11", G_MODULE_BIND_LAZY);
 139     if (x11_module == NULL)
 140         x11_module = g_module_open ("libX11.so.6", G_MODULE_BIND_LAZY);
 141 
 142     if (x11_module == NULL)
 143         return FALSE;
 144 
 145     if (!g_module_symbol (x11_module, "XOpenDisplay", (void *) &func_XOpenDisplay))
 146         goto cleanup;
 147     if (!g_module_symbol (x11_module, "XCloseDisplay", (void *) &func_XCloseDisplay))
 148         goto cleanup;
 149     if (!g_module_symbol (x11_module, "XQueryPointer", (void *) &func_XQueryPointer))
 150         goto cleanup;
 151     if (!g_module_symbol (x11_module, "XSetErrorHandler", (void *) &func_XSetErrorHandler))
 152         goto cleanup;
 153     if (!g_module_symbol (x11_module, "XSetIOErrorHandler", (void *) &func_XSetIOErrorHandler))
 154         goto cleanup;
 155 
 156     install_error_handlers ();
 157     return TRUE;
 158 
 159   cleanup:
 160     func_XOpenDisplay = 0;
 161     func_XCloseDisplay = 0;
 162     func_XQueryPointer = 0;
 163     func_XSetErrorHandler = 0;
 164     func_XSetIOErrorHandler = 0;
 165     g_module_close (x11_module);
 166     x11_module = NULL;
 167     return FALSE;
 168 #else
 169     install_error_handlers ();
 170     return !(lost_connection);
 171 #endif
 172 }
 173 
 174 /* --------------------------------------------------------------------------------------------- */
 175 /*** public functions ****************************************************************************/
 176 /* --------------------------------------------------------------------------------------------- */
 177 
 178 Display *
 179 mc_XOpenDisplay (const char *displayname)
     /* [previous][next][first][last][top][bottom][index][help]  */
 180 {
 181     if (x11_available ())
 182     {
 183         if (setjmp (x11_exception) == 0)
 184         {
 185             Display *retval;
 186 
 187             /* cppcheck-suppress redundantAssignment */
 188             longjmp_allowed = TRUE;
 189 
 190             retval = func_XOpenDisplay (displayname);
 191 
 192             /* cppcheck-suppress redundantAssignment */
 193             longjmp_allowed = FALSE;
 194             return retval;
 195         }
 196     }
 197     return NULL;
 198 }
 199 
 200 /* --------------------------------------------------------------------------------------------- */
 201 
 202 int
 203 mc_XCloseDisplay (Display *display)
     /* [previous][next][first][last][top][bottom][index][help]  */
 204 {
 205     if (x11_available ())
 206     {
 207         if (setjmp (x11_exception) == 0)
 208         {
 209             int retval;
 210 
 211             /* cppcheck-suppress redundantAssignment */
 212             longjmp_allowed = TRUE;
 213 
 214             retval = func_XCloseDisplay (display);
 215 
 216             /* cppcheck-suppress redundantAssignment */
 217             longjmp_allowed = FALSE;
 218 
 219             return retval;
 220         }
 221     }
 222     return 0;
 223 }
 224 
 225 /* --------------------------------------------------------------------------------------------- */
 226 
 227 Bool
 228 mc_XQueryPointer (Display *display, Window win, Window *root_return,
     /* [previous][next][first][last][top][bottom][index][help]  */
 229                   Window *child_return, int *root_x_return, int *root_y_return,
 230                   int *win_x_return, int *win_y_return, unsigned int *mask_return)
 231 {
 232     Bool retval;
 233 
 234     if (x11_available ())
 235     {
 236         if (setjmp (x11_exception) == 0)
 237         {
 238             /* cppcheck-suppress redundantAssignment */
 239             longjmp_allowed = TRUE;
 240 
 241             retval = func_XQueryPointer (display, win, root_return,
 242                                          child_return, root_x_return, root_y_return,
 243                                          win_x_return, win_y_return, mask_return);
 244 
 245             /* cppcheck-suppress redundantAssignment */
 246             longjmp_allowed = FALSE;
 247 
 248             return retval;
 249         }
 250     }
 251     *root_return = None;
 252     *child_return = None;
 253     *root_x_return = 0;
 254     *root_y_return = 0;
 255     *win_x_return = 0;
 256     *win_y_return = 0;
 257     *mask_return = 0;
 258     return False;
 259 }
 260 
 261 /* --------------------------------------------------------------------------------------------- */

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