morpheus

suckless linux distro
git clone git://git.2f30.org/morpheus.git
Log | Files | Refs | Submodules | README | LICENSE

commit 0745b928e350f913d0335743edbd96e133956601
parent e2507715b932d4ea8433872ad60e6b13c4682d4d
Author: sin <sin@2f30.org>
Date:   Tue, 18 Feb 2014 11:12:50 +0000

Add TinyWM and xsetroot

Diffstat:
pkgs/tinywm | 11+++++++++++
pkgs/xsetroot | 11+++++++++++
stage0 | 4+++-
stuff/tinywm.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
stuff/xsetroot.c | 545+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 628 insertions(+), 1 deletion(-)

diff --git a/pkgs/tinywm b/pkgs/tinywm @@ -0,0 +1,11 @@ +build() { + cd stuff + x86_64-musl-linux-gcc -I$libcroot/include -L$libcroot/lib tinywm.c -o tinywm -lX11 -static || return 1 + cd - +} + +install() { + cd stuff + cp tinywm $root/bin + cd - +} diff --git a/pkgs/xsetroot b/pkgs/xsetroot @@ -0,0 +1,11 @@ +build() { + cd stuff + x86_64-musl-linux-gcc -I$libcroot/include -L$libcroot/lib xsetroot.c -o xsetroot -lX11 -static || return 1 + cd - +} + +install() { + cd stuff + cp xsetroot $root/bin + cd - +} diff --git a/stage0 b/stage0 @@ -27,6 +27,8 @@ packages="crossmusl tinyxserver tmux ubase - uuterm" + uuterm + tinywm + xsetroot" ./pkgbuild $packages diff --git a/stuff/tinywm.c b/stuff/tinywm.c @@ -0,0 +1,58 @@ +/* TinyWM is written by Nick Welch <mack@incise.org>, 2005. + * + * This software is in the public domain + * and is provided AS IS, with NO WARRANTY. */ + +#include <X11/Xlib.h> + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +int main() +{ + Display * dpy; + Window root; + XWindowAttributes attr; + XButtonEvent start; + XEvent ev; + + if(!(dpy = XOpenDisplay(0x0))) return 1; + + root = DefaultRootWindow(dpy); + + XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F1")), Mod1Mask, root, + True, GrabModeAsync, GrabModeAsync); + XGrabButton(dpy, 1, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); + XGrabButton(dpy, 3, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); + + for(;;) + { + XNextEvent(dpy, &ev); + if(ev.type == KeyPress && ev.xkey.subwindow != None) + XRaiseWindow(dpy, ev.xkey.subwindow); + else if(ev.type == ButtonPress && ev.xbutton.subwindow != None) + { + XGrabPointer(dpy, ev.xbutton.subwindow, True, + PointerMotionMask|ButtonReleaseMask, GrabModeAsync, + GrabModeAsync, None, None, CurrentTime); + XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr); + start = ev.xbutton; + } + else if(ev.type == MotionNotify) + { + int xdiff, ydiff; + while(XCheckTypedEvent(dpy, MotionNotify, &ev)); + xdiff = ev.xbutton.x_root - start.x_root; + ydiff = ev.xbutton.y_root - start.y_root; + XMoveResizeWindow(dpy, ev.xmotion.window, + attr.x + (start.button==1 ? xdiff : 0), + attr.y + (start.button==1 ? ydiff : 0), + MAX(1, attr.width + (start.button==3 ? xdiff : 0)), + MAX(1, attr.height + (start.button==3 ? ydiff : 0))); + } + else if(ev.type == ButtonRelease) + XUngrabPointer(dpy, CurrentTime); + } +} + diff --git a/stuff/xsetroot.c b/stuff/xsetroot.c @@ -0,0 +1,545 @@ +/* + * +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +/* + * xsetroot.c MIT Project Athena, X Window System root window + * parameter setting utility. This program will set + * various parameters of the X root window. + * + * Author: Mark Lillibridge, MIT Project Athena + * 11-Jun-87 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/Xmu/CurUtil.h> +#include <X11/Xcursor/Xcursor.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "X11/bitmaps/gray" + +#define Dynamic 1 + +static char *program_name; +static Display *dpy; +static int screen; +static Window root; +static char *fore_color = NULL; +static char *back_color = NULL; +static int reverse = 0; +static int save_colors = 0; +static int unsave_past = 0; +static Pixmap save_pixmap = (Pixmap)None; + +static void usage(void) _X_NORETURN; +static void FixupState(void); +static void SetBackgroundToBitmap(Pixmap bitmap, + unsigned int width, unsigned int height); +static Cursor CreateCursorFromFiles(char *cursor_file, char *mask_file); +static Cursor CreateCursorFromName(char *name); +static Pixmap MakeModulaBitmap(int mod_x, int mod_y); +static XColor NameToXColor(char *name, unsigned long pixel); +static unsigned long NameToPixel(char *name, unsigned long pixel); +static Pixmap ReadBitmapFile(char *filename, unsigned int *width, unsigned int *height, int *x_hot, int *y_hot); + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [options]\n%s\n", program_name, + " where options are:\n" + " -display <display> or -d <display>\n" + " -fg <color> or -foreground <color>\n" + " -bg <color> or -background <color>\n" + " -rv or -reverse\n" + " -def or -default\n" + " -name <string>\n" + " -cursor <cursor file> <mask file>\n" + " -cursor_name <cursor-font name>\n" + " -xcf <ARGB cursor file> <cursor size>\n" + " -solid <color>\n" + " -gray or -grey\n" + " -bitmap <filename>\n" + " -mod <x> <y>\n" + " -help\n" + " -version\n" + ); + exit(1); + /*NOTREACHED*/ +} + + +int +main(int argc, char *argv[]) +{ + int excl = 0; + int nonexcl = 0; + int restore_defaults = 0; + char *display_name = NULL; + char *name = NULL; + char *cursor_file = NULL; + char *cursor_mask = NULL; + char *cursor_name = NULL; + char *solid_color = NULL; + char *xcf = NULL; + int xcf_size = 32; + Cursor cursor; + int gray = 0; + char *bitmap_file = NULL; + int mod_x = 0; + int mod_y = 0; + register int i; + unsigned int ww, hh; + Pixmap bitmap; + + program_name=argv[0]; + + for (i = 1; i < argc; i++) { + if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) { + if (++i>=argc) usage (); + display_name = argv[i]; + continue; + } + if (!strcmp("-help", argv[i])) { + usage(); + } + if (!strcmp("-version", argv[i])) { + printf("%s\n", "1.1.1"); + exit(0); + } + if (!strcmp("-def", argv[i]) || !strcmp("-default", argv[i])) { + restore_defaults = 1; + continue; + } + if (!strcmp("-name", argv[i])) { + if (++i>=argc) usage(); + name = argv[i]; + nonexcl++; + continue; + } + if (!strcmp("-cursor", argv[i])) { + if (++i>=argc) usage(); + cursor_file = argv[i]; + if (++i>=argc) usage(); + cursor_mask = argv[i]; + nonexcl++; + continue; + } + if (!strcmp("-cursor_name", argv[i])) { + if (++i>=argc) usage(); + cursor_name = argv[i]; + nonexcl++; + continue; + } + if (!strcmp("-xcf", argv[i])) { + if (++i>=argc) usage(); + xcf = argv[i]; + if (++i>=argc) usage(); + xcf_size = atoi(argv[i]); + if (xcf_size <= 0) + xcf_size = 32; + nonexcl++; + continue; + } + if (!strcmp("-fg",argv[i]) || !strcmp("-foreground",argv[i])) { + if (++i>=argc) usage(); + fore_color = argv[i]; + continue; + } + if (!strcmp("-bg",argv[i]) || !strcmp("-background",argv[i])) { + if (++i>=argc) usage(); + back_color = argv[i]; + continue; + } + if (!strcmp("-solid", argv[i])) { + if (++i>=argc) usage(); + solid_color = argv[i]; + excl++; + continue; + } + if (!strcmp("-gray", argv[i]) || !strcmp("-grey", argv[i])) { + gray = 1; + excl++; + continue; + } + if (!strcmp("-bitmap", argv[i])) { + if (++i>=argc) usage(); + bitmap_file = argv[i]; + excl++; + continue; + } + if (!strcmp("-mod", argv[i])) { + if (++i>=argc) usage(); + mod_x = atoi(argv[i]); + if (mod_x <= 0) mod_x = 1; + if (++i>=argc) usage(); + mod_y = atoi(argv[i]); + if (mod_y <= 0) mod_y = 1; + excl++; + continue; + } + if (!strcmp("-rv",argv[i]) || !strcmp("-reverse",argv[i])) { + reverse = 1; + continue; + } + usage(); + } + + /* Check for multiple use of exclusive options */ + if (excl > 1) { + fprintf(stderr, "%s: choose only one of {solid, gray, bitmap, mod}\n", + program_name); + usage(); + } + + dpy = XOpenDisplay(display_name); + if (!dpy) { + fprintf(stderr, "%s: unable to open display '%s'\n", + program_name, XDisplayName (display_name)); + exit (2); + } + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + + /* If there are no arguments then restore defaults. */ + if (!excl && !nonexcl) + restore_defaults = 1; + + /* Handle a cursor file */ + if (cursor_file) { + cursor = CreateCursorFromFiles(cursor_file, cursor_mask); + XDefineCursor(dpy, root, cursor); + XFreeCursor(dpy, cursor); + } + + if (cursor_name) { + cursor = CreateCursorFromName (cursor_name); + if (cursor) + { + XDefineCursor (dpy, root, cursor); + XFreeCursor (dpy, cursor); + } + } + if (xcf) { + XcursorImages *images = XcursorFilenameLoadImages(xcf, xcf_size); + if (!images) { + fprintf(stderr, "Invalid cursor file \"%s\"\n", xcf); + } else { + cursor = XcursorImagesLoadCursor(dpy, images); + if (cursor) + { + XDefineCursor (dpy, root, cursor); + XFreeCursor (dpy, cursor); + } + } + } + /* Handle -gray and -grey options */ + if (gray) { + bitmap = XCreateBitmapFromData(dpy, root, gray_bits, + gray_width, gray_height); + SetBackgroundToBitmap(bitmap, gray_width, gray_height); + } + + /* Handle -solid option */ + if (solid_color) { + XSetWindowBackground(dpy, root, NameToPixel(solid_color, + BlackPixel(dpy, screen))); + XClearWindow(dpy, root); + unsave_past = 1; + } + + /* Handle -bitmap option */ + if (bitmap_file) { + bitmap = ReadBitmapFile(bitmap_file, &ww, &hh, (int *)NULL, (int *)NULL); + SetBackgroundToBitmap(bitmap, ww, hh); + } + + /* Handle set background to a modula pattern */ + if (mod_x) { + bitmap = MakeModulaBitmap(mod_x, mod_y); + SetBackgroundToBitmap(bitmap, 16, 16); + } + + /* Handle set name */ + if (name) + XStoreName(dpy, root, name); + + /* Handle restore defaults */ + if (restore_defaults) { + if (!cursor_file) + XUndefineCursor(dpy, root); + if (!excl) { + XSetWindowBackgroundPixmap(dpy, root, (Pixmap) None); + XClearWindow(dpy, root); + unsave_past = 1; + } + } + + FixupState(); + XCloseDisplay(dpy); + exit (0); +} + + +/* Free past incarnation if needed, and retain state if needed. */ +static void +FixupState(void) +{ + Atom prop, type; + int format; + unsigned long length, after; + unsigned char *data; + + if (!(DefaultVisual(dpy, screen)->class & Dynamic)) + unsave_past = 0; + if (!unsave_past && !save_colors) + return; + prop = XInternAtom(dpy, "_XSETROOT_ID", False); + if (unsave_past) { + (void)XGetWindowProperty(dpy, root, prop, 0L, 1L, True, AnyPropertyType, + &type, &format, &length, &after, &data); + if ((type == XA_PIXMAP) && (format == 32) && + (length == 1) && (after == 0)) + XKillClient(dpy, *((Pixmap *)data)); + else if (type != None) + fprintf(stderr, "%s: warning: _XSETROOT_ID property is garbage\n", + program_name); + } + if (save_colors) { + if (!save_pixmap) + save_pixmap = XCreatePixmap(dpy, root, 1, 1, 1); + XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, PropModeReplace, + (unsigned char *) &save_pixmap, 1); + XSetCloseDownMode(dpy, RetainPermanent); + } +} + +/* + * SetBackgroundToBitmap: Set the root window background to a caller supplied + * bitmap. + */ +static void +SetBackgroundToBitmap(Pixmap bitmap, unsigned int width, unsigned int height) +{ + Pixmap pix; + GC gc; + XGCValues gc_init; + + gc_init.foreground = NameToPixel(fore_color, BlackPixel(dpy, screen)); + gc_init.background = NameToPixel(back_color, WhitePixel(dpy, screen)); + if (reverse) { + unsigned long temp=gc_init.foreground; + gc_init.foreground=gc_init.background; + gc_init.background=temp; + } + gc = XCreateGC(dpy, root, GCForeground|GCBackground, &gc_init); + pix = XCreatePixmap(dpy, root, width, height, + (unsigned int)DefaultDepth(dpy, screen)); + XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, (unsigned long)1); + XSetWindowBackgroundPixmap(dpy, root, pix); + XFreeGC(dpy, gc); + XFreePixmap(dpy, bitmap); + if (save_colors) + save_pixmap = pix; + else + XFreePixmap(dpy, pix); + XClearWindow(dpy, root); + unsave_past = 1; +} + + +/* + * CreateCursorFromFiles: make a cursor of the right colors from two bitmap + * files. + */ +#define BITMAP_HOT_DEFAULT 8 + +static Cursor +CreateCursorFromFiles(char *cursor_file, char *mask_file) +{ + Pixmap cursor_bitmap, mask_bitmap; + unsigned int width, height, ww, hh; + int x_hot, y_hot; + Cursor cursor; + XColor fg, bg, temp; + + fg = NameToXColor(fore_color, BlackPixel(dpy, screen)); + bg = NameToXColor(back_color, WhitePixel(dpy, screen)); + if (reverse) { + temp = fg; fg = bg; bg = temp; + } + + cursor_bitmap = ReadBitmapFile(cursor_file, &width, &height, &x_hot, &y_hot); + mask_bitmap = ReadBitmapFile(mask_file, &ww, &hh, (int *)NULL, (int *)NULL); + + if (width != ww || height != hh) { + fprintf(stderr, +"%s: dimensions of cursor bitmap and cursor mask bitmap are different\n", + program_name); + exit(1); + /*NOTREACHED*/ + } + + if ((x_hot == -1) && (y_hot == -1)) { + x_hot = BITMAP_HOT_DEFAULT; + y_hot = BITMAP_HOT_DEFAULT; + } + if ((x_hot < 0) || (x_hot >= width) || + (y_hot < 0) || (y_hot >= height)) { + fprintf(stderr, "%s: hotspot is outside cursor bounds\n", program_name); + exit(1); + /*NOTREACHED*/ + } + + cursor = XCreatePixmapCursor(dpy, cursor_bitmap, mask_bitmap, &fg, &bg, + (unsigned int)x_hot, (unsigned int)y_hot); + XFreePixmap(dpy, cursor_bitmap); + XFreePixmap(dpy, mask_bitmap); + + return(cursor); +} + +static Cursor +CreateCursorFromName(char *name) +{ + XColor fg, bg, temp; + int i; + Font fid; + + fg = NameToXColor(fore_color, BlackPixel(dpy, screen)); + bg = NameToXColor(back_color, WhitePixel(dpy, screen)); + if (reverse) { + temp = fg; fg = bg; bg = temp; + } + i = XmuCursorNameToIndex (name); + if (i == -1) + return (Cursor) 0; + fid = XLoadFont (dpy, "cursor"); + if (!fid) + return (Cursor) 0; + return XCreateGlyphCursor (dpy, fid, fid, + i, i+1, &fg, &bg); +} + +/* + * MakeModulaBitmap: Returns a modula bitmap based on an x & y mod. + */ +static Pixmap +MakeModulaBitmap(int mod_x, int mod_y) +{ + int i; + long pattern_line = 0; + char modula_data[16*16/8]; + + for (i=16; i--; ) { + pattern_line <<=1; + if ((i % mod_x) == 0) pattern_line |= 0x0001; + } + for (i=0; i<16; i++) { + if ((i % mod_y) == 0) { + modula_data[i*2] = (char)0xff; + modula_data[i*2+1] = (char)0xff; + } else { + modula_data[i*2] = pattern_line & 0xff; + modula_data[i*2+1] = (pattern_line>>8) & 0xff; + } + } + + return(XCreateBitmapFromData(dpy, root, modula_data, 16, 16)); +} + + +/* + * NameToXColor: Convert the name of a color to its Xcolor value. + */ +static XColor +NameToXColor(char *name, unsigned long pixel) +{ + XColor c; + + if (!name || !*name) { + c.pixel = pixel; + XQueryColor(dpy, DefaultColormap(dpy, screen), &c); + } else if (!XParseColor(dpy, DefaultColormap(dpy, screen), name, &c)) { + fprintf(stderr, "%s: unknown color or bad color format: %s\n", + program_name, name); + exit(1); + /*NOTREACHED*/ + } + return(c); +} + +static unsigned long +NameToPixel(char *name, unsigned long pixel) +{ + XColor ecolor; + + if (!name || !*name) + return pixel; + if (!XParseColor(dpy,DefaultColormap(dpy,screen),name,&ecolor)) { + fprintf(stderr,"%s: unknown color \"%s\"\n",program_name,name); + exit(1); + /*NOTREACHED*/ + } + if (!XAllocColor(dpy, DefaultColormap(dpy, screen),&ecolor)) { + fprintf(stderr, "%s: unable to allocate color for \"%s\"\n", + program_name, name); + exit(1); + /*NOTREACHED*/ + } + if ((ecolor.pixel != BlackPixel(dpy, screen)) && + (ecolor.pixel != WhitePixel(dpy, screen)) && + (DefaultVisual(dpy, screen)->class & Dynamic)) + save_colors = 1; + return(ecolor.pixel); +} + +static Pixmap +ReadBitmapFile(char *filename, unsigned int *width, unsigned int *height, + int *x_hot, int *y_hot) +{ + Pixmap bitmap; + int status; + + status = XReadBitmapFile(dpy, root, filename, width, + height, &bitmap, x_hot, y_hot); + if (status == BitmapSuccess) + return(bitmap); + else if (status == BitmapOpenFailed) + fprintf(stderr, "%s: can't open file: %s\n", program_name, filename); + else if (status == BitmapFileInvalid) + fprintf(stderr, "%s: bad bitmap format file: %s\n", + program_name, filename); + else + fprintf(stderr, "%s: insufficient memory for bitmap: %s", + program_name, filename); + exit(1); + /*NOTREACHED*/ +}