#include "anvil.h"
#include <sys/wait.h>
-void check(intptr_t stat, char* msg)
-{
- if (!stat)
- {
- printf("anvil: fatal error: %s\n", msg);
- exit(1);
- }
-}
+/* X11 State */
+XConf X = {0};
+int (*error_default)(Display* disp, XErrorEvent* ev) = NULL;
+/* Anvil State */
+int PtrX = 0, PtrY = 0;
+int Num_Monitors = 0;
+Monitor Monitors[10] = {0};
+Workspace Workspaces[10] = {0};
+Client* AllClients = NULL;
+Client* Focused = NULL;
/*
*/
-static void xmaprequest(XEvent* e)
+static void XMapRequest(XEvent* e)
{
XMapRequestEvent* ev = &(e->xmaprequest);
printf("MAP(w: 0x%lx)\n", ev->window);
}
}
-static void xunmapnotify(XEvent* e)
+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);
}
}
-static void xdestroynotify(XEvent* e)
+static void XDestroyNotify(XEvent* e)
{
XDestroyWindowEvent* ev = &(e->xdestroywindow);
printf("DESTROY(w: 0x%lx)\n", ev->window);
}
}
-
-
-
-XConf X = {0};
-
-/* Anvil State */
-int PtrX = 0, PtrY = 0;
-int Num_Monitors = 0;
-Monitor Monitors[10] = {0};
-Workspace Workspaces[10] = {0};
-Client* AllClients = NULL;
-Client* Focused = NULL;
-
-static void check_for_wm(void)
-{
- error_default = XSetErrorHandler(error_init);
- XSelectInput(X.disp, X.root, SubstructureRedirectMask|SubstructureNotifyMask);
- XSync(X.disp, False);
- XSetErrorHandler(error_panic);
- XSync(X.disp, False);
-}
-
-static void xbtnpress(XEvent* e)
+static void XBtnPress(XEvent* e)
{
XButtonEvent* ev = &(e->xbutton);
XGrabPointer(X.disp, ev->window, False,
Mouse_Down(ev);
}
-static void xbtnrelease(XEvent* e)
+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);
XUngrabPointer(X.disp, CurrentTime);
}
-static void xbtnmotion(XEvent* e)
+static void XBtnMotion(XEvent* e)
{
/* make sure we get just the latest event */
XMotionEvent *ev = &e->xmotion;
X.last_x = ev->x_root, X.last_y = ev->y_root;
}
-static void xconfigrequest(XEvent* e)
+static void XConfigRequest(XEvent* e)
{
XConfigureRequestEvent* ev = &(e->xconfigurerequest);
printf("CONF(w: 0x%lx x: %d y: %d w: %d h: %d)\n", ev->window, ev->x, ev->y, ev->width, ev->height);
}
}
-static void xconfignotify(XEvent* e)
+static void XConfigNotify(XEvent* e)
{
XConfigureEvent* ev = &(e->xconfigure);
if (ev->window == X.root)
}
}
-static void xclientmsg(XEvent* e)
+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));
// }
}
-static void xpropnotify(XEvent* e)
+static void XPropNotify(XEvent* e)
{
XPropertyEvent* ev = &(e->xproperty);
printf("PROP_NOTIFY(w: 0x%lx)\n", ev->window);
}
}
-static void xenternotify(XEvent* e)
+static void XEnterNotify(XEvent* e)
{
XCrossingEvent* ev = &(e->xcrossing);
printf("ENTER(w: 0x%lx s: %d m: %d d: %d)\n", ev->window, ev->state, ev->mode, ev->detail);
}
}
-static void xexpose(XEvent* e)
+static void XExpose(XEvent* e)
{
XExposeEvent* ev = &(e->xexpose);
if (ev->count == 0)
}
}
-static void xmapnotify(XEvent* e)
+static void XMapNotify(XEvent* e)
{
XMapEvent* ev = &(e->xmap);
printf("MAP(e: 0x%lx w: 0x%lx)\n", ev->event, ev->window);
}
}
-static void xkeypress(XEvent* e)
+static void XKeyPress(XEvent* e)
{
XKeyEvent* ev = &(e->xkey);
printf("KEY_DN(w: 0x%lx)\n", ev->window);
Keys_Process(ev);
}
-static void init_cursors(void)
+static void InitCursors(void)
{
XColor csr_bdr, csr_fill;
Colormap cmap = DefaultColormap(X.disp, X.screen);
XDefineCursor(X.disp, X.root, X.csr_root);
}
-static void init_font(void)
+static void InitFont(void)
{
/* load the font */
char **miss, *def;
X.font = XCreateFontSet(X.disp, FONT_NAME, &miss, &nmiss, &def);
if (!X.font)
{
- X.font = XCreateFontSet(X.disp, "fixed", &miss, &nmiss, &def);
+ printf("anvil: fatal error: unable to create font set for title font\n");
+ exit(1);
}
- check(X.font != NULL, "unable to create font set for title font");
X.font_ext = XExtentsOfFontSet(X.font);
}
-void sigchld(int sig)
+static void SigChldHandler(int sig)
{
(void)sig;
while (waitpid(-1, 0, WNOHANG) > 0);
}
+static int InitErrorHandler(Display* disp, XErrorEvent* ev)
+{
+ (void)disp, (void)ev;
+ printf("anvil: fatal error: another window manager is active");
+ exit(1);
+ return -1;
+}
+
+static int RuntimeErrorHandler(Display* disp, XErrorEvent* ev)
+{
+ printf("error panic!\n");
+
+ int ignore_error = (
+ (ev->error_code == BadWindow)
+ || (ev->request_code == X_SetInputFocus && ev->error_code == BadMatch)
+ || (ev->request_code == X_ConfigureWindow && ev->error_code == BadMatch)
+ || (ev->request_code == X_ChangeWindowAttributes && ev->error_code == BadMatch)
+ );
+ if (ignore_error)
+ {
+ return 0;
+ }
+ fprintf(stderr, "anvil: fatal error: request code=%d, error code=%d\n", ev->request_code, ev->error_code);
+ return error_default(disp, ev);
+}
+
int main(void)
{
/* make sure we cleanup zombie processes */
- signal(SIGCHLD, sigchld);
+ signal(SIGCHLD, SigChldHandler);
/* remap stdout and stderr to file */
fclose(stdout);
stderr = log;
/* Initialize X server*/
- check( (X.disp = XOpenDisplay(0)) != NULL,
- "could not open display");
+ if (!(X.disp = XOpenDisplay(0)))
+ {
+ printf("anvil: fatal error: could not open display\n");
+ exit(1);
+ }
X.mode = M_INIT;
X.root = DefaultRootWindow(X.disp);
X.screen = DefaultScreen(X.disp);
XGetWindowAttributes(X.disp, X.root, &wa);
X.visual = wa.visual;
+ /* try to establish that we are the window manager now */
+ error_default = XSetErrorHandler(InitErrorHandler);
+ XSelectInput(X.disp, X.root, SubstructureRedirectMask|SubstructureNotifyMask);
+ XSync(X.disp, False);
+ XSetErrorHandler(RuntimeErrorHandler);
+ XSync(X.disp, False);
+
/* initialize all the things */
- check_for_wm();
- init_cursors();
- init_font();
+ InitCursors();
+ InitFont();
Client_InitAll();
Keys_Init();
Monitors_Init();
- atoms_init();
+ Atoms_Init();
/* setup window life-cycle management event handlers */
- X.eventfns[MapRequest] = xmaprequest;
- X.eventfns[UnmapNotify] = xunmapnotify;
- X.eventfns[DestroyNotify] = xdestroynotify;
+ X.eventfns[MapRequest] = XMapRequest;
+ X.eventfns[UnmapNotify] = XUnmapNotify;
+ X.eventfns[DestroyNotify] = XDestroyNotify;
/* all other events */
- X.eventfns[MapNotify] = xmapnotify;
- X.eventfns[ButtonPress] = xbtnpress;
- X.eventfns[ButtonRelease] = xbtnrelease;
- X.eventfns[MotionNotify] = xbtnmotion;
- X.eventfns[KeyPress] = xkeypress;
- X.eventfns[ConfigureRequest] = xconfigrequest;
- X.eventfns[ConfigureNotify] = xconfignotify;
- X.eventfns[ClientMessage] = xclientmsg;
- X.eventfns[PropertyNotify] = xpropnotify;
- X.eventfns[EnterNotify] = xenternotify;
- X.eventfns[Expose] = xexpose;
+ X.eventfns[MapNotify] = XMapNotify;
+ X.eventfns[ButtonPress] = XBtnPress;
+ X.eventfns[ButtonRelease] = XBtnRelease;
+ X.eventfns[MotionNotify] = XBtnMotion;
+ X.eventfns[KeyPress] = XKeyPress;
+ X.eventfns[ConfigureRequest] = XConfigRequest;
+ X.eventfns[ConfigureNotify] = XConfigNotify;
+ X.eventfns[ClientMessage] = XClientMsg;
+ X.eventfns[PropertyNotify] = XPropNotify;
+ X.eventfns[EnterNotify] = XEnterNotify;
+ X.eventfns[Expose] = XExpose;
/* main event loop */
XSync(X.disp, False);
extern Client* AllClients;
extern Client* Focused;
-/* list.c */
-int list_length(void* list);
-void* list_del(void* list, void* node);
-void* list_prev(void* list, void* curr);
-void* list_last(void* list);
-#define LIST_FOR_EACH(val,list) \
- for (val = list; (val != NULL); val = val->next)
-#define LIST_FOR_EACH_UNTIL(val,list,cond) \
- for (val = list; (val != NULL) && !(cond); val = val->next)
-
/* keys.c */
void Keys_Init(void);
void Keys_Process(XKeyEvent* ev);
void Mouse_Up(XButtonEvent* ev);
void Mouse_Drag(XMotionEvent* ev);
void Mouse_ToCorner(Client* c);
+void Mouse_ToTitle(Client* c);
void Mouse_GetLocation(int* ptrx, int* ptry);
/* monitors.c */
void Monitors_SetWorkspace(int id);
void Monitors_SendToWorkspace(Client* c, int id);
-/* error.c */
-extern int (*error_default)(Display* disp, XErrorEvent* ev);
-int error_init(Display* disp, XErrorEvent* ev);
-int error_panic(Display* disp, XErrorEvent* ev);
-
#endif
Atom _NET_WM_WINDOW_TYPE;
Atom _NET_WM_WINDOW_TYPE_DIALOG;
-void atoms_init(void) {
+void Atoms_Init(void) {
WM_STATE = XInternAtom(X.disp, "WM_STATE", False);
WM_NAME = XInternAtom(X.disp, "WM_NAME", False);
WM_ICON_NAME = XInternAtom(X.disp, "WM_ICON_NAME", False);
extern Atom _NET_WM_WINDOW_TYPE;
extern Atom _NET_WM_WINDOW_TYPE_DIALOG;
-void atoms_init(void);
+void Atoms_Init(void);
#define HiddenState 2
+#define LIST_FOR_EACH(val,list) \
+ for (val = list; (val != NULL); val = val->next)
+
static void ReadProps(Client* c);
static void Redraw(Client* c);
static void LayerWindows(void);
static int MonitorOverlap(Monitor* mon, Client* c);
-
-void* ecalloc(size_t n, size_t sz)
-{
- void* p = calloc(n, sz);
- if (!p)
- {
- printf("anvil: fatal error: memory allocation failed\n");
- exit(1);
- }
- return p;
-}
-
-void xfree(void* p)
-{
- if (p)
- {
- XFree(p);
- }
-}
-
-void sendmsg(Window win, Atom proto, Atom type)
-{
- XEvent ev;
- memset(&ev, 0, sizeof(ev));
- ev.xclient.type = ClientMessage;
- ev.xclient.window = win;
- ev.xclient.message_type = proto;
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = type;
- ev.xclient.data.l[1] = CurrentTime;
- XSendEvent(X.disp, win, False, 0, &ev);
-}
-
-
-void SetWMState(Client *c, int state)
-{
- CARD32 data[2] = {state, None};
- c->state = state;
- XChangeProperty(X.disp, c->win, WM_STATE, WM_STATE, 32, PropModeReplace, (unsigned char *)data, 2);
-}
-
-///* If we can't find a WM_STATE we're going to have to assume
-// * Withdrawn. This is not exactly optimal, since we can't really
-// * distinguish between the case where no WM has run yet and when the
-// * state was explicitly removed (Clients are allowed to either set the
-// * atom to Withdrawn or just remove it... yuck.) */
-//
-//long GetWMState(Client *c)
-//{
-// Atom real_type;
-// int real_format;
-// long state = WithdrawnState;
-// unsigned long items_read, items_left;
-// unsigned char *data;
-//
-// if (XGetWindowProperty(dsply, c->window, wm_state, 0L, 2L, False, wm_state, &real_type, &real_format, &items_read, &items_left, &data) == Success && items_read)
-// {
-// state = *(long *)data;
-// XFree(data);
-// }
-// return state;
-//}
+static void* Allocate(size_t n, size_t sz);
+static void xfree(void* p);
+static void SendMessage(Window win, Atom proto, Atom type);
+static void SetWMState(Client *c, int state);
+static void* ListDelete(void* list, void* node);
Client* Client_Find(Window win)
{
if (XGetWindowAttributes(X.disp, win, &attr) && !attr.override_redirect)
{
/* we care about it, let's add it to withdrawn */
- c = ecalloc(1, sizeof(Client));
+ c = Allocate(1, sizeof(Client));
c->win = win;
c->x = attr.x;
c->y = attr.y;
return c;
}
-
-
-
void Client_Show(Client* c)
{
/* position it with relative coords */
{
Focused = NULL;
}
- AllClients = list_del(AllClients, c);
+ AllClients = ListDelete(AllClients, c);
xfree(c->name);
XDestroyWindow(X.disp, c->frame);
free(c);
void Client_Raise(Client* c)
{
- AllClients = list_del(AllClients, c);
+ AllClients = ListDelete(AllClients, c);
c->next = AllClients;
AllClients = c;
LayerWindows();
{
if (client->flags & F_WM_DELETE)
{
- sendmsg(client->win, WM_PROTOCOLS, WM_DELETE_WINDOW);
+ SendMessage(client->win, WM_PROTOCOLS, WM_DELETE_WINDOW);
}
else
{
c->rel_y = c->y - Monitors[monitor].y;
}
+
+
+
+
+void Client_InitAll(void)
+{
+// /* TODO: Find all top-level windows and register them correctly
+//
+// * Find all root children with override_redirect set False
+// * Add them to withdrawn list if WM_STATE = withdrawn
+// * Add them as floating and unshaded if WM_STATE = Normal
+// * Add them as floating ad shaded if WM_STATE = Iconic
+//
+// */
+//
+// unsigned int nwins;
+// Window d1, d2, *wins = NULL;
+// XWindowAttributes attr;
+// if (XQueryTree(X.disp, X.root, &d1, &d2, &wins, &nwins))
+// {
+// for (unsigned int i = 0; i < nwins; i++)
+// {
+// if (XGetWindowAttributes(X.disp, wins[i], &attr) && (attr.override_redirect == False))
+// {
+// Client* c = client_add(wins[i], &attr);
+// c->flags |= F_FLOATING;
+// }
+// }
+// xfree(wins);
+// }
+}
+
+void Client_UpdateAll(void)
+{
+ int wspace_mask = 0;
+ for (int i = 0; i < Num_Monitors; i++)
+ {
+ wspace_mask |= (1 << Monitors[i].wspace);
+ }
+ printf("0x%x\n", wspace_mask);
+
+ Client* c;
+ LIST_FOR_EACH(c, AllClients)
+ {
+ int wspace_active = ((wspace_mask & (1 << c->wspace)) != 0);
+ printf("(0x%x & 0x%x) != 0 == %d\n", wspace_mask, (1 << c->wspace), wspace_active);
+
+ if (wspace_active && (c->state != WithdrawnState))
+ {
+ printf("Show 0x%lx\n", c->win);
+ Client_Show(c);
+ }
+ else
+ {
+ printf("Hide 0x%lx\n", c->win);
+ Client_Hide(c);
+ }
+ }
+}
+
+//void client_shade(Client* c)
+//{
+// client_setshade(c, ((c->flags & F_SHADED) ? 0 : 1));
+// Client_MoveResize(c);
+//}
+//
+//void client_setshade(Client* c, int shade)
+//{
+// if (!shade && (c->flags & F_SHADED))
+// {
+// c->flags &= ~F_SHADED;
+// XMapWindow(X.disp, c->win);
+// }
+// else if (shade && !(c->flags & F_SHADED))
+// {
+// c->flags |= F_SHADED;
+// XUnmapWindow(X.disp, c->win);
+// }
+//}
+
+
static void ReadProps(Client* c)
{
Atom *protos = NULL, actual_type, *wintype;
}
}
-void LayerWindows(void)
+static void LayerWindows(void)
{
int nwins = 0;
Window* wins = NULL;
xfree(wins);
}
-
-
-
-void Client_InitAll(void)
-{
-// /* TODO: Find all top-level windows and register them correctly
-//
-// * Find all root children with override_redirect set False
-// * Add them to withdrawn list if WM_STATE = withdrawn
-// * Add them as floating and unshaded if WM_STATE = Normal
-// * Add them as floating ad shaded if WM_STATE = Iconic
-//
-// */
-//
-// unsigned int nwins;
-// Window d1, d2, *wins = NULL;
-// XWindowAttributes attr;
-// if (XQueryTree(X.disp, X.root, &d1, &d2, &wins, &nwins))
-// {
-// for (unsigned int i = 0; i < nwins; i++)
-// {
-// if (XGetWindowAttributes(X.disp, wins[i], &attr) && (attr.override_redirect == False))
-// {
-// Client* c = client_add(wins[i], &attr);
-// c->flags |= F_FLOATING;
-// }
-// }
-// xfree(wins);
-// }
-}
-
-void Client_UpdateAll(void)
-{
- int wspace_mask = 0;
- for (int i = 0; i < Num_Monitors; i++)
- {
- wspace_mask |= (1 << Monitors[i].wspace);
- }
- printf("0x%x\n", wspace_mask);
-
- Client* c;
- LIST_FOR_EACH(c, AllClients)
- {
- int wspace_active = ((wspace_mask & (1 << c->wspace)) != 0);
- printf("(0x%x & 0x%x) != 0 == %d\n", wspace_mask, (1 << c->wspace), wspace_active);
-
- if (wspace_active && (c->state != WithdrawnState))
- {
- printf("Show 0x%lx\n", c->win);
- Client_Show(c);
- }
- else
- {
- printf("Hide 0x%lx\n", c->win);
- Client_Hide(c);
- }
- }
-}
-
-
static int MonitorOverlap(Monitor* mon, Client* c)
{
/* calculate client boundaries */
return area;
}
+static void* Allocate(size_t n, size_t sz)
+{
+ void* p = calloc(n, sz);
+ if (!p)
+ {
+ printf("anvil: fatal error: memory allocation failed\n");
+ exit(1);
+ }
+ return p;
+}
+static void xfree(void* p)
+{
+ if (p)
+ {
+ XFree(p);
+ }
+}
+static void SendMessage(Window win, Atom proto, Atom type)
+{
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = win;
+ ev.xclient.message_type = proto;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = type;
+ ev.xclient.data.l[1] = CurrentTime;
+ XSendEvent(X.disp, win, False, 0, &ev);
+}
-//void client_shade(Client* c)
-//{
-// client_setshade(c, ((c->flags & F_SHADED) ? 0 : 1));
-// Client_MoveResize(c);
-//}
-//
-//void client_setshade(Client* c, int shade)
-//{
-// if (!shade && (c->flags & F_SHADED))
-// {
-// c->flags &= ~F_SHADED;
-// XMapWindow(X.disp, c->win);
-// }
-// else if (shade && !(c->flags & F_SHADED))
-// {
-// c->flags |= F_SHADED;
-// XUnmapWindow(X.disp, c->win);
-// }
-//}
+static void SetWMState(Client *c, int state)
+{
+ CARD32 data[2] = {state, None};
+ c->state = state;
+ XChangeProperty(X.disp, c->win, WM_STATE, WM_STATE, 32, PropModeReplace, (unsigned char *)data, 2);
+}
+
+static void* ListDelete(void* list, void* node)
+{
+ Node *l = list, *n = node;
+ if (!l)
+ {
+ return NULL;
+ }
+ else if (l == n)
+ {
+ return l->next;
+ }
+ else
+ {
+ l->next = ListDelete(l->next, n);
+ return l;
+ }
+}
+++ /dev/null
-#include "anvil.h"
-
-int (*error_default)(Display* disp, XErrorEvent* ev) = NULL;
-
-int error_init(Display* disp, XErrorEvent* ev)
-{
- (void)disp, (void)ev;
- printf("anvil: fatal error: another window manager is active");
- exit(1);
- return -1;
-}
-
-int error_panic(Display* disp, XErrorEvent* ev)
-{
- printf("error panic!\n");
-
- int ignore_error = (
- (ev->error_code == BadWindow)
- || (ev->request_code == X_SetInputFocus && ev->error_code == BadMatch)
- || (ev->request_code == X_ConfigureWindow && ev->error_code == BadMatch)
- || (ev->request_code == X_ChangeWindowAttributes && ev->error_code == BadMatch)
- );
- if (ignore_error)
- {
- return 0;
- }
- fprintf(stderr, "anvil: fatal error: request code=%d, error code=%d\n", ev->request_code, ev->error_code);
- return error_default(disp, ev);
-}
echo "Atom $line;" >> "$src"
done < atoms
echo "" >> "$hdr"
-echo "void atoms_init(void);" >> "$hdr"
+echo "void Atoms_Init(void);" >> "$hdr"
echo "" >> "$src"
-echo "void atoms_init(void) {" >> "$src"
+echo "void Atoms_Init(void) {" >> "$src"
while IFS= read -r atom; do
echo " $atom = XInternAtom(X.disp, \"$atom\", False);" >> "$src"
done < atoms
+++ /dev/null
-#include "anvil.h"
-
-int list_length(void* list)
-{
- int length = 0;
- for (Node* n = list; n; n = n->next, length++);
- return length;
-}
-
-void* list_del(void* list, void* node)
-{
- Node *l = list, *n = node;
- if (!l)
- {
- return NULL;
- }
- else if (l == n)
- {
- return l->next;
- }
- else
- {
- l->next = list_del(l->next, n);
- return l;
- }
-}
-
-void* list_prev(void* list, void* node)
-{
- Node *prev = list, *n = node;
- for (; prev && prev->next != n; prev = prev->next);
- return prev;
-}
-
-void* list_last(void* list)
-{
- Node* tail = list;
- for (; tail && tail->next; tail = tail->next);
- return tail;
-}
-
}
}
-//
-//void mouse_totitle(Client* c)
-//{
-// XWarpPointer(X.disp, None, X.root, 0, 0, 0, 0, (c->x + c->w/2), c->y + (MIN_HEIGHT/2));
-//}
-//
-//void mouse_get(int* ptrx, int* ptry)
-//{
-// Window root = 0, child = 0;
-// int winx = 0, winy = 0, mask = 0;
-// XQueryPointer(X.disp, X.root, &root, &child, ptrx, ptry, &winx, &winy, (unsigned int*)&mask);
-//}
-
-
-
-
-
void Mouse_Down(XButtonEvent* ev)
{
Client* c = Client_Find(ev->window);
X.last_y = c->y + new_h;
}
+void Mouse_ToTitle(Client* c)
+{
+ XWarpPointer(X.disp, None, X.root, 0, 0, 0, 0, (c->x + c->w/2), c->y + (MIN_HEIGHT/2));
+}
+
void Mouse_GetLocation(int* ptrx, int* ptry)
{
Window root = 0, child = 0;