diff
wm.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 75 insertions(+), 12 deletions(-)
diff --git a/wm.c b/wm.c
index 12c97de..f7a3f2b 100644
--- a/wm.c
+++ b/wm.c
@@ -8,9 +8,11 @@
#define cmd_move 2
#define cmd_kill 3
#define num_workspaces 9
+#define modifier_variants 4
static Window windows[max_windows];
static int window_workspace[max_windows], window_count, current_workspace;
+static int is_root_child(Display *display, Window root_window, Window window);
static int
get_window_index(Window window)
@@ -27,6 +29,57 @@ get_window_index(Window window)
return window_count++;
}
+static void
+remove_window(Window window)
+{
+ int i;
+
+ for (i = 0; i < window_count; i++) {
+ if (windows[i] == window) {
+ for (; i < window_count - 1; i++) {
+ windows[i] = windows[i + 1];
+ window_workspace[i] = window_workspace[i + 1];
+ }
+ window_count--;
+ return;
+ }
+ }
+}
+
+static void
+grab_button_variants(Display *display, unsigned int button, unsigned int modifiers,
+ Window root_window, int pointer_mode)
+{
+ unsigned int extra_mods[modifier_variants];
+ int i;
+
+ extra_mods[0] = 0;
+ extra_mods[1] = LockMask;
+ extra_mods[2] = Mod2Mask;
+ extra_mods[3] = LockMask | Mod2Mask;
+ for (i = 0; i < modifier_variants; i++)
+ XGrabButton(display, button, modifiers | extra_mods[i], root_window, True,
+ ButtonPressMask, pointer_mode, GrabModeAsync, None, None);
+}
+
+static void
+get_window_attrs(Display *display, Window window, XWindowAttributes *window_attrs)
+{
+ if (!XGetWindowAttributes(display, window, window_attrs))
+ window_attrs->override_redirect = True;
+}
+
+static int
+is_managed_window(Display *display, Window root_window, Window window)
+{
+ XWindowAttributes window_attrs;
+
+ if (!is_root_child(display, root_window, window))
+ return 0;
+ get_window_attrs(display, window, &window_attrs);
+ return !window_attrs.override_redirect;
+}
+
static void
track_windows(Display *display, Window root_window)
{
@@ -35,7 +88,8 @@ track_windows(Display *display, Window root_window)
if (XQueryTree(display, root_window, &root_return, &parent, &children, (unsigned int *)&j)) {
for (i = 0; i < j; i++)
- get_window_index(children[i]);
+ if (is_managed_window(display, root_window, children[i]))
+ get_window_index(children[i]);
if (children != None)
XFree(children);
}
@@ -64,6 +118,8 @@ show_workspace(Display *display, Window root_window)
if (XQueryTree(display, root_window, &root_return, &parent, &children, (unsigned int *)&j)) {
for (i = 0; i < j; i++) {
+ if (!is_managed_window(display, root_window, children[i]))
+ continue;
window_index = get_window_index(children[i]);
if (window_index >= 0) {
if (window_workspace[window_index] == current_workspace)
@@ -103,16 +159,9 @@ main(void)
ewmh_init(display, root_window);
ewmh_sync(display, root_window, windows, window_workspace, window_count);
- XGrabButton(display, 1, 0, root_window, True, ButtonPressMask, GrabModeAsync,
- GrabModeAsync, None, None);
- XGrabButton(display, 2, 0, root_window, True, ButtonPressMask, GrabModeAsync,
- GrabModeAsync, None, None);
- XGrabButton(display, 3, 0, root_window, True, ButtonPressMask, GrabModeAsync,
- GrabModeAsync, None, None);
- XGrabButton(display, 1, mod_key, root_window, True, ButtonPressMask, GrabModeAsync,
- GrabModeAsync, None, None);
- XGrabButton(display, 3, mod_key, root_window, True, ButtonPressMask, GrabModeAsync,
- GrabModeAsync, None, None);
+ grab_button_variants(display, 1, 0, root_window, GrabModeSync);
+ grab_button_variants(display, 1, mod_key, root_window, GrabModeAsync);
+ grab_button_variants(display, 3, mod_key, root_window, GrabModeAsync);
for (;;) {
XNextEvent(display, &event);
@@ -147,20 +196,32 @@ main(void)
}
}
}
+ } else if (event.type == DestroyNotify) {
+ remove_window(event.xdestroywindow.window);
+ ewmh_sync(display, root_window, windows, window_workspace, window_count);
} else if (event.type == ButtonPress && event.xbutton.subwindow != None) {
drag_window = event.xbutton.subwindow;
+ if (!is_managed_window(display, root_window, drag_window)) {
+ if (!(event.xbutton.state & mod_key))
+ XAllowEvents(display, ReplayPointer, event.xbutton.time);
+ continue;
+ }
ewmh_set_active_window(display, root_window, drag_window);
XSetInputFocus(display, drag_window, RevertToPointerRoot, CurrentTime);
j = get_window_index(drag_window);
if (j >= 0)
window_workspace[j] = current_workspace;
ewmh_sync(display, root_window, windows, window_workspace, window_count);
+ if (!(event.xbutton.state & mod_key) && event.xbutton.button == 1) {
+ XAllowEvents(display, ReplayPointer, event.xbutton.time);
+ continue;
+ }
if (!(event.xbutton.state & mod_key))
continue;
XGrabPointer(display, drag_window, True,
PointerMotionMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
- XGetWindowAttributes(display, drag_window, &window_attrs);
+ get_window_attrs(display, drag_window, &window_attrs);
drag_start = event.xbutton;
if (drag_start.button == 3) {
drag_start.x_root = window_attrs.x + window_attrs.width - 1;
@@ -169,6 +230,8 @@ main(void)
drag_start.x_root, drag_start.y_root);
}
is_dragging = 1;
+ } else if (event.type == ButtonPress && event.xbutton.subwindow == None) {
+ XAllowEvents(display, AsyncPointer, event.xbutton.time);
} else if (event.type == MotionNotify && is_dragging) {
int x_diff, y_diff;