static void xbtnpress(XEvent* e)
{
XButtonEvent* ev = &(e->xbutton);
- Client* c = client_get(e->xbutton.window);
X.start_x = ev->x_root;
X.start_y = ev->y_root;
+ Location loc;
+ Client* c = client_get(e->xbutton.window, &loc);
if (c && (ev->window == c->frame))
{
-// client_btnclick(c, ev->button, ev->x, ev->y);
- if (ev->button == Button1)
+ if (loc.column)
{
- client_raise(c);
- if (ev->y > (TITLE_HEIGHT + BORDER_WIDTH))
- {
- X.mode = M_RESIZE;
- warp_mouse(c);
- }
- }
- else if (ev->button == Button2)
- {
- client_close(c);
+ puts("tiled mouse click");
}
- else if (ev->button == Button3)
+ else
{
- client_lower(c);
+// client_btnclick(c, ev->button, ev->x, ev->y);
+ if (ev->button == Button1)
+ {
+ mons_raise(loc.monitor, c);
+ if (ev->y > (TITLE_HEIGHT + BORDER_WIDTH))
+ {
+ X.mode = M_RESIZE;
+ warp_mouse(c);
+ }
+ }
+ else if (ev->button == Button2)
+ {
+ client_close(c);
+ }
+ else if (ev->button == Button3)
+ {
+ mons_lower(loc.monitor, c);
+ }
}
}
}
/* make sure we get just the latest event */
XMotionEvent *ev = &e->xmotion;
while (XCheckTypedWindowEvent(X.disp, ev->window, ev->type, e));
- Client* c = client_get(ev->window);
+ Location loc;
+ Client* c = client_get(ev->window, &loc);
if (c && (ev->window == c->frame))
{
-// client_btnmove(c, ev->button, ev->x, ev->y);
- if (PRESSED(ev->state, Button1))
+ if (loc.column)
{
- if (X.mode != M_RESIZE)
- {
- client_move(c, ev->x_root - X.start_x, ev->y_root - X.start_y);
- }
- else
+ puts("tiled mouse drag");
+ }
+ else
+ {
+// client_btnmove(c, ev->button, ev->x, ev->y);
+ if (PRESSED(ev->state, Button1))
{
- client_resize(c, ev->x_root - X.start_x, ev->y_root - X.start_y);
+ if (X.mode != M_RESIZE)
+ {
+ client_move(c, ev->x_root - X.start_x, ev->y_root - X.start_y);
+ }
+ else
+ {
+ client_resize(c, ev->x_root - X.start_x, ev->y_root - X.start_y);
+ }
}
}
}
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(X.disp, ev->window, ev->value_mask, &wc);
- Client* c = client_get(ev->window);
+ Client* c = client_get(ev->window, NULL);
if (c && c->win == ev->window)
{
c->w = wc.width;
{
XMapRequestEvent* ev = &(e->xmaprequest);
XWindowAttributes attr;
- if (!client_get(ev->window))
+ if (!client_get(ev->window, NULL))
{
if (XGetWindowAttributes(X.disp, ev->window, &attr) && !attr.override_redirect)
{
static void xunmapnotify(XEvent* e)
{
XUnmapEvent* ev = &(e->xunmap);
- Client* c = client_get(ev->window);
+ Client* c = client_get(ev->window, NULL);
if (c && c->win == ev->window)
{
XUnmapWindow(X.disp, c->frame);
static void xdestroynotify(XEvent* e)
{
XDestroyWindowEvent* ev = &(e->xdestroywindow);
- Client* c = client_get(ev->window);
+ Client* c = client_get(ev->window, NULL);
if (c)
{
if (Focused == c)
static void xpropnotify(XEvent* e)
{
XPropertyEvent* ev = &(e->xproperty);
- Client* c = client_get(ev->window);
+ Client* c = client_get(ev->window, NULL);
if (c)
{
client_readprops(c);
static void xenternotify(XEvent* e)
{
XCrossingEvent* ev = &(e->xcrossing);
- Client* c = client_get(ev->window);
+ Client* c = client_get(ev->window, NULL);
if (c)
{
client_focus(c);
{
if (e->xexpose.count == 0)
{
- Client* c = client_get(e->xexpose.window);
+ Client* c = client_get(e->xexpose.window, NULL);
if (c)
{
client_draw(c);
} Client;
enum {
+ TILE_MONOCLE,
TILE_STACKED,
- TILE_EXPAND,
- TILE_MONOCOLE
+ TILE_EXPAND
} TileMode;
typedef struct Column {
/* mons.c */
extern Monitor* Monitors;
void mons_init(void);
+void mons_layer(Monitor* mon);
void mons_addclient(Client* c);
void mons_delclient(Client* c);
int mons_find(Window win, Location* loc);
void mons_place(Client* c);
void mons_wspace(int i);
void mons_towspace(Client* c, int i);
+void mons_raise(Monitor* mon, Client* c);
+void mons_lower(Monitor* mon, Client* c);
/* client.c */
extern Client* Focused;
void client_initall(void);
Client* client_add(Window win, XWindowAttributes* attr);
void client_draw(Client* c);
-Client* client_get(Window w);
-void client_raise(Client* c);
-void client_lower(Client* c);
+Client* client_get(Window w, Location* loc);
void client_move(Client* c, int xdiff, int ydiff);
void client_resize(Client* c, int xdiff, int ydiff);
void client_close(Client* c);
c->y = attr->y;
c->w = attr->width;
c->h = attr->height;
- mons_addclient(c);
client_readprops(c);
/* Reparent the window if applicable */
/* Map the window and draw the frame */
XAddToSaveSet(X.disp, c->win);
+ mons_addclient(c);
client_show(c, 1);
client_draw(c);
}
}
-Client* client_get(Window w)
+Client* client_get(Window w, Location* loc)
{
+ Location local_loc;
Client* c = NULL;
- Location loc = {0};
- if (mons_find(w, &loc))
+ loc = (loc ? loc : &local_loc);
+ if (mons_find(w, loc))
{
- c = loc.client;
+ c = loc->client;
}
return c;
}
for (int i = 0; i < 10; i++)
{
Column* col = ecalloc(1, sizeof(Column));
- col->mode = TILE_STACKED,
+ col->mode = TILE_MONOCLE,
col->width = m->w;
Workspace* wspace = ecalloc(1, sizeof(Workspace));
wspace->columns = col;
xfree(mons);
}
+static void coldims(Monitor* mon, Column* col, int *x, int *y, int *w, int *h)
+{
+ *x = mon->x, *y = mon->y, *w = col->width, *h = mon->h;
+ for (Column* c = mon->cspace->columns; c != col; *x += c->width, c = c->next);
+ *x += BORDER_WIDTH;
+ *y += BORDER_WIDTH + TITLE_HEIGHT;
+ *w -= 2*BORDER_WIDTH;
+ *h -= 2*BORDER_WIDTH + TITLE_HEIGHT;
+}
+
+void mons_layer(Monitor* mon)
+{
+ /* lower all of the floating windows first */
+ for (Client* client = mon->cspace->floating; client; client = client->next)
+ {
+ XLowerWindow(X.disp, client->win);
+ XLowerWindow(X.disp, client->frame);
+ }
+ /* now lower all of the tiled windows */
+ for (Column* col = mon->cspace->columns; col; col = col->next)
+ {
+ for (Client* client = col->clients; client; client = client->next)
+ {
+ XLowerWindow(X.disp, client->win);
+ XLowerWindow(X.disp, client->frame);
+ }
+ }
+}
+
+static void tile_monocle(Monitor* mon, Column* col, Client* c)
+{
+ coldims(mon, col, &(c->x), &(c->y), &(c->w), &(c->h));
+ client_move(c, 0, 0);
+ client_resize(c, 0, 0);
+ c->next = col->clients;
+ col->clients = c;
+}
+
+static void tile_expand(Monitor* mon, Column* col, Client* client)
+{
+ (void)mon, (void)col;
+ client->next = col->clients;
+ col->clients = client;
+}
+
+static void tile_stacked(Monitor* mon, Column* col, Client* client)
+{
+ (void)mon, (void)col;
+ client->next = col->clients;
+ col->clients = client;
+}
+
/* adds a new client to the most appropriate monitor */
void mons_addclient(Client* c)
{
int ptrx = 0, ptry = 0, winx = 0, winy = 0, mask = 0;
XQueryPointer(X.disp, X.root, &root, &child, &ptrx, &ptry, &winx, &winy, (unsigned int*)&mask);
Monitor* mon = pickmon(ptrx, ptry);
- printf("add win to %p\n", mon);
if (X.mode == M_INIT)
{
c->next = mon->cspace->floating;
int ch = c->h + 2*BORDER_WIDTH + TITLE_HEIGHT;
c->x = mon->midx - cw/2;
c->y = mon->midy - ch/2;
+ client_move(c, 0, 0);
+ client_resize(c, 0, 0);
}
else
{
Column* col = pickcol(mon->cspace->columns, ptrx - mon->x);
- /*
- Client* c = find_max(col->clients);
- if (c)
+ if (col->mode == TILE_MONOCLE)
{
- c->next = col->clients;
- col->clients = c;
+ tile_monocle(mon, col, c);
}
- else
+ else if (col->mode == TILE_EXPAND)
{
- shrink the window;
- fill the gap with the new window;
+ tile_expand(mon, col, c);
+ }
+ else if (col->mode == TILE_STACKED)
+ {
+ tile_stacked(mon, col, c);
}
- */
-
- c->next = col->clients;
- col->clients = c;
- /* TODO: tile the window approriately */
}
- assert(c != c->next);
+ mons_layer(mon);
}
void mons_delclient(Client* c)
{
- assert(c != c->next);
Location loc = {0};
if (mons_find(c->win, &loc))
{
}
}
+void mons_raise(Monitor* mon, Client* c)
+{
+ mon->cspace->floating = delclient(mon->cspace->floating, c);
+ c->next = mon->cspace->floating;
+ mon->cspace->floating = c;
+ mons_layer(mon);
+}
+
+void mons_lower(Monitor* mon, Client* c)
+{
+ mon->cspace->floating = delclient(mon->cspace->floating, c);
+ c->next = NULL;
+ if (mon->cspace->floating)
+ {
+ Client* curr = mon->cspace->floating;
+ for (; curr && curr->next; curr = curr->next);
+ curr->next = c;
+ }
+ else
+ {
+ mon->cspace->floating = c;
+ }
+ mons_layer(mon);
+}
+
static Monitor* pickmon(int ptrx, int ptry)
{
Monitor* mon = Monitors;
/* otherwise, return the current column */
if (!col)
{
- puts("searching for active col");
+// puts("searching for active col");
int left = 0, right = 0;
for (col = cols; col; col = col->next)
{
left = right, right += col->width;
- printf("%d <= %d < %d\n", left, relx, right);
+// printf("%d <= %d < %d\n", left, relx, right);
if (left <= relx && relx < right)
{
break; /* we found the column holding the mouse */
}
}
}
- else
- {
- puts("empty col");
- }
assert(col);
return col;
}