tinywm-1.3.orig/0000755000175000017500000000000010213735122015345 5ustar iwamatsuiwamatsu00000000000000tinywm-1.3.orig/Makefile0000644000175000017500000000023210211730621016777 0ustar iwamatsuiwamatsu00000000000000PREFIX?=/usr/X11R6 CFLAGS?=-Os -pedantic -Wall all: $(CC) $(CFLAGS) -I$(PREFIX)/include -L$(PREFIX)/lib -lX11 -o tinywm tinywm.c clean: rm -f tinywm tinywm-1.3.orig/tinywm.c0000644000175000017500000000370210213733760017050 0ustar iwamatsuiwamatsu00000000000000/* TinyWM is written by Nick Welch , 2005. * * This software is in the public domain * and is provided AS IS, with NO WARRANTY. */ #include #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); } } tinywm-1.3.orig/tinywm.py0000644000175000017500000000300610213734016017246 0ustar iwamatsuiwamatsu00000000000000# TinyWM is written by Nick Welch , 2005. # # This software is in the public domain # and is provided AS IS, with NO WARRANTY. from Xlib.display import Display from Xlib import X, XK dpy = Display() root = dpy.screen().root root.grab_key(XK.string_to_keysym("F1"), X.Mod1Mask, 1, X.GrabModeAsync, X.GrabModeAsync) root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask, X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE) root.grab_button(3, X.Mod1Mask, 1, X.ButtonPressMask, X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE) while 1: ev = root.display.next_event() if ev.type == X.KeyPress and ev.child != X.NONE: ev.window.circulate(X.RaiseLowest) elif ev.type == X.ButtonPress and ev.child != X.NONE: ev.child.grab_pointer(1, X.PointerMotionMask|X.ButtonReleaseMask, X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE, X.CurrentTime) attr = ev.child.get_geometry() start = ev elif ev.type == X.MotionNotify: #while(XCheckTypedEvent(dpy, MotionNotify, &ev)); xdiff = ev.root_x - start.root_x ydiff = ev.root_y - start.root_y ev.window.configure( x = attr.x + (start.detail == 1 and xdiff or 0), y = attr.y + (start.detail == 1 and ydiff or 0), width = max(1, attr.width + (start.detail == 3 and xdiff or 0)), height = max(1, attr.height + (start.detail == 3 and ydiff or 0))) elif ev.type == X.ButtonRelease: dpy.ungrab_pointer(X.CurrentTime) tinywm-1.3.orig/README0000644000175000017500000000314110213736152016230 0ustar iwamatsuiwamatsu00000000000000TinyWM is written by Nick Welch , 2005. TinyWM is a ridiculously tiny window manager implemented in nearly as few lines of C as possible, without being obfuscated or entirely useless. It allows you to move, resize, focus (sloppy), and raise windows -- that's it! TinyWM's main purpose is to serve as a quick example of some window manager programming basics. Files: Makefile: highly advanced build system tinywm.c: the code annotated.c: same, but with tons of rambling comments about everything tinywm.py: a python version (requires CVS python-xlib due to a bug) Usage: Focus follows pointer. Alt+Button1, drag: interactive window move Alt+Button3, drag: interactive window resize Alt+F1: raise focused window Misc: A fella by the name of Trent Buck made a lisp version: http://twb.ath.cx/~twb/src/misc/tinywm.lisp I have started a wiki about window manager development, although I'm not sure the subject is popular enough for the wiki to keep from dying a horrible death. In any case, it is here: http://riters.com/WMDev/ Another very small window manager is failsafewm. Originally I started hacking on it, as there was quite a bit of stuff in it that I thought was unneeded, and I wound up rewriting it from scratch, with just the bare necessities -- that's TinyWM. http://freshmeat.net/projects/failsafewm/ Yet another small -- but in comparison, big -- window manager is aewm. It's a good example for learning about window management, and the fact that so many WMs have spawned from it is proof. http://www.red-bean.com/~decklin/aewm/ tinywm-1.3.orig/annotated.c0000644000175000017500000002056610213734042017477 0ustar iwamatsuiwamatsu00000000000000/* TinyWM is written by Nick Welch , 2005. * * This software is in the public domain * and is provided AS IS, with NO WARRANTY. */ /* much of tinywm's purpose is to serve as a very basic example of how to do X * stuff and/or understand window managers, so i wanted to put comments in the * code explaining things, but i really hate wading through code that is * over-commented -- and for that matter, tinywm is supposed to be as concise * as possible, so having lots of comments just wasn't really fitting for it. * i want tinywm.c to be something you can just look at and go "wow, that's * it? cool!" so what i did was just copy it over to annotated.c and comment * the hell out of it. ahh, but now i have to make every code change twice! * oh well. i could always use some sort of script to process the comments out * of this and write it to tinywm.c ... nah. */ /* most X stuff will be included with Xlib.h, but a few things require other * headers, like Xmd.h, keysym.h, etc. */ #include #define MAX(a, b) ((a) > (b) ? (a) : (b)) int main() { Display * dpy; Window root; XWindowAttributes attr; /* we use this to save the pointer's state at the beginning of the * move/resize. */ XButtonEvent start; XEvent ev; /* return failure status if we can't connect */ if(!(dpy = XOpenDisplay(0x0))) return 1; /* you'll usually be referencing the root window a lot. this is a somewhat * naive approach that will only work on the default screen. most people * only have one screen, but not everyone. if you run multi-head without * xinerama then you quite possibly have multiple screens. (i'm not sure * about vendor-specific implementations, like nvidia's) * * many, probably most window managers only handle one screen, so in * reality this isn't really *that* naive. * * if you wanted to get the root window of a specific screen you'd use * RootWindow(), but the user can also control which screen is our default: * if they set $DISPLAY to ":0.foo", then our default screen number is * whatever they specify "foo" as. */ root = DefaultRootWindow(dpy); /* you could also include keysym.h and use the XK_F1 constant instead of * the call to XStringToKeysym, but this method is more "dynamic." imagine * you have config files which specify key bindings. instead of parsing * the key names and having a huge table or whatever to map strings to XK_* * constants, you can just take the user-specified string and hand it off * to XStringToKeysym. XStringToKeysym will give you back the appropriate * keysym or tell you if it's an invalid key name. * * a keysym is basically a platform-independent numeric representation of a * key, like "F1", "a", "b", "L", "5", "Shift", etc. a keycode is a * numeric representation of a key on the keyboard sent by the keyboard * driver (or something along those lines -- i'm no hardware/driver expert) * to X. so we never want to hard-code keycodes, because they can and will * differ between systems. */ XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F1")), Mod1Mask, root, True, GrabModeAsync, GrabModeAsync); /* XGrabKey and XGrabButton are basically ways of saying "when this * combination of modifiers and key/button is pressed, send me the events." * so we can safely assume that we'll receive Alt+F1 events, Alt+Button1 * events, and Alt+Button3 events, but no others. You can either do * individual grabs like these for key/mouse combinations, or you can use * XSelectInput with KeyPressMask/ButtonPressMask/etc to catch all events * of those types and filter them as you receive them. */ XGrabButton(dpy, 1, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); XGrabButton(dpy, 3, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); for(;;) { /* this is the most basic way of looping through X events; you can be * more flexible by using XPending(), or ConnectionNumber() along with * select() (or poll() or whatever floats your boat). */ XNextEvent(dpy, &ev); /* this is our keybinding for raising windows. as i saw someone * mention on the ratpoison wiki, it is pretty stupid; however, i * wanted to fit some sort of keyboard binding in here somewhere, and * this was the best fit for it. * * i was a little confused about .window vs. .subwindow for a while, * but a little RTFMing took care of that. our passive grabs above * grabbed on the root window, so since we're only interested in events * for its child windows, we look at .subwindow. when subwindow == * None, that means that the window the event happened in was the same * window that was grabbed on -- in this case, the root window. */ if(ev.type == KeyPress && ev.xkey.subwindow != None) XRaiseWindow(dpy, ev.xkey.subwindow); else if(ev.type == ButtonPress && ev.xbutton.subwindow != None) { /* now we take command of the pointer, looking for motion and * button release events. */ XGrabPointer(dpy, ev.xbutton.subwindow, True, PointerMotionMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); /* we "remember" the position of the pointer at the beginning of * our move/resize, and the size/position of the window. that way, * when the pointer moves, we can compare it to our initial data * and move/resize accordingly. */ XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr); start = ev.xbutton; } /* the only way we'd receive a motion notify event is if we already did * a pointer grab and we're in move/resize mode, so we assume that. */ else if(ev.type == MotionNotify) { int xdiff, ydiff; /* here we "compress" motion notify events. if there are 10 of * them waiting, it makes no sense to look at any of them but the * most recent. in some cases -- if the window is really big or * things are just acting slowly in general -- failing to do this * can result in a lot of "drag lag." * * for window managers with things like desktop switching, it can * also be useful to compress EnterNotify events, so that you don't * get "focus flicker" as windows shuffle around underneath the * pointer. */ while(XCheckTypedEvent(dpy, MotionNotify, &ev)); /* now we use the stuff we saved at the beginning of the * move/resize and compare it to the pointer's current position to * determine what the window's new size or position should be. * * if the initial button press was button 1, then we're moving. * otherwise it was 3 and we're resizing. * * we also make sure not to go negative with the window's * dimensions, resulting in "wrapping" which will make our window * something ridiculous like 65000 pixels wide (often accompanied * by lots of swapping and slowdown). * * even worse is if we get "lucky" and hit a width or height of * exactly zero, triggering an X error. so we specify a minimum * width/height of 1 pixel. */ 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))); } /* like motion notifies, the only way we'll receive a button release is * during a move/resize, due to our pointer grab. this ends the * move/resize. */ else if(ev.type == ButtonRelease) XUngrabPointer(dpy, CurrentTime); } } tinywm-1.3.orig/COPYING0000644000175000017500000000021210213733703016376 0ustar iwamatsuiwamatsu00000000000000TinyWM is written by Nick Welch , 2005. This software is in the public domain and is provided AS IS, with NO WARRANTY.