]> code.delx.au - spectrwm/blob - lib/swm_hack.c
Let scrotwm adjust the font size on xterms as it squishes them in tiling
[spectrwm] / lib / swm_hack.c
1 /* $scrotwm$ */
2 /*
3 * Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
4 * Copyright (c) 2009 Ryan McBride <mcbride@countersiege.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 /*
19 * Copyright (C) 2005-2007 Carsten Haitzler
20 * Copyright (C) 2006-2007 Kim Woelders
21 *
22 * Permission is hereby granted, free of charge, to any person obtaining a copy
23 * of this software and associated documentation files (the "Software"), to
24 * deal in the Software without restriction, including without limitation the
25 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
26 * sell copies of the Software, and to permit persons to whom the Software is
27 * furnished to do so, subject to the following conditions:
28 *
29 * The above copyright notice and this permission notice shall be included in
30 * all copies of the Software, its documentation and marketing & publicity
31 * materials, and acknowledgment shall be given in the documentation, materials
32 * and software packages that this Software was used.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
37 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
38 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 */
41 /*
42 * Basic hack mechanism (dlopen etc.) taken from e_hack.c in e17.
43 */
44 #include <string.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <dlfcn.h>
48 #include <X11/Xlib.h>
49 #include <X11/X.h>
50 #include <X11/Xatom.h>
51 #include <X11/Intrinsic.h>
52
53 /* dlopened libs so we can find the symbols in the real one to call them */
54 static void *lib_xlib = NULL;
55 static void *lib_xtlib = NULL;
56
57 static Window root = None;
58 static int xterm = 0;
59 static Display *dpy = NULL;
60
61 /* Find our root window */
62 static Window
63 MyRoot(Display * dpy)
64 {
65 char *s;
66
67 if (root != None)
68 return root;
69
70 root = DefaultRootWindow(dpy);
71
72 s = getenv("ENL_WM_ROOT");
73 if (!s)
74 return root;
75
76 sscanf(s, "%lx", &root);
77 return root;
78 }
79
80 #define SWM_PROPLEN (16)
81 void
82 set_property(Display *dpy, Window id, char *name, char *val)
83 {
84 Atom atom = 0;
85 char prop[SWM_PROPLEN];
86
87 /* Try to update the window's workspace property */
88 atom = XInternAtom(dpy, name, False);
89 if (atom)
90 if (snprintf(prop, SWM_PROPLEN, "%s", val) < SWM_PROPLEN)
91 XChangeProperty(dpy, id, atom, XA_STRING,
92 8, PropModeReplace, prop, SWM_PROPLEN);
93 }
94
95 typedef Window(CWF) (Display * _display, Window _parent, int _x,
96 int _y, unsigned int _width,
97 unsigned int _height,
98 unsigned int _border_width, int _depth,
99 unsigned int _class, Visual * _visual,
100 unsigned long _valuemask,
101 XSetWindowAttributes * _attributes);
102
103 /* XCreateWindow intercept hack */
104 Window
105 XCreateWindow(Display * display, Window parent, int x, int y,
106 unsigned int width, unsigned int height,
107 unsigned int border_width,
108 int depth, unsigned int clss, Visual * visual,
109 unsigned long valuemask, XSetWindowAttributes * attributes)
110 {
111 static CWF *func = NULL;
112 char *env;
113 Window id;
114
115 /* find the real Xlib and the real X function */
116 if (!lib_xlib)
117 lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
118 if (!func) {
119 func = (CWF *) dlsym(lib_xlib, "XCreateWindow");
120 dpy = display;
121 }
122
123 if (parent == DefaultRootWindow(display))
124 parent = MyRoot(display);
125
126 id = (*func) (display, parent, x, y, width, height, border_width,
127 depth, clss, visual, valuemask, attributes);
128
129 if (id) {
130 if ((env = getenv("_SWM_WS")) != NULL)
131 set_property(display, id, "_SWM_WS", env);
132 if ((env = getenv("_SWM_PID")) != NULL)
133 set_property(display, id, "_SWM_PID", env);
134 if ((env = getenv("_SWM_XTERM_FONTADJ")) != NULL) {
135 unsetenv("_SWM_XTERM_FONTADJ");
136 xterm = 1;
137 }
138 }
139 return (id);
140 }
141
142 typedef Window(CSWF) (Display * _display, Window _parent, int _x,
143 int _y, unsigned int _width,
144 unsigned int _height,
145 unsigned int _border_width,
146 unsigned long _border,
147 unsigned long _background);
148
149 /* XCreateSimpleWindow intercept hack */
150 Window
151 XCreateSimpleWindow(Display * display, Window parent, int x, int y,
152 unsigned int width, unsigned int height,
153 unsigned int border_width,
154 unsigned long border, unsigned long background)
155 {
156 static CSWF *func = NULL;
157 char *env;
158 Window id;
159
160 /* find the real Xlib and the real X function */
161 if (!lib_xlib)
162 lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
163 if (!func)
164 func = (CSWF *) dlsym(lib_xlib, "XCreateSimpleWindow");
165
166 if (parent == DefaultRootWindow(display))
167 parent = MyRoot(display);
168
169 id = (*func) (display, parent, x, y, width, height,
170 border_width, border, background);
171
172 if (id) {
173 if ((env = getenv("_SWM_WS")) != NULL)
174 set_property(display, id, "_SWM_WS", env);
175 if ((env = getenv("_SWM_PID")) != NULL)
176 set_property(display, id, "_SWM_PID", env);
177 if ((env = getenv("_SWM_XTERM_FONTADJ")) != NULL) {
178 unsetenv("_SWM_XTERM_FONTADJ");
179 xterm = 1;
180 }
181 }
182 return (id);
183 }
184
185 typedef int (RWF) (Display * _display, Window _window, Window _parent,
186 int x, int y);
187
188 /* XReparentWindow intercept hack */
189 int
190 XReparentWindow(Display * display, Window window, Window parent, int x, int y)
191 {
192 static RWF *func = NULL;
193
194 /* find the real Xlib and the real X function */
195 if (!lib_xlib)
196 lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
197 if (!func)
198 func = (RWF *) dlsym(lib_xlib, "XReparentWindow");
199
200 if (parent == DefaultRootWindow(display))
201 parent = MyRoot(display);
202
203 return (*func) (display, window, parent, x, y);
204 }
205
206 typedef void (ANEF) (XtAppContext app_context, XEvent *event_return);
207 int evcount = 0;
208
209 /*
210 * XtAppNextEvent Intercept Hack
211 * Normally xterm rejects "synthetic" (XSendEvent) events to prevent spoofing.
212 * We don't want to disable this completely, it's insecure. But hook here
213 * and allow these mostly harmless ones that we use to adjust fonts.
214 */
215 void
216 XtAppNextEvent(XtAppContext app_context, XEvent *event_return)
217 {
218 static ANEF *func = NULL;
219 static int kp_add = 0, kp_subtract = 0;
220
221 /* find the real Xlib and the real X function */
222 if (!lib_xtlib)
223 lib_xtlib = dlopen("libXt.so", RTLD_GLOBAL | RTLD_LAZY);
224 if (!func) {
225 func = (ANEF *) dlsym(lib_xtlib, "XtAppNextEvent");
226 if (dpy != NULL) {
227 kp_add = XKeysymToKeycode(dpy, XK_KP_Add);
228 kp_subtract = XKeysymToKeycode(dpy, XK_KP_Subtract);
229 }
230 }
231
232 (*func) (app_context, event_return);
233
234 /* Return here if it's not an Xterm. */
235 if (!xterm)
236 return;
237
238 /* Allow spoofing of font change keystrokes. */
239 if ((event_return->type == KeyPress ||
240 event_return->type == KeyRelease) &&
241 event_return->xkey.state == ShiftMask &&
242 (event_return->xkey.keycode == kp_add ||
243 event_return->xkey.keycode == kp_subtract))
244 event_return->xkey.send_event = 0;
245 }