aboutsummaryrefslogtreecommitdiffstats
path: root/calmwm.c
diff options
context:
space:
mode:
authorbernd2007-04-27 17:58:48 +0000
committerbernd2007-04-27 17:58:48 +0000
commit055eec93ac495df814cc5585fd55712a6cac06c4 (patch)
treea7f9e9b6a1231b28b552199ac2e27c45d64a9ba7 /calmwm.c
downloadcwm-055eec93ac495df814cc5585fd55712a6cac06c4.tar.gz
Initial import of cwm-3.
tested by sturm@, ok matthieu@
Diffstat (limited to 'calmwm.c')
-rw-r--r--calmwm.c345
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))
+ ;
+}