diff --git a/proto.h b/proto.h index 7379027..ec1b953 100644 --- a/proto.h +++ b/proto.h @@ -2,6 +2,7 @@ void catch_exit(int sig); int execsh(char *cmd); void exec_cmd(char *cmd); int oops(Display *d, XErrorEvent *ee); +void query_windows(); unsigned int color_name_to_pixel(const char *name); int window_get_prop(Window w, Atom prop, Atom *type, int *items, void *buffer, int bytes); int window_get_atom_prop(Window w, Atom atom, Atom *list, int count); @@ -16,14 +17,13 @@ void client_free(client *c); void stack_free(stack *s); int client_has_state(client *c, Atom state); int client_toggle_state(client *c, Atom state); -void query_visible_windows(stack *s); int window_send_clientmessage(Window target, Window subject, Atom atom, unsigned long protocol, unsigned long mask); int client_send_wm_protocol(client *c, Atom protocol); void client_close(client *c); void client_place_spot(client *c, int spot, int mon, int force); void client_spot_cycle(client *c); Window spot_focus_top_window(int spot, int mon, Window except); -void client_stack_family(client *c, stack *all, stack *raise); +void client_stack_family(client *c, stack *raise); void client_raise_family(client *c); void client_set_focus(client *c); void client_activate(client *c); diff --git a/xoat.c b/xoat.c index b0f9039..fc1862c 100644 --- a/xoat.c +++ b/xoat.c @@ -63,6 +63,26 @@ int oops(Display *d, XErrorEvent *ee) return xerror(display, ee); } +// build windows cache +void query_windows() +{ + if (windows.depth) return; + unsigned int nwins; int i; Window w1, w2, *wins; client *c; + if (XQueryTree(display, root, &w1, &w2, &wins, &nwins) && wins) + { + for (i = nwins-1; i > -1; i--) + { + if ((c = window_build_client(wins[i])) && c->visible && windows.depth < STACK) + { + windows.clients[windows.depth] = c; + windows.windows[windows.depth++] = wins[i]; + } + else client_free(c); + } + } + if (wins) XFree(wins); +} + unsigned int color_name_to_pixel(const char *name) { XColor color; Colormap map = DefaultColormap(display, DefaultScreen(display)); @@ -123,13 +143,11 @@ void window_set_window_prop(Window w, Atom prop, Window *values, int count) void ewmh_client_list() { - int i; client *c; stack all, wins; + int i; client *c; stack wins; memset(&wins, 0, sizeof(stack)); - query_visible_windows(&all); - for (i = all.depth-1; i > -1; i--) + for_windows_rev(i, c) if (c->manage) { - if (!((c = all.clients[i]) && c->manage)) continue; wins.clients[wins.depth] = c; wins.windows[wins.depth++] = c->window; } @@ -234,31 +252,6 @@ int client_toggle_state(client *c, Atom state) return rc; } -void query_visible_windows(stack *s) -{ - if (inplay.depth) // cached? - { - memmove(s, &inplay, sizeof(stack)); - return; - } - memset(s, 0, sizeof(stack)); - unsigned int nwins; int i; Window w1, w2, *wins; client *c; - if (XQueryTree(display, root, &w1, &w2, &wins, &nwins) && wins) - { - for (i = nwins-1; i > -1; i--) - { - if ((c = window_build_client(wins[i])) && c->visible && s->depth < STACK) - { - s->clients[s->depth] = c; - s->windows[s->depth++] = wins[i]; - } - else client_free(c); - } - } - if (wins) XFree(wins); - memmove(&inplay, s, sizeof(stack)); -} - int window_send_clientmessage(Window target, Window subject, Atom atom, unsigned long protocol, unsigned long mask) { XEvent e; memset(&e, 0, sizeof(XEvent)); @@ -296,7 +289,7 @@ void client_close(client *c) void client_place_spot(client *c, int spot, int mon, int force) { if (!c) return; - client *t; + int i; client *t; // try to center over our transient parent if (!force && c->transient && (t = window_build_client(c->transient))) @@ -309,16 +302,11 @@ void client_place_spot(client *c, int spot, int mon, int force) // try to center over top-most window in our group if (!force && c->leader && c->type == atoms[_NET_WM_WINDOW_TYPE_DIALOG]) { - int i; stack wins; - query_visible_windows(&wins); - for (i = 0; i < wins.depth; i++) + for_windows(i, t) if (t->manage && t->window != c->window && t->leader == c->leader) { - if ((t = wins.clients[i]) && t->manage && t->window != c->window && t->leader == c->leader) - { - spot = t->spot; - mon = t->monitor; - break; - } + spot = t->spot; + mon = t->monitor; + break; } } c->spot = spot; c->monitor = mon; @@ -389,11 +377,8 @@ void client_spot_cycle(client *c) if (!c) return; spot_focus_top_window(c->spot, c->monitor, c->window); - stack lower; memset(&lower, 0, sizeof(stack)); - stack all; query_visible_windows(&all); - - client_stack_family(c, &all, &lower); + client_stack_family(c, &lower); XLowerWindow(display, lower.windows[0]); XRestackWindows(display, lower.windows, lower.depth); } @@ -401,10 +386,9 @@ void client_spot_cycle(client *c) Window spot_focus_top_window(int spot, int mon, Window except) { int i; client *c; - stack wins; query_visible_windows(&wins); - for (i = 0; i < wins.depth; i++) + for_windows(i, c) { - if ((c = wins.clients[i]) && c->window != except && c->manage && c->spot == spot && c->monitor == mon) + if (c->window != except && c->manage && c->spot == spot && c->monitor == mon) { client_raise_family(c); client_set_focus(c); @@ -414,15 +398,15 @@ Window spot_focus_top_window(int spot, int mon, Window except) return None; } -void client_stack_family(client *c, stack *all, stack *raise) +void client_stack_family(client *c, stack *raise) { int i; client *o, *self = NULL; - for (i = 0; i < all->depth; i++) + for_windows(i, o) { - if ((o = all->clients[i]) && o->manage && o->visible && o->transient == c->window) - client_stack_family(o, all, raise); + if (o->manage && o->visible && o->transient == c->window) + client_stack_family(o, raise); else - if (o && o->visible && o->window == c->window) + if (o->visible && o->window == c->window) self = o; } if (self) @@ -436,28 +420,22 @@ void client_raise_family(client *c) { if (!c) return; - int i; client *o; stack raise, all, family; + int i; client *o; stack raise, family; memset(&raise, 0, sizeof(stack)); memset(&family, 0, sizeof(stack)); - query_visible_windows(&all); - for (i = 0; i < all.depth; i++) - if ((o = all.clients[i]) && o->type == atoms[_NET_WM_WINDOW_TYPE_DOCK]) - client_stack_family(o, &all, &raise); + for_windows(i, o) if (o->type == atoms[_NET_WM_WINDOW_TYPE_DOCK]) + client_stack_family(o, &raise); // above only counts for fullscreen windows if (client_has_state(c, atoms[_NET_WM_STATE_FULLSCREEN])) - for (i = 0; i < all.depth; i++) - if ((o = all.clients[i]) && client_has_state(o, atoms[_NET_WM_STATE_ABOVE])) - client_stack_family(o, &all, &raise); + for_windows(i, o) if (client_has_state(o, atoms[_NET_WM_STATE_ABOVE])) + client_stack_family(o, &raise); - while (c->transient) - { - client *t = window_build_client(c->transient); - if (t) c = family.clients[family.depth++] = t; - } + while (c->transient && (o = window_build_client(c->transient))) + c = family.clients[family.depth++] = o; - client_stack_family(c, &all, &raise); + client_stack_family(c, &raise); XRaiseWindow(display, raise.windows[0]); XRestackWindows(display, raise.windows, raise.depth); stack_free(&family); @@ -540,11 +518,9 @@ void action_command(void *data, int num, client *cli) void action_find_or_start(void *data, int num, client *cli) { int i; client *c; char *class = data; - stack all; query_visible_windows(&all); - for (i = 0; i < all.depth; i++) - if ((c = all.clients[i]) && c->manage && !strcasecmp(c->class, class)) - { client_activate(c); return; } + for_windows(i, c) if (c->manage && !strcasecmp(c->class, class)) + { client_activate(c); return; } exec_cmd(class); } @@ -593,16 +569,13 @@ void action_above(void *data, int num, client *cli) void action_snapshot(void *data, int num, client *cli) { - int i; client *c; stack wins; + int i; client *c; stack_free(&snapshot); - query_visible_windows(&wins); - for (i = 0; i < wins.depth; i++) + + for_windows(i, c) if (c->manage) { - if ((c = wins.clients[i]) && c->manage) - { - snapshot.clients[snapshot.depth] = window_build_client(c->window); - snapshot.windows[snapshot.depth++] = c->window; - } + snapshot.clients[snapshot.depth] = window_build_client(c->window); + snapshot.windows[snapshot.depth++] = c->window; } } @@ -820,7 +793,7 @@ handler handlers[LASTEvent] = { int main(int argc, char *argv[]) { - int i, j; client *c; XEvent ev; stack wins; + int i, j; client *c; XEvent ev; if (!(display = XOpenDisplay(0))) return 1; @@ -843,16 +816,12 @@ int main(int argc, char *argv[]) } // default non-multi-head setup - memset(monitors, 0, sizeof(monitors)); monitors[0].w = WidthOfScreen(DefaultScreenOfDisplay(display)); monitors[0].h = HeightOfScreen(DefaultScreenOfDisplay(display)); // detect panel struts - query_visible_windows(&wins); - for (i = 0; i < wins.depth; i++) + for_windows(i, c) { - if (!(c = wins.clients[i])) continue; - wm_strut strut; memset(&strut, 0, sizeof(wm_strut)); if (window_get_cardinal_prop(c->window, atoms[_NET_WM_STRUT_PARTIAL], (unsigned long*)&strut, 12) || window_get_cardinal_prop(c->window, atoms[_NET_WM_STRUT], (unsigned long*)&strut, 4)) @@ -863,7 +832,6 @@ int main(int argc, char *argv[]) struts.bottom = MIN(MAX_STRUT, MAX(struts.bottom, strut.bottom)); } } - stack_free(&inplay); // support multi-head. XineramaScreenInfo *info; @@ -948,12 +916,9 @@ int main(int argc, char *argv[]) XGrabButton(display, Button3, AnyModifier, root, True, ButtonPressMask, GrabModeSync, GrabModeSync, None, None); // setup existing managable windows - memset(&snapshot, 0, sizeof(stack)); - query_visible_windows(&wins); - for (i = 0; i < wins.depth; i++) + stack_free(&windows); + for_windows(i, c) if (c->manage) { - if (!(c = wins.clients[i]) || !c->manage) continue; - window_listen(c->window); client_update_border(c); client_place_spot(c, c->spot, c->monitor, 0); @@ -965,7 +930,7 @@ int main(int argc, char *argv[]) // main event loop for (;;) { - stack_free(&inplay); + stack_free(&windows); XNextEvent(display, &ev); if (handlers[ev.type]) handlers[ev.type](&ev); diff --git a/xoat.h b/xoat.h index 7691ae6..76fb166 100644 --- a/xoat.h +++ b/xoat.h @@ -110,7 +110,15 @@ typedef struct { short current_spot = 0, current_mon = 0; Window current = None; -stack inplay, snapshot; +stack windows, snapshot; + +#define for_windows(i,c)\ + for ((i) = 0, query_windows(); (i) < windows.depth; (i)++)\ + if (((c) = windows.clients[(i)])) + +#define for_windows_rev(i,c)\ + for ((i) = windows.depth-1, query_windows(); (i) > -1; (i)--)\ + if (((c) = windows.clients[(i)])) static int (*xerror)(Display *, XErrorEvent *); @@ -190,3 +198,9 @@ typedef struct { void *data; int num; } binding; + + + + + +