#include <string.h>
#include <assert.h>
+#define MIN_COLUMN_FACTOR 0.10
+#define MAX_COLUMNS 10
+#define MAX_COLUMN_CLIENTS 256
+#define MAX_FLOATING_CLIENTS 256
+#define NUM_WORKSPACES 10
+#define MAX_MONITORS 4
+
+/* calculate the size of the client pool */
+#define MAX_WSPACE_CLIENTS (MAX_COLUMNS * MAX_COLUMN_CLIENTS + MAX_FLOATING_CLIENTS)
+#define MAX_MONITOR_CLIENTS (NUM_WORKSPACES * MAX_WSPACE_CLIENTS)
+#define MAX_CLIENTS (MAX_MONITORS * MAX_MONITOR_CLIENTS)
+
+#define BORDER_WIDTH 5
+#define TITLE_HEIGHT (X.font_ext->max_logical_extent.height)
+#define MIN_HEIGHT (TITLE_HEIGHT+BORDER_WIDTH)
+#define MIN_COL_FACT 0.20
+#define FONT_NAME "-*-lucida-bold-r-normal-sans-14-*-*-*-p-*-iso10646-1"
+#define MODKEY Mod4Mask
+#define FRAME_HEIGHT_SUM (2*BORDER_WIDTH + TITLE_HEIGHT)
+#define FRAME_WIDTH_SUM (2*BORDER_WIDTH)
+
#define min(a,b) (a < b ? a : b)
#define max(a,b) (a > b ? a : b)
struct Node* next;
} Node;
-typedef struct Client {
- struct Client* next;
+typedef struct Client Client;
+typedef struct Column Column;
+typedef struct Workspace Workspace;
+typedef struct Monitor Monitor;
+typedef struct Location Location;
+
+struct Client {
+ Client* next;
+
+ /* location data */
+ Monitor* monitor;
+ Workspace* workspace;
+ Column* column;
+
+ /* attributes */
char* name;
Window frame, win;
int flags, x, y, w, h;
XSizeHints hints;
Pixmap pixmap;
Visual visual;
-} Client;
+};
-typedef struct Column {
- struct Column* next;
+struct Column {
int width;
- Client* focused;
Client* clients;
-} Column;
+};
-typedef struct Workspace {
- struct Workspace* next;
+struct Workspace {
Client* floating;
- Column* columns;
-} Workspace;
+ int ncolumns;
+ Column columns[MAX_COLUMNS];
+};
-typedef struct Monitor {
- struct Monitor* next;
+struct Monitor {
int x, y, w, h, midx, midy;
- Workspace* wspaces;
+ Workspace wspaces[NUM_WORKSPACES];
Workspace* cspace;
-} Monitor;
+};
-typedef struct Location {
+struct Location {
Monitor* monitor;
Workspace* workspace;
Column* column;
Client* client;
-} Location;
+};
typedef union {
int i;
Arg arg;
} Key;
-#define BORDER_WIDTH 5
-#define TITLE_HEIGHT (X.font_ext->max_logical_extent.height)
-#define MIN_HEIGHT (TITLE_HEIGHT+BORDER_WIDTH)
-#define MIN_COL_FACT 0.20
-#define FONT_NAME "-*-lucida-bold-r-normal-sans-14-*-*-*-p-*-iso10646-1"
-#ifdef __APPLE__
-#define MODKEY Mod1Mask
-#else
-#define MODKEY Mod4Mask
-#endif
-#define FRAME_HEIGHT_SUM (2*BORDER_WIDTH + TITLE_HEIGHT)
-#define FRAME_WIDTH_SUM (2*BORDER_WIDTH)
-
/* anvil.c */
extern XConf X;
+
+Client* Client_Find(Window win);
+Client* Client_Add(Window win, XWindowAttributes* attr);
+void Client_Del(Client* client);
+void Client_AdjustSize(Client* client);
+void Client_SetActive(Window win);
+void Client_ReadProps(Client* client);
+void Client_Draw(Client* client);
+void Client_Focus(Client* client);
+
+void Mouse_ToCorner(Client* client);
+void Mouse_Down(XButtonEvent* ev, Client* client);
+void Mouse_Up(XButtonEvent* ev, Client* client);
+void Mouse_Drag(XMotionEvent* ev, Client* client);
+
+void Keys_Run(XKeyEvent* ev);
+
+
+
+
+
+
/* list.c */
int list_length(void* list);
void* list_del(void* list, void* node);
void keys_run(XKeyEvent* ev);
/* mons.c */
-extern Monitor* Monitors;
+extern Monitor Monitors[MAX_MONITORS];
+
void mons_init(void);
+void mons_delclient(Location* loc);
+void mons_activate(Window win);
+
void mons_layer(Monitor* mon);
void mons_addclient(Client* c);
-void mons_delclient(Location* loc);
void mons_togglefloat(Location* loc);
int mons_find(Window win, Location* loc);
void mons_place(Client* c);
void mons_coljoin(void);
void mons_coladjust(Monitor* mon, Column* col, int wdiff);
void mons_tilemove(Location* loc, int hdiff);
-void mons_activate(Window win);
/* client.c */
extern Client* Focused;
void mouse_get(int* ptrx, int* ptry);
/* tile.c */
-void monocled_add(Location* loc);
-void monocled_del(Location* loc);
-void monocled_raise(Location* loc);
-void stacked_add(Location* loc);
-void stacked_del(Location* loc);
-void stacked_set(Location* loc);
-void stacked_addheight(Location* loc, int amount);
+void tile_add(Location* loc);
+void tile_del(Location* loc);
+void tile_set(Location* loc);
+void tile_addheight(Location* loc, int amount);
/* error.c */
extern int (*error_default)(Display* disp, XErrorEvent* ev);
#include "anvil.h"
+#define NUM_BITMAP_CELLS (MAX_CLIENTS / sizeof(unsigned long) + 1)
+#define CELL_IS_FULL ((unsigned long)-1)
+
+/* Client allocation bitmap */
+static unsigned long Client_Bitmap[NUM_BITMAP_CELLS];
+
+/* Client allocation buffer */
+static Client Client_Buffer[MAX_CLIENTS];
+
+/* The currently focused client */
Client* Focused = NULL;
+Client* Client_Find(Window win)
+{
+ Client* client = NULL;
+ for (int i = 0; i < MAX_CLIENTS; i++)
+ {
+ unsigned long cell = i / sizeof(unsigned long);
+ unsigned long bit = i % sizeof(unsigned long);
+ int allocated = ((Client_Bitmap[cell] & (1 << bit)) != 0);
+
+ /* if the client is allocated and matches frame or window id, return it */
+ if (allocated && ((Client_Buffer[i].win == win) || (Client_Buffer[i].frame == win)))
+ {
+ client = &Client_Buffer[i];
+ break;
+ }
+ }
+ return client;
+}
+
+Client* Client_Add(Window win, XWindowAttributes* attr)
+{
+ Client* client = NULL;
+
+ for (int i = 0; i < NUM_BITMAP_CELLS; i++)
+ {
+ if (Client_Bitmap[i] != CELL_IS_FULL)
+ {
+ unsigned long bit_index = __builtin_ctz(~Client_Bitmap[i]);
+ Client_Bitmap[i] |= (1 << bit_index);
+ client = &Client_Buffer[i + bit_index];
+ break;
+ }
+ }
+
+ return client;
+}
+
+void Client_Del(Client* client)
+{
+ /* cleanup stuff here... */
+
+ /* now deallocate it */
+ unsigned long client_index = (client - &Client_Buffer[0]) / sizeof(Client);
+ unsigned long cell = client_index / sizeof(unsigned long);
+ unsigned long bit = client_index % sizeof(unsigned long);
+ Client_Bitmap[cell] &= ~(1 << bit);
+}
+
+void Client_AdjustSize(Client* client)
+{
+}
+
+void Client_SetActive(Window win)
+{
+}
+
+void Client_ReadProps(Client* client)
+{
+}
+
+void Client_Draw(Client* client)
+{
+}
+
+void Client_Focus(Client* client)
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
void client_initall(void)
{
unsigned int nwins;
}
}
}
+
+void Keys_Run(XKeyEvent* ev)
+{
+}
static Client* client_find(Client* clients, Window win);
static void add_client(Monitor* mon, Client* c, int ptrx);
static void remove_client(Location* loc, Client* c);
-static void adjust_all(Column* col, int xoff);
+//static void adjust_all(Column* col, int xoff);
static void change_wspace(Monitor* mon, Workspace* wspace);
-Monitor* Monitors = NULL;
+Monitor Monitors[MAX_MONITORS];
-static int min_col_width(Monitor* mon)
-{
- return (int)(mon->w * MIN_COL_FACT);
-}
+//static int min_col_width(Monitor* mon)
+//{
+// return (int)(mon->w * MIN_COL_FACT);
+//}
void mons_init(void)
{
int nmons;
check( XineramaIsActive(X.disp), "Xinerama extension is required");
XineramaScreenInfo* mons = XineramaQueryScreens(X.disp, &nmons);
- for (int i = 0; i < nmons; i++)
+ for (int i = 0; i < nmons && i < MAX_MONITORS; i++)
{
- Monitor* m = ecalloc(1, sizeof(Monitor));
+ Monitor* m = &Monitors[i];
m->x = mons[i].x_org;
m->y = mons[i].y_org;
m->w = mons[i].width;
m->h = mons[i].height;
m->midx = m->x + m->w/2;
m->midy = m->y + m->h/2;
- m->next = Monitors;
- Monitors = m;
for (int i = 0; i < 10; i++)
{
- Column* col = ecalloc(1, sizeof(Column));
- col->width = m->w;
- Workspace* wspace = ecalloc(1, sizeof(Workspace));
- wspace->columns = col;
- wspace->next = m->wspaces;
- m->wspaces = wspace;
+ m->wspaces[i].ncolumns = 1;
+ m->wspaces[i].columns[0].width = m->w;
}
m->cspace = m->wspaces;
}
xfree(mons);
-
- Monitor* m = Monitors;
- while (m)
- {
- printf("x: %d y: %d w: %d h: %d\n", m->x, m->y, m->w, m->h);
- Workspace* w = m->wspaces;
- while (w)
- {
- printf(" wspace %p\n", (void*)w);
- Column* c = w->columns;
- while (c)
- {
- printf(" col %p %d\n", (void*)c, c->width);
- c = c->next;
- }
- w = w->next;
- }
- m = m->next;
- }
-
}
-void mons_layer(Monitor* mon)
+int mons_find(Window win, Location* loc)
{
- int nwins = 0;
- Window* wins = NULL;
- Client* c;
- Column* col;
- LIST_FOR_EACH(c, mon->cspace->floating)
+ for (int m = 0; m < MAX_MONITORS; m++)
{
- wins = realloc(wins, ++nwins * sizeof(Window));
- wins[nwins-1] = c->frame;
- }
- /* add in the monocled windows first */
- LIST_FOR_EACH(col, mon->cspace->columns)
- {
- if (col->focused)
+ for (int i = 0; i < NUM_WORKSPACES; i++)
{
- wins = realloc(wins, ++nwins * sizeof(Window));
- wins[nwins-1] = col->focused->frame;
- }
- }
- /* now lower all of the tiled windows */
- LIST_FOR_EACH(col, mon->cspace->columns)
- {
- LIST_FOR_EACH(c, col->clients)
- {
- if (col->focused != c)
+ Workspace* wspace = &(Monitors[m].wspaces[i]);
+ Column* column = NULL;
+ Client* client = client_find(wspace->floating, win);
+ if (!client)
{
- wins = realloc(wins, ++nwins * sizeof(Window));
- wins[nwins-1] = c->frame;
+ for (int i =0; i < wspace->ncolumns; i++)
+ {
+ Column* column = &wspace->columns[i];
+ if ( (client = client_find(column->clients, win)) )
+ {
+ break;
+ }
+ }
+ }
+ /* return the client location if we found it */
+ if (client)
+ {
+ loc->monitor = &Monitors[m];
+ loc->workspace = wspace;
+ loc->column = column;
+ loc->client = client;
+ return 1;
}
}
}
- if (nwins)
- {
- XRestackWindows(X.disp, wins, nwins);
- }
- xfree(wins);
+ return 0;
}
/* adds a new client to the most appropriate monitor */
free(loc->client);
}
+void mons_layer(Monitor* mon)
+{
+ int nwins = 0;
+ Window* wins = NULL;
+ Client* c;
+ Column* col;
+ LIST_FOR_EACH(c, mon->cspace->floating)
+ {
+ wins = realloc(wins, ++nwins * sizeof(Window));
+ wins[nwins-1] = c->frame;
+ }
+
+ /* first lower all of the tiled windows */
+ for (int i =0; i < mon->cspace->ncolumns; i++)
+ {
+ col = &mon->cspace->columns[i];
+ LIST_FOR_EACH(c, col->clients)
+ {
+ wins = realloc(wins, ++nwins * sizeof(Window));
+ wins[nwins-1] = c->frame;
+ }
+ }
+ if (nwins)
+ {
+ XRestackWindows(X.disp, wins, nwins);
+ }
+ xfree(wins);
+}
+
void mons_togglefloat(Location* loc)
{
remove_client(loc, loc->client);
mons_addclient(loc->client);
}
-int mons_find(Window win, Location* loc)
-{
- Monitor* mon;
- Workspace* wspace;
- LIST_FOR_EACH(mon, Monitors)
- {
- LIST_FOR_EACH(wspace, mon->wspaces)
- {
- Column* column = NULL;
- Client* client = client_find(wspace->floating, win);
- if (!client)
- {
- LIST_FOR_EACH(column, wspace->columns)
- {
- if ( (client = client_find(column->clients, win)) )
- {
- break;
- }
- }
- }
- /* return the client location if we found it */
- if (client)
- {
- loc->monitor = mon;
- loc->workspace = wspace;
- loc->column = column;
- loc->client = client;
- return 1;
- }
- }
- }
- return 0;
-}
-
/* find the best monitor to own the window by calculating the overlap */
void mons_place(Client* c)
{
{
int maxarea = 0;
Monitor *mon = NULL, *closest = NULL;
- LIST_FOR_EACH(mon, Monitors)
+ for (int m = 0; m < MAX_MONITORS; m++)
{
+ mon = &Monitors[m];
int left = max(cleft, mon->x);
int right = min(cright, mon->x + mon->w);
int top = max(ctop, mon->y);
void mons_colsplit(void)
{
- Monitor* mon = pickmon();
- Column* col = pickcol(mon->cspace->columns, PtrX - mon->x);
- int next_empty = (col->next && !col->next->clients);
- if (col->clients && !next_empty && col->width >= 2*min_col_width(mon))
- {
- Column* newcol = ecalloc(1, sizeof(Column));
- newcol->width = col->width/2;
- col->width -= newcol->width;
- newcol->next = col->next;
- col->next = newcol;
- adjust_all(col, 0);
- }
+// Monitor* mon = pickmon();
+// Column* col = pickcol(mon->cspace->columns, PtrX - mon->x);
+// int next_empty = (col->next && !col->next->clients);
+// if (col->clients && !next_empty && col->width >= 2*min_col_width(mon))
+// {
+// Column* newcol = ecalloc(1, sizeof(Column));
+// newcol->width = col->width/2;
+// col->width -= newcol->width;
+// newcol->next = col->next;
+// col->next = newcol;
+// adjust_all(col, 0);
+// }
}
void mons_coljoin(void)
{
- Monitor* mon = pickmon();
- Column* dest = pickcol(mon->cspace->columns, PtrX - mon->x);
- Column* dead = dest->next;
- if (!dead)
- {
- dead = dest;
- dest = list_prev(mon->cspace->columns, dead);
- }
-
- if (dest && dead)
- {
- /* add the clients to the current col */
- for (Client* c = dead->clients; c;)
- {
- Client* next = c->next;
- if (dest->focused)
- {
-
- monocled_add(&(Location){mon, NULL, dest, c});
- }
- else
- {
- stacked_add(&(Location){mon, NULL, dest, c});
- }
- c = next;
- }
- dest->next = dead->next;
- dest->width += dead->width;
- free(dead);
- adjust_all(dest, 0);
- }
+// Monitor* mon = pickmon();
+// Column* dest = pickcol(mon->cspace->columns, PtrX - mon->x);
+// Column* dead = dest->next;
+// if (!dead)
+// {
+// dead = dest;
+// dest = list_prev(mon->cspace->columns, dead);
+// }
+//
+// if (dest && dead)
+// {
+// /* add the clients to the current col */
+// for (Client* c = dead->clients; c;)
+// {
+// Client* next = c->next;
+// tile_add(&(Location){mon, NULL, dest, c});
+// c = next;
+// }
+// dest->next = dead->next;
+// dest->width += dead->width;
+// free(dead);
+// adjust_all(dest, 0);
+// }
}
void mons_coladjust(Monitor* mon, Column* col, int wdiff)
{
- Column* neighbor = col->next;
- int minwidth = min_col_width(mon);
- if (X.edge == E_LEFT && mon->cspace->columns != col)
- {
- for (neighbor = mon->cspace->columns; neighbor && neighbor->next != col; neighbor = neighbor->next);
- int minadj = -(neighbor->width - minwidth);
- int maxadj = (col->width - minwidth);
- wdiff = min(max(minadj, wdiff), maxadj);
- neighbor->width += wdiff;
- col->width -= wdiff;
- adjust_all(col, wdiff);
- adjust_all(neighbor, 0);
- }
- else if (X.edge == E_RIGHT && col->next)
- {
- int minadj = -(col->width - minwidth);
- int maxadj = (neighbor->width - minwidth);
- wdiff = min(max(minadj, wdiff), maxadj);
- col->width += wdiff;
- neighbor->width -= wdiff;
- adjust_all(col, 0);
- adjust_all(neighbor, wdiff);
- }
- else
- {
- /* invalid edge */
- }
+// Column* neighbor = col->next;
+// int minwidth = min_col_width(mon);
+// if (X.edge == E_LEFT && mon->cspace->columns != col)
+// {
+// for (neighbor = mon->cspace->columns; neighbor && neighbor->next != col; neighbor = neighbor->next);
+// int minadj = -(neighbor->width - minwidth);
+// int maxadj = (col->width - minwidth);
+// wdiff = min(max(minadj, wdiff), maxadj);
+// neighbor->width += wdiff;
+// col->width -= wdiff;
+// adjust_all(col, wdiff);
+// adjust_all(neighbor, 0);
+// }
+// else if (X.edge == E_RIGHT && col->next)
+// {
+// int minadj = -(col->width - minwidth);
+// int maxadj = (neighbor->width - minwidth);
+// wdiff = min(max(minadj, wdiff), maxadj);
+// col->width += wdiff;
+// neighbor->width -= wdiff;
+// adjust_all(col, 0);
+// adjust_all(neighbor, wdiff);
+// }
+// else
+// {
+// /* invalid edge */
+// }
}
void mons_tilemove(Location* loc, int hdiff)
client_setshade(loc->client, 0);
loc->monitor = mon;
loc->column = col;
- if (col->focused)
- {
- monocled_add(loc);
- }
- else
- {
- stacked_add(loc);
- }
+ tile_add(loc);
}
else
{
- stacked_addheight(loc, hdiff);
+ tile_addheight(loc, hdiff);
}
mouse_totitle(loc->client);
}
if (mons_find(win, &loc))
{
change_wspace(loc.monitor, loc.workspace);
- if (loc.column && loc.column->focused)
- {
- monocled_raise(&loc);
- mons_layer(loc.monitor);
- }
- else if (!loc.column)
+ if (!loc.column)
{
mons_raise(loc.monitor, loc.client);
}
static Monitor* pickmon(void)
{
mouse_get(&PtrX, &PtrY);
+ int m = 0;
Monitor* mon;
- LIST_FOR_EACH_UNTIL(mon, Monitors,
- (mon->x <= PtrX && PtrX < mon->x+mon->w) &&
- (mon->y <= PtrY && PtrY < mon->y+mon->h)
- );
- mon = (mon ? mon : Monitors);
+ for (; m < MAX_MONITORS; m++)
+ {
+ mon = &Monitors[m];
+ if ((mon->x <= PtrX && PtrX < mon->x+mon->w) &&
+ (mon->y <= PtrY && PtrY < mon->y+mon->h))
+ {
+ break;
+ }
+ }
+ mon = (m < MAX_MONITORS ? mon : &Monitors[0]);
return mon;
}
Column* col;
int left = 0, right = 0;
printf("cols %p\n", (void*)cols);
- LIST_FOR_EACH(col, cols)
+ for (int i = 0; i < MAX_COLUMNS; i++)
{
+ col = &(cols[i]);
printf("curr = %p\n", (void*)col);
left = right, right += col->width;
printf("%d <= %d < %d\n", left, relx, right);
static Workspace* pickws(Monitor* mon, int wsid)
{
- Workspace* wspace;
- int i = 0;
- LIST_FOR_EACH_UNTIL(wspace, mon->wspaces, (i++ == wsid));
- return wspace;
+ return &(mon->wspaces[wsid]);
}
static void client_visibility(Workspace* wspace, int show)
{
client_show(client, show);
}
- LIST_FOR_EACH(col, wspace->columns)
+ for (int i = 0; i < wspace->ncolumns; i++)
{
+ col = &(wspace->columns[i]);
LIST_FOR_EACH(client, col->clients)
{
client_show(client, show);
}
else
{
- /* find first empty column, and fill that first */
+ /* find first empty column, and fill that first, otherwise use the last column we find */
Column* col = NULL;
- LIST_FOR_EACH_UNTIL(col, mon->cspace->columns, col->clients == NULL);
- if (!col)
+ for (int i = 0; i < mon->cspace->ncolumns; i++)
{
- /* otherwise pick the column to the right or the current column */
- col = pickcol(mon->cspace->columns, ptrx - mon->x);
- if (col->next)
+ col = &(mon->cspace->columns[i]);
+ if (col->clients == NULL)
{
- col = col->next;
+ break;
}
}
- /* add in monocled or stacked mode */
- if (col->focused)
- {
- monocled_add(&(Location){mon, NULL, col, c});
- }
- else
- {
- stacked_add(&(Location){mon, NULL, col, c});
- }
+ tile_add(&(Location){mon, NULL, col, c});
}
mons_layer(mon);
}
{
loc->workspace->floating = list_del(loc->workspace->floating, c);
}
- else if (loc->column->focused)
- {
- monocled_del(loc);
- }
else
{
- stacked_del(loc);
+ tile_del(loc);
}
}
-static void adjust_all(Column* col, int xoff)
-{
- Client* c;
- LIST_FOR_EACH(c, col->clients)
- {
- c->x += xoff;
- c->w = col->width;
- client_adjust(c);
- }
-}
+//static void adjust_all(Column* col, int xoff)
+//{
+// Client* c;
+// LIST_FOR_EACH(c, col->clients)
+// {
+// c->x += xoff;
+// c->w = col->width;
+// client_adjust(c);
+// }
+//}
static void change_wspace(Monitor* mon, Workspace* wspace)
{
static void stack_clients(Location* loc)
{
- stacked_set(loc);
-}
-
-static void rotate_client(Location* loc)
-{
- Client *tail, *client = loc->column->clients;
- if (client->next)
- {
- loc->column->clients = client->next;
- tail = list_last(loc->column->clients);
- client->next = NULL;
- tail->next = client;
- monocled_raise(loc);
- }
+ tile_set(loc);
}
static void reposition_tile(Location* loc)
X.mode = (X.edge == E_TOP ? M_TILE_RESIZE : M_COL_RESIZE);
}
-static void monocle_client(Location* loc)
-{
- monocled_raise(loc);
-}
-
MouseAct Floating[] = {
{ 0, Button1, ButtonPress, resize_frame },
{ MODKEY|ShiftMask, Button2, ButtonPress, toggle_float },
{ 0, Button5, ButtonPress, raise_client }
};
-MouseAct Monocled[] = {
- { 0, Button1, ButtonPress, stack_clients },
- { MODKEY|ShiftMask, Button2, ButtonPress, toggle_float },
- { MODKEY, Button2, ButtonPress, close_client },
- { 0, Button3, ButtonPress, rotate_client },
-};
-
MouseAct Stacked[] = {
{ 0, Button1, ButtonPress, reposition_tile },
{ MODKEY|ShiftMask, Button2, ButtonPress, toggle_float },
{ MODKEY, Button2, ButtonPress, close_client },
{ 0, Button2, ButtonPress, stack_clients },
- { 0, Button3, ButtonPress, monocle_client },
};
static void process(XButtonEvent* ev, Location* loc, MouseAct* actions, int nactions)
{
process(ev, loc, Floating, sizeof(Floating)/sizeof(Floating[0]));
}
- else if (loc->column->focused)
- {
- process(ev, loc, Monocled, sizeof(Monocled)/sizeof(Monocled[0]));
- }
else
{
process(ev, loc, Stacked, sizeof(Stacked)/sizeof(Stacked[0]));
XQueryPointer(X.disp, X.root, &root, &child, ptrx, ptry, &winx, &winy, (unsigned int*)&mask);
}
+void Mouse_ToCorner(Client* client)
+{
+}
+
+void Mouse_Down(XButtonEvent* ev, Client* client)
+{
+}
+
+void Mouse_Up(XButtonEvent* ev, Client* client)
+{
+}
+
+void Mouse_Drag(XMotionEvent* ev, Client* client)
+{
+}
+
+++ /dev/null
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/keysym.h>
-#include <X11/XKBlib.h>
-#include <X11/Xatom.h>
-#include <X11/cursorfont.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/Xinerama.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-typedef struct {
- Display* disp;
- int screen, mode, edge, start_x, start_y, last_x, last_y;
- Window root;
- unsigned long clr_bg, clr_bdr, clr_urgent;
- Cursor csr_root, csr_point, csr_move;
- XFontSet font;
- XFontSetExtents *font_ext;
- Visual* visual;
- void (*eventfns[LASTEvent])(XEvent*);
-} XConf;
-
-#define MIN_COLUMN_FACTOR 0.10
-#define MAX_COLUMNS 10
-#define MAX_COLUMN_CLIENTS 128
-#define MAX_FLOATING_CLIENTS 128
-#define NUM_WORKSPACES 10
-#define MAX_MONITORS 4
-
-/* calculate the size of the client pool */
-#define MAX_WSPACE_CLIENTS (MAX_COLUMNS * MAX_COLUMN_CLIENTS + MAX_FLOATING_CLIENTS)
-#define MAX_MONITOR_CLIENTS (NUM_WORKSPACES * MAX_WSPACE_CLIENTS)
-#define MAX_CLIENTS (MAX_MONITORS * MAX_MONITOR_CLIENTS)
-
-typedef struct Client {
- char* name;
- Window frame, win;
- int flags, x, y, w, h;
- long hint_flags, wm_flags;
- XSizeHints hints;
- Pixmap pixmap;
- Visual visual;
-} Client;
-
-typedef struct Column {
- int width, focused;
- Client* clients[MAX_COLUMN_CLIENTS];
-} Column;
-
-typedef struct Workspace {
- Client* floating[MAX_FLOATING_CLIENTS];
- Column columns[MAX_COLUMNS];
-} Workspace;
-
-typedef struct Monitor {
- int x, y, w, h, midx, midy, cspace;
- Workspace wspaces[NUM_WORKSPACES];
-} Monitor;
-
-typedef struct Location {
- Monitor* monitor;
- Workspace* workspace;
- Column* column;
- Client* client;
-} Location;
{
Column* c;
*x = mon->x, *y = mon->y, *w = col->width, *h = mon->h;
- LIST_FOR_EACH_UNTIL(c, mon->cspace->columns, (c == col))
- {
- *x += c->width;
- }
-}
-void monocled_add(Location* loc)
-{
- Client* c = loc->client;
- coldims(loc->monitor, loc->column, &(c->x), &(c->y), &(c->w), &(c->h));
- client_setshade(c, 0);
- client_adjust(c);
- c->next = loc->column->clients;
- loc->column->clients = c;
- loc->column->focused = c;
-}
-
-void monocled_del(Location* loc)
-{
- Client* c = loc->client;
- loc->column->clients = list_del(loc->column->clients, c);
- loc->column->focused = loc->column->clients;
- c = loc->column->clients;
- if (c)
+ int curr = (col - &mon->cspace->columns[0]) / sizeof(Column);
+ for (int i = 0; i < curr; i++)
{
- coldims(loc->monitor, loc->column, &(c->x), &(c->y), &(c->w), &(c->h));
- client_setshade(c, 0);
- client_adjust(c);
+ c = &mon->cspace->columns[i];
+ *x += c->width;
}
}
-void monocled_raise(Location* loc)
-{
- loc->column->clients = list_del(loc->column->clients, loc->client);
- loc->client->next = loc->column->clients;
- loc->column->clients = loc->client;
- loc->column->focused = loc->client;
- coldims(loc->monitor, loc->column,
- &(loc->client->x), &(loc->client->y), &(loc->client->w), &(loc->client->h));
- client_setshade(loc->client, 0);
- client_adjust(loc->client);
- mons_layer(loc->monitor);
-}
-
-void monocled_set(Location* loc)
-{
- loc->column->clients = list_del(loc->column->clients, loc->client);
- loc->client->next = loc->column->clients;
- loc->column->clients = loc->client;
- loc->column->focused = loc->client;
- coldims(loc->monitor, loc->column,
- &(loc->client->x), &(loc->client->y), &(loc->client->w), &(loc->client->h));
- client_setshade(loc->client, 0);
- client_adjust(loc->client);
- mons_layer(loc->monitor);
-}
-
-void stacked_add(Location* loc)
+void tile_add(Location* loc)
{
Client* c = loc->client;
coldims(loc->monitor, loc->column, &(c->x), &(c->y), &(c->w), &(c->h));
}
if (max->h < 3*MIN_HEIGHT)
{
- if (loc->column->next)
- {
- stacked_add(loc);
- }
- else
- {
- c->next = loc->monitor->cspace->floating;
- loc->monitor->cspace->floating = c;
- c->x = loc->monitor->midx - c->w/2;
- c->y = loc->monitor->midy - c->h/2;
- client_adjust(c);
- }
+ c->next = loc->monitor->cspace->floating;
+ loc->monitor->cspace->floating = c;
+ c->x = loc->monitor->midx - c->w/2;
+ c->y = loc->monitor->midy - c->h/2;
+ client_adjust(c);
}
else
{
}
}
-void stacked_del(Location* loc)
+void tile_del(Location* loc)
{
Client* c = loc->client;
if (loc->column->clients == c)
}
}
-void stacked_set(Location* loc)
+void tile_set(Location* loc)
{
Client *curr, *c = loc->client;
- loc->column->focused = NULL;
int starty = loc->monitor->y;
/* stack the windows before the target */
LIST_FOR_EACH_UNTIL(curr, loc->column->clients, curr == c)
}
}
-void stacked_addheight(Location* loc, int amount)
+void tile_addheight(Location* loc, int amount)
{
Client* c = loc->client;
Client* prev = list_prev(loc->column->clients, c);
XConf X = {0};
+/* Checks if another window manager is already running */
static void check_for_wm(void)
{
error_default = XSetErrorHandler(error_init);
XSync(X.disp, False);
}
-static void xbtnpress(XEvent* e)
+/* Handles newly mapped windows. */
+static void xmaprequest(XEvent* e)
{
- XButtonEvent* ev = &(e->xbutton);
- XGrabPointer(X.disp, ev->window, False,
- ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
- GrabModeAsync, GrabModeAsync, None, X.csr_move, CurrentTime);
- //printf("BTN_DN(w: 0x%lx s: %d x: %d y: %d rx: %d ry: %d)\n", ev->window, ev->state, ev->x, ev->y, ev->x_root, ev->y_root);
- X.start_x = ev->x_root, X.start_y = ev->y_root;
- X.last_x = ev->x_root, X.last_y = ev->y_root;
- Location loc = {0};
- if (mons_find(ev->window, &loc) && (loc.client->frame == ev->window))
+ XMapRequestEvent* ev = &(e->xmaprequest);
+ //printf("MAP(w: 0x%lx)\n", ev->window);
+ XWindowAttributes attr;
+
+ /* if no record of this window exists, add it to our managed list */
+ if (!Client_Find(ev->window))
{
- Client* c = loc.client;
- if (ev->y < MIN_HEIGHT)
- {
- X.edge = E_TOP;
- }
- else if (ev->y_root > (c->y + c->h - BORDER_WIDTH))
- {
- X.edge = E_BOTTOM;
- }
- else if (ev->x < BORDER_WIDTH)
- {
- X.edge = E_LEFT;
- }
- else if (ev->x_root > (c->x + c->w - BORDER_WIDTH))
+ if (XGetWindowAttributes(X.disp, ev->window, &attr) && !attr.override_redirect)
{
- X.edge = E_RIGHT;
+ Client_Add(ev->window, &attr);
}
- else
- {
- X.edge = E_NONE;
- }
- mouse_down(ev, &loc);
}
}
-static void xbtnrelease(XEvent* e)
+/* Handle unmap events for window we manage.
+ TODO: This is probably busted right now. mplab x windows have a habit of being
+ remapped since they don't get destroyed. Probably need an explicit state
+ for that (ex. withdrawn)
+*/
+static void xunmapnotify(XEvent* e)
{
- XButtonEvent* ev = &(e->xbutton);
- //printf("BTN_UP(w: 0x%lx x: %d y: %d rx: %d ry: %d)\n", ev->window, ev->x, ev->y, ev->x_root, ev->y_root);
- Location loc = {0};
- if (mons_find(ev->window, &loc) && (loc.client->frame == ev->window))
- {
- mouse_up(ev, &loc);
- }
- X.mode = M_IDLE;
- XUngrabPointer(X.disp, CurrentTime);
-}
+ XUnmapEvent* ev = &(e->xunmap);
+ //printf("UNMAP(e: 0x%lx w: 0x%lx %d)\n", ev->event, ev->window, ev->from_configure);
-static void xbtnmotion(XEvent* e)
-{
- /* make sure we get just the latest event */
- XMotionEvent *ev = &e->xmotion;
- //printf("BTN_MV(w: 0x%lx x: %d y: %d rx: %d ry: %d)\n", ev->window, ev->x, ev->y, ev->x_root, ev->y_root);
- while (XCheckTypedWindowEvent(X.disp, ev->window, ev->type, e));
- Location loc = {0};
- if (mons_find(ev->window, &loc) && (loc.client->frame == ev->window))
+ Client* client = Client_Find(ev->window);
+ if (client)
{
- mouse_drag(ev, &loc);
+ if (ev->event == X.root)
+ {
+ Client_Del(client);
+ }
+ else if ( !(client->flags & F_SHADED) )
+ {
+ XUnmapWindow(X.disp, client->frame);
+ }
}
- X.last_x = ev->x_root, X.last_y = ev->y_root;
}
-static void xconfignotify(XEvent* e)
+/* Handle closed/destroyed windows */
+static void xdestroynotify(XEvent* e)
{
- XConfigureEvent* ev = &(e->xconfigure);
- if (ev->window == X.root)
+ XDestroyWindowEvent* ev = &(e->xdestroywindow);
+ //printf("DESTROY(w: 0x%lx)\n", ev->window);
+
+ Client* client = Client_Find(ev->window);
+ if (client)
{
- puts("root window resized");
+ Client_Del(client);
}
}
+/* Handle window resize requests. Ignore them for tiled windows. */
static void xconfigrequest(XEvent* e)
{
XConfigureRequestEvent* ev = &(e->xconfigurerequest);
wc.border_width = ev->border_width;
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
- Location loc = {0};
- if (mons_find(ev->window, &loc))
+
+ Client* client = Client_Find(ev->window);
+ if (client)
{
/* only allow floating clients to resize on their own */
- if ((loc.client->win == ev->window) && !loc.column)
+ if ((client->win == ev->window) && !client->column)
{
- loc.client->w = wc.width + FRAME_WIDTH_SUM;
- loc.client->h = wc.height + FRAME_HEIGHT_SUM;
- client_adjust(loc.client);
- if (X.mode == M_RESIZE && Focused == loc.client)
+ client->w = wc.width + FRAME_WIDTH_SUM;
+ client->h = wc.height + FRAME_HEIGHT_SUM;
+ Client_AdjustSize(client);
+ if (X.mode == M_RESIZE && Focused == client)
{
- mouse_tocorner(loc.client);
+ mouse_tocorner(client);
}
}
+
}
else
{
}
}
-static void xmaprequest(XEvent* e)
-{
- XMapRequestEvent* ev = &(e->xmaprequest);
- //printf("MAP(w: 0x%lx)\n", ev->window);
- XWindowAttributes attr;
- Location loc = {0};
- if (!mons_find(ev->window, &loc))
- {
- if (XGetWindowAttributes(X.disp, ev->window, &attr) && !attr.override_redirect)
- {
- (void)client_add(ev->window, &attr);
- }
- }
-}
-
-static void xunmapnotify(XEvent* e)
-{
- XUnmapEvent* ev = &(e->xunmap);
- //printf("UNMAP(e: 0x%lx w: 0x%lx %d)\n", ev->event, ev->window, ev->from_configure);
- Location loc = {0};
- if (mons_find(ev->window, &loc))// && loc.client->win == ev->window)
- {
- if (ev->event == X.root && ev->window == loc.client->win)
- {
- mons_delclient(&loc);
- }
- else if ( !(loc.client->flags & F_SHADED) )
- {
- XUnmapWindow(X.disp, loc.client->frame);
- }
- }
-}
-
-static void xdestroynotify(XEvent* e)
-{
- XDestroyWindowEvent* ev = &(e->xdestroywindow);
- //printf("DESTROY(w: 0x%lx)\n", ev->window);
- Location loc = {0};
- if (mons_find(ev->window, &loc))
- {
- mons_delclient(&loc);
- }
-}
-
+/* Handle client messages. ICCM and EWMH stuff. */
static void xclientmsg(XEvent* e)
{
XClientMessageEvent* ev = &(e->xclient);
//printf("CLIENT_MSG(w: 0x%lx a: '%s')\n", ev->window, XGetAtomName(X.disp, ev->message_type));
+
if (ev->message_type == atom("_NET_ACTIVE_WINDOW"))
{
- mons_activate(ev->window);
+ Client_SetActive(ev->window);
}
}
+/* Handle window properties */
static void xpropnotify(XEvent* e)
{
XPropertyEvent* ev = &(e->xproperty);
//printf("PROP_NOTIFY(w: 0x%lx)\n", ev->window);
- Location loc = {0};
- if (mons_find(ev->window, &loc))
+
+ Client* client = Client_Find(ev->window);
+ if (client)
{
- client_readprops(loc.client);
- client_draw(loc.client);
+ Client_ReadProps(client);
+ Client_Draw(client);
}
}
+/* Handle window focus. Focus follows mouse */
static void xenternotify(XEvent* e)
{
XCrossingEvent* ev = &(e->xcrossing);
- Location loc = {0};
//printf("ENTER(w: 0x%lx s: %d m: %d d: %d)\n", ev->window, ev->state, ev->mode, ev->detail);
- if (mons_find(ev->window, &loc))
+
+ Client* client = Client_Find(ev->window);
+ if (client)
{
- client_focus(loc.client);
+ Client_Focus(client);
}
}
+/* Handle redraw events */
static void xexpose(XEvent* e)
{
XExposeEvent* ev = &(e->xexpose);
if (ev->count == 0)
{
//printf("EXPOSE(w: 0x%lx)\n", ev->window);
- Location loc = {0};
- if (mons_find(ev->window, &loc))
+ Client* client = Client_Find(ev->window);
+ if (client)
{
- client_draw(loc.client);
+ Client_Draw(client);
}
}
}
+static void xbtnpress(XEvent* e)
+{
+ XButtonEvent* ev = &(e->xbutton);
+ XGrabPointer(X.disp, ev->window, False,
+ ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
+ GrabModeAsync, GrabModeAsync, None, X.csr_move, CurrentTime);
+ //printf("BTN_DN(w: 0x%lx s: %d x: %d y: %d rx: %d ry: %d)\n", ev->window, ev->state, ev->x, ev->y, ev->x_root, ev->y_root);
+ X.start_x = ev->x_root, X.start_y = ev->y_root;
+ X.last_x = ev->x_root, X.last_y = ev->y_root;
+
+
+ Client* client = Client_Find(ev->window);
+ if (client && (client->frame == ev->window))
+ {
+ if (ev->y < MIN_HEIGHT)
+ {
+ X.edge = E_TOP;
+ }
+ else if (ev->y_root > (client->y + client->h - BORDER_WIDTH))
+ {
+ X.edge = E_BOTTOM;
+ }
+ else if (ev->x < BORDER_WIDTH)
+ {
+ X.edge = E_LEFT;
+ }
+ else if (ev->x_root > (client->x + client->w - BORDER_WIDTH))
+ {
+ X.edge = E_RIGHT;
+ }
+ else
+ {
+ X.edge = E_NONE;
+ }
+ Mouse_Down(ev, client);
+ }
+}
+
+static void xbtnrelease(XEvent* e)
+{
+ XButtonEvent* ev = &(e->xbutton);
+ //printf("BTN_UP(w: 0x%lx x: %d y: %d rx: %d ry: %d)\n", ev->window, ev->x, ev->y, ev->x_root, ev->y_root);
+
+ Client* client = Client_Find(ev->window);
+ if (client && (client->frame == ev->window))
+ {
+ Mouse_Up(ev, client);
+ }
+ X.mode = M_IDLE;
+ XUngrabPointer(X.disp, CurrentTime);
+}
+
+static void xbtnmotion(XEvent* e)
+{
+ /* make sure we get just the latest event */
+ XMotionEvent *ev = &e->xmotion;
+ //printf("BTN_MV(w: 0x%lx x: %d y: %d rx: %d ry: %d)\n", ev->window, ev->x, ev->y, ev->x_root, ev->y_root);
+
+ while (XCheckTypedWindowEvent(X.disp, ev->window, ev->type, e));
+ Client* client = Client_Find(ev->window);
+ if (client && (client->frame == ev->window))
+ {
+ Mouse_Drag(ev, client);
+ }
+ X.last_x = ev->x_root, X.last_y = ev->y_root;
+}
+
static void xkeypress(XEvent* e)
{
XKeyEvent* ev = &(e->xkey);
//printf("KEY_DN(w: 0x%lx)\n", ev->window);
- keys_run(ev);
+
+ Keys_Run(ev);
}
static void init_cursors(void)
X.eventfns[ButtonRelease] = xbtnrelease;
X.eventfns[MotionNotify] = xbtnmotion;
X.eventfns[KeyPress] = xkeypress;
- X.eventfns[ConfigureNotify] = xconfignotify;
X.eventfns[ConfigureRequest] = xconfigrequest;
X.eventfns[MapRequest] = xmaprequest;
X.eventfns[UnmapNotify] = xunmapnotify;