#define MCLIENT(c) \
container_of(c, Client, mnode)
+#define Tiled_Clients \
+ (Desktops[Desktop].tiled)
+
+#define Floated_Clients \
+ (Desktops[Desktop].floated)
+
enum {
TOO_SMALL = (1 << 0),
FLOATING = (1 << 1),
struct {
Node *floated, *tiled;
} Desktops[10] = {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}};
-int Desktop = 0;
-
+int Desktop = 1;
XConf X = {0};
Node* All_Clients = NULL;
Cursor Move_Cursor;
Cursor Main_Cursor;
int StartY = 0;
-#define Tiled_Clients (Desktops[Desktop].tiled)
-#define Floated_Clients (Desktops[Desktop].floated)
-
/* configuration */
uint32_t BorderWidth = 1;
uint32_t BorderColor = 0xFF0000;
void client_to_desktop(const Arg arg);
#define MOD Mod1Mask
-
-// Avoid multiple paste
#define DESKTOPCHANGE(K,N) \
{ MOD, K, change_desktop, {.i = N}}, \
{ MOD|ShiftMask, K, client_to_desktop, {.i = N}},
-// Shortcuts
static struct key keys[] = {
// MOD KEY FUNCTION ARGS
-// { MOD, XK_c, spawn, {.com = lockcmd}},
-// { MOD, XK_p, spawn, {.com = dmenucmd}},
-// { MOD|ShiftMask, XK_Return, spawn, {.com = urxvtcmd}},
+// { MOD, XK_c, spawn, {.com = lockcmd}},
+// { MOD, XK_p, spawn, {.com = dmenucmd}},
+// { MOD|ShiftMask, XK_Return, spawn, {.com = urxvtcmd}},
+// { MOD|ShiftMask, XK_q, quit, {NULL}}
DESKTOPCHANGE( XK_0, 0)
DESKTOPCHANGE( XK_1, 1)
DESKTOPCHANGE( XK_2, 2)
DESKTOPCHANGE( XK_7, 7)
DESKTOPCHANGE( XK_8, 8)
DESKTOPCHANGE( XK_9, 9)
-// { MOD, XK_q, quit, {NULL}}
};
-void change_desktop(const Arg arg) {
- Desktop = arg.i;
-}
-
-void client_to_desktop(const Arg arg) {
- printf("send to desktop %d\n", arg.i);
-}
-
/* Utility Functions
*****************************************************************************/
void die(char* errstr) {
/* Client Handling
*****************************************************************************/
void client_reconfig(XConf* xs, Client* c);
+void client_config(XConf* xs, Client* c, int x, int y, int w, int h);
void* biggest(Node* node, void* accum) {
if (!accum || TCLIENT(node)->h > ((Client*)accum)->h)
return (c->flags & mask);
}
-void client_add(Client* parent, Client* c) {
+void client_raise(XConf* x, Client* c) {
+ XMapRaised(x->display, c->frame);
+ XMapRaised(x->display, c->win);
+}
+
+void client_add(Client* c, int dtop) {
list_add(&All_Clients, NULL, &(c->mnode));
- if (!client_flags(c, FLOATING))
- list_add(&Tiled_Clients, (parent ? &(parent->tnode) : NULL), &(c->tnode));
- else
- list_add(&Floated_Clients, NULL, &(c->tnode));
+ if (!client_flags(c, FLOATING)) {
+ Client* parent = list_reduce(Desktops[dtop].tiled, biggest, NULL);
+ list_add(&Desktops[dtop].tiled, (parent ? &(parent->tnode) : NULL), &(c->tnode));
+ if (parent) {
+ c->h = (parent->h - (parent->h / 2));
+ parent->h /= 2;
+ c->y = parent->y + parent->h;
+ client_config(&X, parent, parent->x, parent->y, parent->w, parent->h);
+ }
+ } else {
+ list_add(&Desktops[dtop].floated, NULL, &(c->tnode));
+ }
}
void client_del(Client* c) {
list_del(&All_Clients, &(c->mnode));
- if (!client_flags(c, FLOATING))
+ if (!client_flags(c, FLOATING)) {
list_del(&Tiled_Clients, &(c->tnode));
- else
+ int y = c->y, h = c->h;
+ Node* nsucc = (c->tnode.prev ? c->tnode.prev : c->tnode.next);
+ if (nsucc) {
+ Client* succ = TCLIENT(nsucc);
+ succ->h += h;
+ if (nsucc == c->tnode.next)
+ succ->y = y;
+ client_config(&X, succ, succ->x, succ->y, succ->w, succ->h);
+ client_raise(&X, succ);
+ }
+ } else {
list_del(&Floated_Clients, &(c->tnode));
+ }
}
void client_redraw(XConf* x, Client* c) {
client_redraw(xs, c);
}
-void client_raise(XConf* x, Client* c) {
- XMapRaised(x->display, c->frame);
- XMapRaised(x->display, c->win);
-}
-
void client_initprops(XConf* x, Client* c) {
int nprops = 0;
Atom* props = XListProperties(x->display, c->win, &nprops);
int format;
void* data = 0;
size_t ndata;
- printf("props(%x) { \n", (int)c->win);
for (int i = 0; i < nprops; i++) {
- printf(" %s\n", XGetAtomName(x->display, props[i]));
if (props[i] == XA_NET_WM_WINDOW_TYPE) {
if (Success == get_prop(x, c->win, props[i], &type, &format, &data, &ndata))
if (((Atom*)data)[0] == XA_NET_WM_WINDOW_TYPE_DIALOG)
}
data = xfree(data);
}
- printf("}\n");
}
void client_create(XConf* x, Window win) {
EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
/* position the window and frame */
- Client* parent = NULL;
- if (!client_flags(c, FLOATING)) {
- parent = list_reduce(Tiled_Clients, biggest, NULL);
- if (parent) {
- c->h = (parent->h - (parent->h / 2));
- parent->h /= 2;
- c->y = parent->y + parent->h;
- client_config(x, parent, parent->x, parent->y, parent->w, parent->h);
- }
- }
- client_add(parent, c);
+ client_add(c, Desktop);
client_config(x, c, c->x, c->y, c->w, c->h);
client_redraw(x, c);
client_raise(x, c);
c->y = y, c->h = h;
}
+/* Desktop Management
+ *****************************************************************************/
+void* hide_wins(Node* node, void* data) {
+ Client* c = TCLIENT(node);
+ XUnmapWindow(X.display, c->frame);
+ XUnmapWindow(X.display, c->win);
+ return data;
+}
+
+void* show_wins(Node* node, void* data) {
+ Client* c = TCLIENT(node);
+ XMapWindow(X.display, c->frame);
+ XMapWindow(X.display, c->win);
+ client_redraw(&X, c);
+ return data;
+}
+
+void change_desktop(const Arg arg) {
+ XGrabServer(X.display);
+ list_reduce(Tiled_Clients, hide_wins, NULL);
+ list_reduce(Floated_Clients, hide_wins, NULL);
+ Desktop = arg.i;
+ list_reduce(Tiled_Clients, show_wins, NULL);
+ list_reduce(Floated_Clients, show_wins, NULL);
+ XUngrabServer(X.display);
+ XSync(X.display, True);
+}
+
+void client_to_desktop(const Arg arg) {
+ int bar;
+ Window foo, win;
+ do{
+ (void)XQueryPointer(X.display, DefaultRootWindow(X.display),
+ &foo, &win, &bar, &bar, &bar, &bar, (unsigned int*)&bar);
+ } while (win <= 0);
+ Client* c = client_find(win);
+ if (!c) return;
+ client_del(c);
+ XUnmapWindow(X.display, c->frame);
+ XUnmapWindow(X.display, c->win);
+ XSync(X.display, True);
+ client_add(c, arg.i);
+}
+
/* X11 Event Handling
*****************************************************************************/
*/
static void xbtnpress(XConf* x, XEvent* e) {
- printf("btn\n");
Client* c = client_find(e->xbutton.window);
if (!c || c->frame != e->xbutton.window || client_flags(c, FLOATING))
return;
}
static void xbtnrelease(XConf* x, XEvent* e) {
- printf("btn\n");
Client* c = client_find(e->xbutton.window);
if (!c || c->frame != e->xbutton.window || client_flags(c, FLOATING))
return;
if (Button1 == e->xbutton.button) {
XUndefineCursor(X.display, e->xbutton.window);
- printf("moved: %d\n", e->xbutton.y - StartY);
client_resize(x, c, e->xbutton.y - StartY);
}
}
static void xconfigrequest(XConf* x, XEvent* e) {
- printf("config\n");
/*
Check if it's a window we care about. If it is, and it's floating, just
grant the request. Otherwise, deny it as we have it tiled already. All
}
static void xmaprequest(XConf* x, XEvent* e) {
- printf("map\n");
static XWindowAttributes attr = {0};
if (XGetWindowAttributes(x->display, e->xmaprequest.window, &attr)) {
if (attr.override_redirect) return; /* ignore certain windows (like frames) */
}
static void xunmapnotify(XConf* x, XEvent* e) {
- printf("unmap\n");
}
static void xdestroynotify(XConf* x, XEvent* e) {
- printf("destroy\n");
/* This is where we cleanup windows we care about. destroy them and their frames. */
Client* c = client_find(e->xdestroywindow.window);
- if (c) {
- if (!client_flags(c, FLOATING)) {
- int y = c->y, h = c->h;
- Node* nsucc = (c->tnode.prev ? c->tnode.prev : c->tnode.next);
- if (nsucc) {
- Client* succ = TCLIENT(nsucc);
- succ->h += h;
- if (nsucc == c->tnode.next)
- succ->y = y;
- client_config(x, succ, succ->x, succ->y, succ->w, succ->h);
- client_raise(x, succ);
- }
- }
- client_destroy(x, c);
- }
+ if (c) client_destroy(x, c);
}
static void xclientmsg(XConf* x, XEvent* e) {
- printf("client\n");
}
static void xpropnotify(XConf* x, XEvent* e) {
}
static void xenternotify(XConf* x, XEvent* e) {
- printf("enter\n");
/*
Handle focus follows mouse here.
*/
}
static void xexpose(XConf* x, XEvent* e) {
- printf("expose\n");
Client* c = client_find(e->xexpose.window);
if (c && e->xexpose.count == 0)
client_redraw(x, c);