--- /dev/null
+/* $scrotwm$ */
+/*
+ * Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
+ * Copyright (c) 2009 Ryan McBride <mcbride@countersiege.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (C) 2005-2007 Carsten Haitzler
+ * Copyright (C) 2006-2007 Kim Woelders
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies of the Software, its documentation and marketing & publicity
+ * materials, and acknowledgment shall be given in the documentation, materials
+ * and software packages that this Software was used.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * Basic hack mechanism (dlopen etc.) taken from e_hack.c in e17.
+ */
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <X11/Xlib.h>
+#include <X11/X.h>
+#include <X11/Xatom.h>
+
+/* dlopened xlib so we can find the symbols in the real xlib to call them */
+static void *lib_xlib = NULL;
+
+static Window root = None;
+
+/* Find our root window */
+static Window
+MyRoot(Display * dpy)
+{
+ char *s;
+
+ if (root != None)
+ return root;
+
+ root = DefaultRootWindow(dpy);
+
+ s = getenv("ENL_WM_ROOT");
+ if (!s)
+ return root;
+
+ sscanf(s, "%lx", &root);
+ return root;
+}
+
+#define SWM_PROPLEN (16)
+void
+set_property(Display *dpy, Window id, char *name, char *val)
+{
+ Atom atom = 0;
+ char prop[SWM_PROPLEN];
+
+ /* Try to update the window's workspace property */
+ atom = XInternAtom(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);
+}
+
+typedef Window(CWF) (Display * _display, Window _parent, int _x,
+ int _y, unsigned int _width,
+ unsigned int _height,
+ unsigned int _border_width, int _depth,
+ unsigned int _class, Visual * _visual,
+ unsigned long _valuemask,
+ XSetWindowAttributes * _attributes);
+
+/* XCreateWindow intercept hack */
+Window
+XCreateWindow(Display * display, Window parent, int x, int y,
+ unsigned int width, unsigned int height,
+ unsigned int border_width,
+ int depth, unsigned int clss, Visual * visual,
+ unsigned long valuemask, XSetWindowAttributes * attributes)
+{
+ static CWF *func = NULL;
+ 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)
+ func = (CWF *) dlsym(lib_xlib, "XCreateWindow");
+
+ if (parent == DefaultRootWindow(display))
+ parent = MyRoot(display);
+
+ id = (*func) (display, 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_PID")) != NULL)
+ set_property(display, id, "_SWM_PID", env);
+ }
+ return (id);
+}
+
+typedef Window(CSWF) (Display * _display, Window _parent, int _x,
+ int _y, unsigned int _width,
+ unsigned int _height,
+ unsigned int _border_width,
+ unsigned long _border,
+ unsigned long _background);
+
+/* XCreateSimpleWindow intercept hack */
+Window
+XCreateSimpleWindow(Display * display, Window parent, int x, int y,
+ unsigned int width, unsigned int height,
+ unsigned int border_width,
+ unsigned long border, unsigned long background)
+{
+ static CSWF *func = NULL;
+ 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)
+ func = (CSWF *) dlsym(lib_xlib, "XCreateSimpleWindow");
+
+ if (parent == DefaultRootWindow(display))
+ parent = MyRoot(display);
+
+ id = (*func) (display, 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_PID")) != NULL)
+ set_property(display, id, "_SWM_PID", env);
+ }
+ return (id);
+}
+
+typedef int (RWF) (Display * _display, Window _window, Window _parent,
+ int x, int y);
+
+/* XReparentWindow intercept hack */
+int
+XReparentWindow(Display * display, 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)
+ func = (RWF *) dlsym(lib_xlib, "XReparentWindow");
+
+ if (parent == DefaultRootWindow(display))
+ parent = MyRoot(display);
+
+ return (*func) (display, window, parent, x, y);
+}
#define SWM_D_MOVE 0x0010
#define SWM_D_STACK 0x0020
#define SWM_D_MOUSE 0x0040
+#define SWM_D_PROP 0x0080
+
u_int32_t swm_debug = 0
| SWM_D_MISC
| SWM_D_FOCUS
| SWM_D_MOVE
| SWM_D_STACK
+ | SWM_D_PROP
;
#else
#define DPRINTF(x...)
#define WIDTH(r) (r)->g.w
#define HEIGHT(r) (r)->g.h
+#ifndef SWM_LIB
+#define SWM_LIB "/usr/X11R6/lib/swmhack.so"
+#endif
+
+#define SWM_PROPLEN (16)
+
char **start_argv;
Atom astate;
int (*xerrorxlib)(Display *, XErrorEvent *);
} else {
/* otherwise, choose a region based on pointer location */
TAILQ_FOREACH(r, &screens[i].rl, entry) {
- if (x > X(r) && x < X(r) + WIDTH(r) &&
- y > Y(r) && y < Y(r) + HEIGHT(r))
+ if (x >= X(r) && x <= X(r) + WIDTH(r) &&
+ y >= Y(r) && y <= Y(r) + HEIGHT(r))
break;
}
*/
if (fork() == 0) {
if (fork() == 0) {
+ char *ret;
if (display)
close(ConnectionNumber(display));
+ setenv("LD_PRELOAD", SWM_LIB, 1);
+ if (asprintf(&ret, "%d", r->ws->idx))
+ setenv("_SWM_WS", ret, 1);
+ if (asprintf(&ret, "%d", getpid()))
+ setenv("_SWM_PID", ret, 1);
setsid();
execvp(args->argv[0], args->argv);
fprintf(stderr, "execvp failed\n");
struct ws_win *win = cur_focus;
struct workspace *ws, *nws;
Atom ws_idx_atom = 0;
- unsigned char ws_idx_str[1];
+ unsigned char ws_idx_str[SWM_PROPLEN];
DNPRINTF(SWM_D_MOVE, "send_to_ws: win: %lu\n", win->id);
/* Try to update the window's workspace property */
ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
- ws_idx_str[0] = (unsigned char)nws->idx;
- XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
- PropModeReplace, ws_idx_str, 1);
+ if (ws_idx_atom &&
+ snprintf(ws_idx_str, SWM_PROPLEN, "%d", nws->idx) < SWM_PROPLEN) {
+ DNPRINTF(SWM_D_PROP, "setting property _SWM_WS to %s\n",
+ ws_idx_str);
+ XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
+ PropModeReplace, ws_idx_str, SWM_PROPLEN);
+ }
if (count_win(nws, 1) == 1)
nws->focus = win;
int format;
unsigned long nitems, bytes;
Atom ws_idx_atom = 0, type;
- unsigned char ws_idx_str[1], *prop = NULL;
+ unsigned char ws_idx_str[SWM_PROPLEN], *prop = NULL;
struct swm_region *r;
if ((win = find_window(id)) != NULL)
ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
if (ws_idx_atom)
- XGetWindowProperty(display, id, ws_idx_atom, 0, 1, False, XA_STRING,
- &type, &format, &nitems, &bytes, &prop);
+ XGetWindowProperty(display, id, ws_idx_atom, 0, SWM_PROPLEN,
+ False, XA_STRING, &type, &format, &nitems, &bytes, &prop);
XGetWindowAttributes(display, id, &win->wa);
r = root_to_region(win->wa.root);
/* If the window was managed before, put it in the same workspace */
- if (prop)
- ws = &r->s->ws[prop[0]];
- else
+ if (prop) {
+ int ws_idx;
+ const char *errstr;
+
+ DNPRINTF(SWM_D_PROP, "got property _SWM_WS=%s\n", prop);
+ ws_idx = strtonum(prop, 0, 9, &errstr);
+ if (errstr)
+ DNPRINTF(SWM_D_EVENT, "window idx is %s: %s",
+ errstr, prop);
+ ws = &r->s->ws[ws_idx];
+ } else
ws = r->ws;
win->id = id;
win->g.x = win->wa.x;
win->g.y = win->wa.y;
- if (ws_idx_atom && prop == NULL) {
- /* set the window's workspace property if it wasn't there */
- ws_idx_str[0] = (unsigned char)ws->idx;
- XChangeProperty(display, id, ws_idx_atom, XA_STRING, 1,
- PropModeReplace, ws_idx_str, 1);
+ if (ws_idx_atom && prop == NULL &&
+ snprintf(ws_idx_str, SWM_PROPLEN, "%d", ws->idx) < SWM_PROPLEN) {
+ DNPRINTF(SWM_D_PROP, "setting property _SWM_WS to %s\n",
+ ws_idx_str);
+ XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
+ PropModeReplace, ws_idx_str, SWM_PROPLEN);
}
+ XFree(prop);
/*
fprintf(stderr, "manage window: %d x %d y %d w %d h %d\n", win->id, win->g.x, win->g.y, win->g.w, win->g.h);