Manual pages: mcmcdiffmceditmcview

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 <https://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 *, int *, int *, int *,
  70                                    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             longjmp_allowed = TRUE;
 188 
 189             retval = func_XOpenDisplay (displayname);
 190 
 191             longjmp_allowed = FALSE;
 192             return retval;
 193         }
 194     }
 195     return NULL;
 196 }
 197 
 198 /* --------------------------------------------------------------------------------------------- */
 199 
 200 int
 201 mc_XCloseDisplay (Display *display)
     /* [previous][next][first][last][top][bottom][index][help]  */
 202 {
 203     if (x11_available ())
 204     {
 205         if (setjmp (x11_exception) == 0)
 206         {
 207             int retval;
 208 
 209             longjmp_allowed = TRUE;
 210 
 211             retval = func_XCloseDisplay (display);
 212 
 213             longjmp_allowed = FALSE;
 214 
 215             return retval;
 216         }
 217     }
 218     return 0;
 219 }
 220 
 221 /* --------------------------------------------------------------------------------------------- */
 222 
 223 Bool
 224 mc_XQueryPointer (Display *display, Window win, Window *root_return, Window *child_return,
     /* [previous][next][first][last][top][bottom][index][help]  */
 225                   int *root_x_return, int *root_y_return, int *win_x_return, int *win_y_return,
 226                   unsigned int *mask_return)
 227 {
 228     Bool retval;
 229 
 230     if (x11_available ())
 231     {
 232         if (setjmp (x11_exception) == 0)
 233         {
 234             longjmp_allowed = TRUE;
 235 
 236             retval = func_XQueryPointer (display, win, root_return, child_return, root_x_return,
 237                                          root_y_return, win_x_return, win_y_return, mask_return);
 238 
 239             longjmp_allowed = FALSE;
 240 
 241             return retval;
 242         }
 243     }
 244     *root_return = None;
 245     *child_return = None;
 246     *root_x_return = 0;
 247     *root_y_return = 0;
 248     *win_x_return = 0;
 249     *win_y_return = 0;
 250     *mask_return = 0;
 251     return False;
 252 }
 253 
 254 /* --------------------------------------------------------------------------------------------- */

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