diff options
Diffstat (limited to 'calmwm.c')
-rw-r--r-- | calmwm.c | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/calmwm.c b/calmwm.c new file mode 100644 index 0000000..ff09bfc --- /dev/null +++ b/calmwm.c @@ -0,0 +1,345 @@ +/* + * calmwm - the calm window manager + * + * Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org> + * All rights reserved. + * + * $Id: calmwm.c,v 1.1.1.1 2007/04/27 17:58:48 bernd Exp $ + */ + +#include "headers.h" +#include "calmwm.h" + +Display *G_dpy; +XFontStruct *G_font; + +Cursor G_cursor_move; +Cursor G_cursor_resize; +Cursor G_cursor_select; +Cursor G_cursor_default; +Cursor G_cursor_question; + +struct screen_ctx_q G_screenq; +struct screen_ctx *G_curscreen; +u_int G_nscreens; + +struct client_ctx_q G_clientq; + +int G_doshape, G_shape_ev; +int G_starting; +struct conf G_conf; +struct fontdesc *DefaultFont; +char *DefaultFontName; + +/* From TWM */ +#define gray_width 2 +#define gray_height 2 +static char gray_bits[] = {0x02, 0x01}; + +/* List borrowed from 9wm/rio */ +char *tryfonts[] = { + "9x15bold", + "blit", + "*-lucidatypewriter-bold-*-14-*-75-*", + "*-lucidatypewriter-medium-*-12-*-75-*", + "fixed", + "*", + NULL, +}; + +static void _sigchld_cb(int); + +int +main(int argc, char **argv) +{ + int ch; + int conf_flags = 0; + + DefaultFontName = "sans-serif:pixelsize=14:bold"; + + while ((ch = getopt(argc, argv, "sf:")) != -1) { + switch (ch) { + case 's': + conf_flags |= CONF_STICKY_GROUPS; + break; + case 'f': + DefaultFontName = xstrdup(optarg); + break; + default: + errx(1, "Unknown option '%c'", ch); + } + } + + /* Ignore a few signals. */ + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + err(1, "signal"); + + if (signal(SIGCHLD, _sigchld_cb) == SIG_ERR) + err(1, "signal"); + + group_init(); + + G_starting = 1; + conf_setup(&G_conf); + G_conf.flags |= conf_flags; + client_setup(); + x_setup(); + G_starting = 0; + + xev_init(); + XEV_QUICK(NULL, NULL, MapRequest, xev_handle_maprequest, NULL); + XEV_QUICK(NULL, NULL, UnmapNotify, xev_handle_unmapnotify, NULL); + XEV_QUICK(NULL, NULL, ConfigureRequest, + xev_handle_configurerequest, NULL); + XEV_QUICK(NULL, NULL, PropertyNotify, xev_handle_propertynotify, NULL); + XEV_QUICK(NULL, NULL, EnterNotify, xev_handle_enternotify, NULL); + XEV_QUICK(NULL, NULL, LeaveNotify, xev_handle_leavenotify, NULL); + XEV_QUICK(NULL, NULL, ButtonPress, xev_handle_buttonpress, NULL); + XEV_QUICK(NULL, NULL, ButtonRelease, xev_handle_buttonrelease, NULL); + XEV_QUICK(NULL, NULL, KeyPress, xev_handle_keypress, NULL); + XEV_QUICK(NULL, NULL, KeyRelease, xev_handle_keyrelease, NULL); + XEV_QUICK(NULL, NULL, Expose, xev_handle_expose, NULL); + XEV_QUICK(NULL, NULL, DestroyNotify, xev_handle_destroynotify, NULL); + XEV_QUICK(NULL, NULL, ClientMessage, xev_handle_clientmessage, NULL); + + xev_loop(); + + return (0); +} + +void +x_setup(void) +{ + int i; + struct screen_ctx *sc; + char *fontname; + + TAILQ_INIT(&G_screenq); + + if ((G_dpy = XOpenDisplay("")) == NULL) + errx(1, "%s:%d XOpenDisplay()", __FILE__, __LINE__); + + XSetErrorHandler(x_errorhandler); + + G_doshape = XShapeQueryExtension(G_dpy, &G_shape_ev, &i); + + i = 0; + while ((fontname = tryfonts[i++]) != NULL) { + if ((G_font = XLoadQueryFont(G_dpy, fontname)) != NULL) + break; + } + + if (fontname == NULL) + errx(1, "Couldn't load any fonts."); + + G_nscreens = ScreenCount(G_dpy); + for (i = 0; i < (int)G_nscreens; i++) { + XMALLOC(sc, struct screen_ctx); + x_setupscreen(sc, i); + TAILQ_INSERT_TAIL(&G_screenq, sc, entry); + } + + G_cursor_move = XCreateFontCursor(G_dpy, XC_fleur); + G_cursor_resize = XCreateFontCursor(G_dpy, XC_bottom_right_corner); + /* (used to be) XCreateFontCursor(G_dpy, XC_hand1); */ + G_cursor_select = XCreateFontCursor(G_dpy, XC_hand1); +/* G_cursor_select = cursor_bigarrow(G_curscreen); */ + G_cursor_default = XCreateFontCursor(G_dpy, XC_X_cursor); +/* G_cursor_default = cursor_bigarrow(G_curscreen); */ + G_cursor_question = XCreateFontCursor(G_dpy, XC_question_arrow); +} + +int +x_setupscreen(struct screen_ctx *sc, u_int which) +{ + XColor tmp; + XGCValues gv, gv1/* , gv2 */; + Window *wins, w0, w1; + u_int nwins, i = 0; + XWindowAttributes winattr; + XSetWindowAttributes rootattr; + struct keybinding *kb; + + sc->display = x_screenname(which); + sc->which = which; + sc->rootwin = RootWindow(G_dpy, which); + XAllocNamedColor(G_dpy, DefaultColormap(G_dpy, which), + "black", &sc->fgcolor, &tmp); + XAllocNamedColor(G_dpy, DefaultColormap(G_dpy, which), + "#00cc00", &sc->bgcolor, &tmp); + XAllocNamedColor(G_dpy,DefaultColormap(G_dpy, which), + "blue", &sc->fccolor, &tmp); + XAllocNamedColor(G_dpy, DefaultColormap(G_dpy, which), + "red", &sc->redcolor, &tmp); + XAllocNamedColor(G_dpy, DefaultColormap(G_dpy, which), + "#00ccc8", &sc->cyancolor, &tmp); + XAllocNamedColor(G_dpy, DefaultColormap(G_dpy, which), + "white", &sc->whitecolor, &tmp); + XAllocNamedColor(G_dpy, DefaultColormap(G_dpy, which), + "black", &sc->blackcolor, &tmp); + + TAILQ_FOREACH(kb, &G_conf.keybindingq, entry) + xu_key_grab(sc->rootwin, kb->modmask, kb->keysym); + + /* Special -- for alt state. */ +/* xu_key_grab(sc->rootwin, 0, XK_Alt_L); */ +/* xu_key_grab(sc->rootwin, 0, XK_Alt_R); */ + + sc->blackpixl = BlackPixel(G_dpy, sc->which); + sc->whitepixl = WhitePixel(G_dpy, sc->which); + sc->bluepixl = sc->fccolor.pixel; + sc->redpixl = sc->redcolor.pixel; + sc->cyanpixl = sc->cyancolor.pixel; + + sc->gray = XCreatePixmapFromBitmapData(G_dpy, sc->rootwin, + gray_bits, gray_width, gray_height, + sc->blackpixl, sc->whitepixl, DefaultDepth(G_dpy, sc->which)); + + sc->blue = XCreatePixmapFromBitmapData(G_dpy, sc->rootwin, + gray_bits, gray_width, gray_height, + sc->bluepixl, sc->whitepixl, DefaultDepth(G_dpy, sc->which)); + + sc->red = XCreatePixmapFromBitmapData(G_dpy, sc->rootwin, + gray_bits, gray_width, gray_height, + sc->redpixl, sc->whitepixl, DefaultDepth(G_dpy, sc->which)); + + gv.foreground = sc->blackpixl^sc->whitepixl; + gv.background = sc->whitepixl; + gv.function = GXxor; + gv.line_width = 1; + gv.subwindow_mode = IncludeInferiors; + gv.font = G_font->fid; + + sc->gc = XCreateGC(G_dpy, sc->rootwin, + GCForeground|GCBackground|GCFunction| + GCLineWidth|GCSubwindowMode|GCFont, &gv); + +#ifdef notyet + gv2.foreground = sc->blackpixl^sc->cyanpixl; + gv2.background = sc->cyanpixl; + gv2.function = GXxor; + gv2.line_width = 1; + gv2.subwindow_mode = IncludeInferiors; + gv2.font = G_font->fid; +#endif + + sc->hlgc = XCreateGC(G_dpy, sc->rootwin, + GCForeground|GCBackground|GCFunction| + GCLineWidth|GCSubwindowMode|GCFont, &gv); + + gv1.function = GXinvert; + gv1.subwindow_mode = IncludeInferiors; + gv1.line_width = 1; + gv1.font = G_font->fid; + + sc->invgc = XCreateGC(G_dpy, sc->rootwin, + GCFunction|GCSubwindowMode|GCLineWidth|GCFont, &gv1); + + font_init(sc); + DefaultFont = font_getx(sc, DefaultFontName); + + /* + * XXX - this should *really* be in screen_init(). ordering + * problem. + */ + TAILQ_INIT(&sc->mruq); + + /* Initialize menu window. */ + grab_menuinit(sc); + search_init(sc); + + /* Deal with existing clients. */ + XQueryTree(G_dpy, sc->rootwin, &w0, &w1, &wins, &nwins); + + for (i = 0; i < nwins; i++) { + XGetWindowAttributes(G_dpy, wins[i], &winattr); + if (winattr.override_redirect || + winattr.map_state != IsViewable) { + char *name; + XFetchName(G_dpy, wins[i], &name); + continue; + } + client_new(wins[i], sc, winattr.map_state != IsUnmapped); + } + XFree(wins); + + G_curscreen = sc; /* XXX */ + screen_init(); + screen_updatestackingorder(); + + rootattr.event_mask = ChildMask|PropertyChangeMask|EnterWindowMask| + LeaveWindowMask|ColormapChangeMask|ButtonMask; + + /* Set the root cursor to a nice obnoxious arrow :-) */ +/* rootattr.cursor = cursor_bigarrow(sc); */ + + XChangeWindowAttributes(G_dpy, sc->rootwin, + /* CWCursor| */CWEventMask, &rootattr); + + XSync(G_dpy, False); + + return (0); +} + +char * +x_screenname(int which) +{ + char *cp, *dstr, *sn; + size_t snlen; + + if (which > 9) + errx(1, "Can't handle more than 9 screens. If you need it, " + "tell <marius@monkey.org>. It's a trivial fix."); + + dstr = xstrdup(DisplayString(G_dpy)); + + if ((cp = rindex(dstr, ':')) == NULL) + return (NULL); + + if ((cp = index(cp, '.')) != NULL) + *cp = '\0'; + + snlen = strlen(dstr) + 3; /* string, dot, number, null */ + sn = (char *)xmalloc(snlen); + snprintf(sn, snlen, "%s.%d", dstr, which); + free(dstr); + + return (sn); +} + +int +x_errorhandler(Display *dpy, XErrorEvent *e) +{ +#ifdef DEBUG + { + char msg[80], number[80], req[80]; + + XGetErrorText(G_dpy, e->error_code, msg, sizeof(msg)); + snprintf(number, sizeof(number), "%d", e->request_code); + XGetErrorDatabaseText(G_dpy, "XRequest", number, + "<unknown>", req, sizeof(req)); + + warnx("%s(0x%x): %s", req, (u_int)e->resourceid, msg); + } +#endif + + if (G_starting && + e->error_code == BadAccess && + e->request_code == X_GrabKey) + errx(1, "root window unavailable - perhaps another " + "wm is running?"); + + return (0); +} + +static void +_sigchld_cb(int which) +{ + pid_t pid; + int status; + +/* Collect dead children. */ + while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || + (pid < 0 && errno == EINTR)) + ; +} |