]> code.delx.au - spectrwm/blobdiff - lib/swm_hack.c
Pacify -Wconditional-uninitialized warnings.
[spectrwm] / lib / swm_hack.c
index 459d8800cffb28f304b43c01a5b9dfaaf76eab0c..04be57be2cc24545141478cf2386aad509618f42 100644 (file)
@@ -1,4 +1,3 @@
-/* $scrotwm$ */
 /*
  * Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
  * Copyright (c) 2009 Ryan McBride <mcbride@countersiege.com>
  * Basic hack mechanism (dlopen etc.) taken from e_hack.c in e17.
  */
 #include <string.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <dlfcn.h>
 #include <X11/Xlib.h>
 #include <X11/X.h>
 #include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
 
-/* dlopened xlib so we can find the symbols in the real xlib to call them */
-static void        *lib_xlib = NULL;
+/* dlopened libs so we can find the symbols in the real one to call them */
+static void            *lib_xlib = NULL;
+static void            *lib_xtlib = NULL;
 
-static Window       root = None;
+static Window          root = None;
+static bool            xterm = false;
+static Display         *display = NULL;
+
+void   set_property(Display *, Window, char *, char *);
+
+#ifdef _GNU_SOURCE
+#define DLOPEN(s)      RTLD_NEXT
+#else
+#define DLOPEN(s)      dlopen((s), RTLD_GLOBAL | RTLD_LAZY)
+#endif
 
 /* Find our root window */
 static              Window
@@ -66,26 +78,50 @@ MyRoot(Display * dpy)
        root = DefaultRootWindow(dpy);
 
        s = getenv("ENL_WM_ROOT");
-       if (!s)
+       if (s == NULL)
                return root;
 
        sscanf(s, "%lx", &root);
        return root;
 }
 
+
+typedef Atom   (XIA) (Display *display, char *atom_name, Bool
+                   only_if_exists);
+
+typedef int    (XCP) (Display *display, Window w, Atom property,
+                   Atom type, int format, int mode, unsigned char *data,
+                   int nelements);
+
 #define SWM_PROPLEN    (16)
 void
 set_property(Display *dpy, Window id, char *name, char *val)
 {
        Atom                    atom = 0;
        char                    prop[SWM_PROPLEN];
+       static XIA              *xia = NULL;
+       static XCP              *xcp = NULL;
+
+       if (lib_xlib == NULL)
+               lib_xlib = DLOPEN("libX11.so");
+       if (lib_xlib) {
+               if (xia == NULL)
+                       xia = (XIA *) dlsym(lib_xlib, "XInternAtom");
+               if (xcp == NULL)
+                       xcp = (XCP *) dlsym(lib_xlib, "XChangeProperty");
+       }
+       if (xia == NULL || xcp == NULL) {
+               fprintf(stderr, "libswmhack.so: ERROR: %s\n", dlerror());
+               return;
+       }
 
        /* Try to update the window's workspace property */
-       atom = XInternAtom(dpy, name, False);
-       if (atom) 
+       atom = (*xia)(dpy, name, False);
+       if (atom)
                if (snprintf(prop, SWM_PROPLEN, "%s", val) < SWM_PROPLEN)
-                       XChangeProperty(dpy, id, atom, XA_STRING,
-                           8, PropModeReplace, prop, SWM_PROPLEN);
+                       (*xcp)(dpy, id, atom, XA_STRING,
+                           8, PropModeReplace, (unsigned char *)prop,
+                           strlen((char *)prop));
 }
 
 typedef             Window(CWF) (Display * _display, Window _parent, int _x,
@@ -98,7 +134,7 @@ typedef             Window(CWF) (Display * _display, Window _parent, int _x,
 
 /* XCreateWindow intercept hack */
 Window
-XCreateWindow(Display * display, Window parent, int x, int y,
+XCreateWindow(Display *dpy, Window parent, int x, int y,
    unsigned int width, unsigned int height,
    unsigned int border_width,
    int depth, unsigned int clss, Visual * visual,
@@ -108,23 +144,32 @@ XCreateWindow(Display * display, Window parent, int x, int y,
        char            *env;
        Window          id;
 
-       /* find the real Xlib and the real X function */
-       if (!lib_xlib)
-               lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
-       if (!func)
+       if (lib_xlib == NULL)
+               lib_xlib = DLOPEN("libX11.so");
+       if (lib_xlib && func == NULL) {
                func = (CWF *) dlsym(lib_xlib, "XCreateWindow");
+               display = dpy;
+       }
+       if (func == NULL) {
+               fprintf(stderr, "libswmhack.so: ERROR: %s\n", dlerror());
+               return None;
+       }
 
-       if (parent == DefaultRootWindow(display))
-               parent = MyRoot(display);
-       
-       id = (*func) (display, parent, x, y, width, height, border_width,
+       if (parent == DefaultRootWindow(dpy))
+               parent = MyRoot(dpy);
+
+       id = (*func) (dpy, parent, x, y, width, height, border_width,
            depth, clss, visual, valuemask, attributes);
 
        if (id) {
-               if ((env = getenv("_SWM_WS")) != NULL) 
-                       set_property(display, id, "_SWM_WS", env);
+               if ((env = getenv("_SWM_WS")) != NULL)
+                       set_property(dpy, id, "_SWM_WS", env);
                if ((env = getenv("_SWM_PID")) != NULL)
-                       set_property(display, id, "_SWM_PID", env);
+                       set_property(dpy, id, "_SWM_PID", env);
+               if ((env = getenv("_SWM_XTERM_FONTADJ")) != NULL) {
+                       unsetenv("_SWM_XTERM_FONTADJ");
+                       xterm = true;
+               }
        }
        return (id);
 }
@@ -138,7 +183,7 @@ typedef             Window(CSWF) (Display * _display, Window _parent, int _x,
 
 /* XCreateSimpleWindow intercept hack */
 Window
-XCreateSimpleWindow(Display * display, Window parent, int x, int y,
+XCreateSimpleWindow(Display *dpy, Window parent, int x, int y,
     unsigned int width, unsigned int height,
     unsigned int border_width,
     unsigned long border, unsigned long background)
@@ -147,23 +192,30 @@ XCreateSimpleWindow(Display * display, Window parent, int x, int y,
        char            *env;
        Window          id;
 
-       /* find the real Xlib and the real X function */
-       if (!lib_xlib)
-               lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
-       if (!func)
+       if (lib_xlib == NULL)
+               lib_xlib = DLOPEN("libX11.so");
+       if (lib_xlib && func == NULL)
                func = (CSWF *) dlsym(lib_xlib, "XCreateSimpleWindow");
+       if (func == NULL) {
+               fprintf(stderr, "libswmhack.so: ERROR: %s\n", dlerror());
+               return None;
+       }
 
-       if (parent == DefaultRootWindow(display))
-               parent = MyRoot(display);
+       if (parent == DefaultRootWindow(dpy))
+               parent = MyRoot(dpy);
 
-       id = (*func) (display, parent, x, y, width, height,
+       id = (*func) (dpy, parent, x, y, width, height,
            border_width, border, background);
 
        if (id) {
-               if ((env = getenv("_SWM_WS")) != NULL) 
-                       set_property(display, id, "_SWM_WS", env);
+               if ((env = getenv("_SWM_WS")) != NULL)
+                       set_property(dpy, id, "_SWM_WS", env);
                if ((env = getenv("_SWM_PID")) != NULL)
-                       set_property(display, id, "_SWM_PID", env);
+                       set_property(dpy, id, "_SWM_PID", env);
+               if ((env = getenv("_SWM_XTERM_FONTADJ")) != NULL) {
+                       unsetenv("_SWM_XTERM_FONTADJ");
+                       xterm = true;
+               }
        }
        return (id);
 }
@@ -173,18 +225,66 @@ typedef int         (RWF) (Display * _display, Window _window, Window _parent,
 
 /* XReparentWindow intercept hack */
 int
-XReparentWindow(Display * display, Window window, Window parent, int x, int y)
+XReparentWindow(Display *dpy, Window window, Window parent, int x, int y)
 {
        static RWF         *func = NULL;
 
-       /* find the real Xlib and the real X function */
-       if (!lib_xlib)
-               lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
-       if (!func)
+       if (lib_xlib == NULL)
+               lib_xlib = DLOPEN("libX11.so");
+       if (lib_xlib && func == NULL)
                func = (RWF *) dlsym(lib_xlib, "XReparentWindow");
+       if (func == NULL) {
+               fprintf(stderr, "libswmhack.so: ERROR: %s\n", dlerror());
+               /* Xlib function always returns 1, so return 0 here. */
+               return 0;
+       }
+
+       if (parent == DefaultRootWindow(dpy))
+               parent = MyRoot(dpy);
+
+       return (*func) (dpy, window, parent, x, y);
+}
+
+typedef                void (ANEF) (XtAppContext app_context, XEvent *event_return);
+int            evcount = 0;
+
+/*
+ * XtAppNextEvent Intercept Hack
+ * Normally xterm rejects "synthetic" (XSendEvent) events to prevent spoofing.
+ * We don't want to disable this completely, it's insecure. But hook here
+ * and allow these mostly harmless ones that we use to adjust fonts.
+ */
+void
+XtAppNextEvent(XtAppContext app_context, XEvent *event_return)
+{
+       static ANEF     *func = NULL;
+       static KeyCode  kp_add = 0, kp_subtract = 0;
+
+       if (lib_xtlib == NULL)
+               lib_xtlib = DLOPEN("libXt.so");
+       if (lib_xtlib && func == NULL) {
+               func = (ANEF *) dlsym(lib_xtlib, "XtAppNextEvent");
+               if (display) {
+                       kp_add = XKeysymToKeycode(display, XK_KP_Add);
+                       kp_subtract = XKeysymToKeycode(display, XK_KP_Subtract);
+               }
+       }
+       if (func == NULL) {
+               fprintf(stderr, "libswmhack.so: ERROR: %s\n", dlerror());
+               return;
+       }
+
+       (*func) (app_context, event_return);
 
-       if (parent == DefaultRootWindow(display))
-               parent = MyRoot(display);
+       /* Return here if it's not an Xterm. */
+       if (!xterm)
+               return;
 
-       return (*func) (display, window, parent, x, y);
+       /* Allow spoofing of font change keystrokes. */
+       if ((event_return->type == KeyPress ||
+          event_return->type == KeyRelease) &&
+          event_return->xkey.state == ShiftMask &&
+          (event_return->xkey.keycode == kp_add ||
+          event_return->xkey.keycode == kp_subtract))
+               event_return->xkey.send_event = 0;
 }