all repos — ryudo @ 794fc2bc71269ed8c033f565d9d7ae645c2ad3a2

the floatiling window manager that flows; fork of rio from plan9port

first commit
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAl3lVoQACgkQO3+8IhRO
Y5iBfg/8C2uS/pEeoRTyXHEJrr0ZM8a3hpoTfsIbojGO1WKlN8fNTcsLX/lAZlVy
m47GfLTR5fW3lFrUxrcTWctBlvUumaEJUyfwTGgiKiNE25p8VA4zfJxgpI7zh3XV
dMYPxlw4/yZH89ZE1KcNfKIjGtiksnviweotBIhWy0rxDuqUM9EhMH3p4sSeet1i
+mvilULnKncQ/mW+y/w3fk+5mr1B644jfOD0j0GKjWCYgtlSgHipv4idHzMWuqAI
Wi/qQ5o/hdcb1cJW6AUzNDVG+BpBoOagYaRpfUJ2BSreqN0Jq7AGwsNBha6/8md5
+jAMrSPKWAKJEXFj6NvxoQbRePFqi3q/qSTZ4m9EVBFfVdJoKJPQFWiXcv9NcKww
8G+JhLNWRWy3crhBSLkNYGg2gKr0JrxNbGymUYT1cf+Gh217Qap3DiUua0dN7Y0j
EPstgLGTZqFEc+DWFxRJueN2alR864+N0lc4ppQNT6LZJE2izNWjvhgSw6Jz9YHT
0Hyrmy2JeFxuxoM6Aokx+Njah2zNjZxePflrriGhc5RatrD5DNAbeahBRsRW7qqt
Ol4Uqkq//uYq4BQjwHdNoTfy4IUwXVh4FDhAVI2jRe5pEJu4uFTY7QbduustArNp
UVLtWO3RC0bsH8aklROuK/BNDfsoQuIgsrrfhQhMedsu2WKWG1c=
=ew3F
-----END PGP SIGNATURE-----
commit

794fc2bc71269ed8c033f565d9d7ae645c2ad3a2

A .gitignore

@@ -0,0 +1,2 @@

+*.o +ryudo
A README.md

@@ -0,0 +1,258 @@

+# [[ RYUDO ]] +## the minimalist floatiling window manager that flows + -- Derek Stevens <drkste@zoho.com> 2019 -- + +### About +Ryudo is a fork of Russ Cox's Rio, itself a fork of David Hogan's 9wm. +The primary additions I've made are: + +- URxvt is detected as a proper terminal program for sweeping out new windows +- URxvt is the default terminal emulator (still tries 9term and then xterm if no dice) +- Customizable colors, borders, fonts, and keybinds in config.h +- Default keybindings: + + New Terminal: Super+Slash + + Destroy: Super+D + + Iconify: Super+I + + Maximize: Super+M + + moVe: Super+V + + Reshape: Super+R + + Snap Left: Super+H + + Snap Right: Super+L + + Snap Top: Super+K + + Snap Bottom: Super+J + + Snap Top-Left: Super+Q + + Snap Bottom-Left: Super+W + + Snap Bottom-Right: Super+O + + Snap Top-Right: Super+P + + Snap Floating-Center: Super+C + + Virtual Desk++: Super+Right + + Virtual Desk--: Super+Left + +The name "Ryudo" is a nod to "Rio" and a Japanese word for "flow." +Using Ryudo should feel very natural -- you can do things with keyboard or +mouse depending on the situation. Terminal launching can be done with mouse +using the popup menu, or using the keyboar, which will spawn a terminal +window centered taking up 9/25 of the screen (3/5 width, 3/5 height). + +### Dependencies, Building, Installation +Being forked from Rio, Ryudo requires **plan9port**, **Xlib**, and **Xt**. +Make it with **mk ryudo** and then copy the resulting executable **ryudo** to +somewhere in your **PATH** + +If you try to install it with **mk install** it will probably install +to **$PLAN9/bin/** under the name **rio**. This is less than ideal but I'm +not a master of mk, so my protocol is to use a mk target **ryudo** which +builds the program as **o.rio**, then calls **ryudomagic.sh** to rename +the program. + +If you have trouble building, you might need to edit the **mkfile** at line 2 +to point to the proper location of your plan9port's **mkwsysrules.sh**. + +### Bugs and Caveats +Of the bugs and caveats not already mentioned in Rio's readme: +- Rendering of windows with RGBA surfaces is bound to RGB space (xshove and transset can be leveraged to get transparent terminals if you want it) +- Since maximization doesn't use the EWM Hint for maximization, programs like Firefox will remember their window size as the maximized size and probably start offset so they aren't completely onscreen. There is probably a rule we can put in newwindow() to mitigate this, but it's not super important. +- Probably more! + +### Legacy +This is David Hogan's 9wm updated to behave more like +Plan 9's rio. Since I cannot get approval for the changes +and I'd prefer not to resort to patches, I have renamed it "rio". + +Current incompatibilities that would be nice to fix: + +- The command-line options should be made more like Plan 9. + +- Should work out a protocol between 9term and rio so that: + * 9term can tell rio to blue its border during hold mode + +- Should change window focus on b2/b3 clicks and then + pass along the click event to the now-focused window. + +- Should change 9term to redirect b3 clicks to rio so that rio + can put up the usual b3 menu. + +Axel Belinfante contributed the code to handle border grabbing +for resize and various other improvements. + +The original README is below. + +- russ cox +rsc@swtch.com +30 march 2004 + + + 9wm Version 1.2 + Copyright 1994-1996 David Hogan. + +What is 9wm? +============ + +9wm is an X window manager which attempts to emulate the Plan 9 window +manager 8-1/2 as far as possible within the constraints imposed by X. +It provides a simple yet comfortable user interface, without garish +decorations or title-bars. Or icons. And it's click-to-type. This +will not appeal to everybody, but if you're not put off yet then read +on. (And don't knock it until you've tried it.) + +One major difference between 9wm and 8-1/2 is that the latter provides +windows of text with a typescript interface, and doesn't need to run a +separate program to emulate a terminal. 9wm, as an X window manager, +does require a separate program. For better 8-1/2 emulation, you should +obtain Matthew Farrow's "9term" program (ftp://ftp.cs.su.oz.au/matty/unicode), +version 1.6 or later (earlier versions don't cooperate with 9wm in +implementing "hold mode"). Of course, you can run xterm under 9wm as well. + +What is 9wm not? +================ + +9wm is not a virtual window manager. It is not customisable to any +great extent. It is not large and unwieldy, and doesn't use the X +toolkit. Requests to make it any of these things will be silently +ignored (or flamed if I have had a bad day :-) If you want tvtwm +or mwm, you know where to get them... + +Where do I get it? +================== + +The latest version of 9wm is held at ftp://ftp.cs.su.oz.au/dhog/9wm + +Author +====== + +9wm was written by David Hogan (dhog@cs.su.oz.au), a postgraduate +student at the Basser Department of Computer Science, University +of Sydney (http://www.cs.su.oz.au/~dhog/). + +Licence +======= + + 9wm is free software, and is Copyright (c) 1994-1996 by David Hogan. + Permission is granted to all sentient beings to use this software, + to make copies of it, and to distribute those copies, provided + that: + + (1) the copyright and licence notices are left intact + (2) the recipients are aware that it is free software + (3) any unapproved changes in functionality are either + (i) only distributed as patches + or (ii) distributed as a new program which is not called 9wm + and whose documentation gives credit where it is due + (4) the author is not held responsible for any defects + or shortcomings in the software, or damages caused by it. + + There is no warranty for this software. Have a nice day. + +How do I compile/install it? +============================ + +Assuming your system is correctly configured, you should only need to +run xmkmf to generate the Makefile, and then run make or make install. +make install.man should copy the manpage (9wm.man) to the appropriate +directory. + +If the make fails, complaining that the function _XShapeQueryExtension +does not exist, try removing the "-DSHAPE" from the Imakefile, and +run xmkmf and make again. + +If you don't have imake, or it is misconfigured, or you would prefer +not to use it, try copying the file "Makefile.no-imake" to "Makefile", +then edit the definitions in this Makefile to suit your system. This +may require defining suitable compilation flags for your system +(normally imake does this for you). For instance, on AIX you must +include "-DBSD_INCLUDES" in CFLAGS. + +How do I use it? +================ + +See the manual page for details. You should probably read the +man page for 9term as well. + +What if I find a bug? +===================== + +Please mail all bug reports to 9wm-bugs@plan9.cs.su.oz.au, so +that I can incorporate fixes into the next release. If you can +tell me how to fix it, all the better. + +Known Problems/Bugs +=================== + +9wm tries hard to emulate 8-1/2, but isn't 100% compatible. If +you are an experienced 8-1/2 user, please be patient with it. + +One intentional difference between 9wm and 8-1/2 is in the behaviour +of the menu when the last hidden item is unhidden. Under 8-1/2, when +the menu is next used, it pops up with "New" selected. Under 9wm, +the (new) last menu item will be selected. This is a feature. It +may be confusing if you frequently switch between 9wm and 8-1/2. +If you don't like this feature, email me for the one line fix. + +There have been some problems encountered when resizing 9term on +some platforms. This turns out to be a problem in 9term (actually +in libXg, to be precise). Newer versions of 9term should be +immune to this, see matty@cs.su.oz.au if your 9term needs fixing. + +Some client programs do weird things. One of these is Frame Maker. +It appears that if it has a modal dialog on the screen, then if any +of its windows are current, all keypresses are redirected to the +modal dialog. This is not 9wm's fault -- Frame Maker is doing this. + +Programs like Netscape Navigator like to put riddiculously long +icon name properties on their windows, of the form "Netscape: blah blah". +There is no way that I know of to stop netscape from doing this. For this +reason, 9wm truncates labels at the first colon it finds. This keeps the +button 3 menu from becoming excessively wide. Note that with same +applications, you can use an iconName resource to set the label; this +works well for "xman", whose default icon name of "Manual Browser" +is a tad too long. + +See Also +======== + +http://www.cs.su.oz.au/~dhog/ + The 9wm Home Page + +ftp://ftp.cs.su.oz.au/matty/unicode/ + for source to 9term (get README first) + +ftp://plan9.att.com/plan9/unixsrc/sam/ + for source && info on Rob Pike's editor "sam" + +ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/shell/rc + for information on a publically available implementation + of the Plan 9 shell "rc" for unix (or look in comp.unix.shell). + +ftp://viz.tamu.edu/pub/rc + for source to the abovementioned implementation of rc. + +http://plan9.att.com/plan9/ +http://plan9.att.com/magic/man2html/1/8%c2%bd + for information on Plan 9 (including the 8-1/2 manual entry) + +Acknowledgements +================ + +Thanks to Rob Pike for writing the original 8-1/2 program (and +before that, mux) which inspired the writing of 9wm. + +Thanks to John Mackin, whose gwm "wool code" for emulating mux +was also an inspiration: I used it (and hacked it) until I got +too frustrated with gwm's large memory requirements and lack of +speed (sorry Colas!), and decided to write a dedicated program. + +Thanks to Matthew Farrow for writing 9term. + +A big thanks to Dave Edmondson for adding support for +multi-screen displays. + +The following people helped beta test 9wm: + + John Mackin + Noel Hunt + Fred Curtis + James Matthew Farrow + Danny Yee + Arnold Robbins + Byron Rakitzis + micro@cooper.edu
A client.c

@@ -0,0 +1,285 @@

+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "dat.h" +#include "fns.h" + +Client *clients; +Client *current; + +void +setactive(Client *c, int on) +{ +/* dbg("setactive client %x %d", c->window, c->on); */ + + if(c->parent == c->screen->root) + return; + + if(on){ + XUngrabButton(dpy, AnyButton, AnyModifier, c->parent); + XSetInputFocus(dpy, c->window, RevertToPointerRoot, timestamp()); + if(c->proto & Ptakefocus) + sendcmessage(c->window, wm_protocols, wm_take_focus, 0, 1); + cmapfocus(c); + }else{ + if(c->proto & Plosefocus) + sendcmessage(c->window, wm_protocols, wm_lose_focus, 0, 1); + XGrabButton(dpy, AnyButton, AnyModifier, c->parent, False, + ButtonMask, GrabModeAsync, GrabModeSync, None, None); + } + draw_border(c, on); +} + +void +draw_border(Client *c, int active) +{ + unsigned long pixel; + + if(active){ + if(c->hold) + pixel = c->screen->activeholdborder; + else + pixel = c->screen->activeborder; + }else{ + if(c->hold) + pixel = c->screen->inactiveholdborder; + else + pixel = c->screen->inactiveborder; + } + + if(debug) fprintf(stderr, "draw_border %p pixel %ld active %d hold %d\n", (void*)c, pixel, active, c->hold); + XSetWindowBackground(dpy, c->parent, pixel); + XClearWindow(dpy, c->parent); +} + +void +active(Client *c) +{ + Client *cc; + + if(c == 0){ + fprintf(stderr, "ryudo: active(c==0)\n"); + return; + } + if(c == current) + return; + if(current){ + setactive(current, 0); + if(current->screen != c->screen) + cmapnofocus(current->screen); + } + setactive(c, 1); + for(cc = clients; cc; cc = cc->next) + if(cc->revert == c) + cc->revert = c->revert; + c->revert = current; + while(c->revert && !normal(c->revert)) + c->revert = c->revert->revert; + current = c; +#ifdef DEBUG + if(debug) + dump_revert(); +#endif +} + +void +nofocus(void) +{ + static Window w = 0; + int mask; + XSetWindowAttributes attr; + Client *c; + + if(current){ + setactive(current, 0); + for(c = current->revert; c; c = c->revert) + if(normal(c)){ + active(c); + return; + } + cmapnofocus(current->screen); + /* if no candidates to revert to, fall through */ + } + current = 0; + if(w == 0){ + mask = CWOverrideRedirect/*|CWColormap*/; + attr.override_redirect = 1; + /* attr.colormap = screens[0].def_cmap;*/ + w = XCreateWindow(dpy, screens[0].root, 0, 0, 1, 1, 0, + 0 /*screens[0].depth*/, InputOnly, screens[0].vis, mask, &attr); + XMapWindow(dpy, w); + } + XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp()); +} + +void +top(Client *c) +{ + Client **l, *cc; + + l = &clients; + for(cc = *l; cc; cc = *l){ + if(cc == c){ + *l = c->next; + c->next = clients; + clients = c; + return; + } + l = &cc->next; + } + fprintf(stderr, "rio: %p not on client list in top()\n", (void*)c); +} + +Client * +getclient(Window w, int create) +{ + Client *c; + + if(w == 0 || getscreen(w)) + return 0; + + for(c = clients; c; c = c->next) + if(c->window == w || c->parent == w) + return c; + + if(!create) + return 0; + + c = (Client *)malloc(sizeof(Client)); + memset(c, 0, sizeof(Client)); + c->window = w; + /* c->parent will be set by the caller */ + c->parent = None; + c->reparenting = 0; + c->state = WithdrawnState; + c->init = 0; + c->cmap = None; + c->label = c->class = 0; + c->revert = 0; + c->is9term = 0; + c->hold = 0; + c->ncmapwins = 0; + c->cmapwins = 0; + c->wmcmaps = 0; + c->next = clients; + c->virt = virt; + clients = c; + return c; +} + +void +rmclient(Client *c) +{ + Client *cc; + + for(cc = current; cc && cc->revert; cc = cc->revert) + if(cc->revert == c) + cc->revert = cc->revert->revert; + + if(c == clients) + clients = c->next; + for(cc = clients; cc && cc->next; cc = cc->next) + if(cc->next == c) + cc->next = cc->next->next; + + if(hidden(c)) + unhidec(c, 0); + + if(c->parent != c->screen->root) + XDestroyWindow(dpy, c->parent); + + c->parent = c->window = None; /* paranoia */ + if(current == c){ + current = c->revert; + if(current == 0) + nofocus(); + else { + if(current->screen != c->screen) + cmapnofocus(c->screen); + setactive(current, 1); + } + } + if(c->ncmapwins != 0){ + XFree((char *)c->cmapwins); + free((char *)c->wmcmaps); + } + if(c->iconname != 0) + XFree((char*) c->iconname); + if(c->name != 0) + XFree((char*) c->name); + if(c->instance != 0) + XFree((char*) c->instance); + if(c->class != 0) + XFree((char*) c->class); + memset(c, 0, sizeof(Client)); /* paranoia */ + free(c); +} + +#ifdef DEBUG +void +dump_revert(void) +{ + Client *c; + int i; + + i = 0; + for(c = current; c; c = c->revert){ + fprintf(stderr, "%s(%x:%d)", c->label ? c->label : "?", (int)c->window, c->state); + if(i++ > 100) + break; + if(c->revert) + fprintf(stderr, " -> "); + } + if(current == 0) + fprintf(stderr, "empty"); + fprintf(stderr, "\n"); +} + +void +dump_clients(void) +{ + Client *c; + + for(c = clients; c; c = c->next) + fprintf(stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", (int)c->window, (int)c->parent, c->x, c->y); +} +#endif + +void +shuffle(int up) +{ + Client **l, *c; + + if(clients == 0 || clients->next == 0) + return; + if(!up){ + c = 0; + /*for(c=clients; c->next; c=c->next) */ + /* ; */ + for(l=&clients; (*l)->next; l=&(*l)->next) + if ((*l)->state == 1) + c = *l; + if (c == 0) + return; + XMapRaised(dpy, c->parent); + top(c); + active(c); + }else{ + c = clients; + for(l=&clients; *l; l=&(*l)->next) + ; + clients = c->next; + *l = c; + c->next = 0; + XLowerWindow(dpy, c->window); + } +/* XMapRaised(dpy, clients->parent); */ +/* top(clients); */ +/* active(clients); */ +} +
A color.c

@@ -0,0 +1,45 @@

+/* Copyright (c) 2004 Russ Cox, see README for licence details */ +#include <stdio.h> +#include <signal.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "dat.h" +#include "fns.h" + +unsigned long +colorpixel(Display *dpy, ScreenInfo *s, int depth, unsigned long rgb, unsigned long def) +{ + int r, g, b; + + r = rgb>>16; + g = (rgb>>8)&0xFF; + b = rgb&0xFF; + + switch(depth){ + case 1: + case 2: + case 4: + case 8: + default: + /* not going to waste color map entries */ + return def; + case 15: + r >>= 3; + g >>= 3; + b >>= 3; + return (r<<10) | (g<<5) | b; + case 16: + r >>= 3; + g >>= 2; + b >>= 3; + return (r<<11) | (g<<5) | b; + case 24: + case 32: + /* try to find byte order */ + if(s->vis->red_mask & 0xff) + return (r) | (g<<8) | (b<<16); /* OK on Sun */ + return rgb; + } +} +
A config.h

@@ -0,0 +1,39 @@

+#define SHOLDCOL 0xC8C8C8 +#define HOLDCOL 0x444444 +#define SBORDERCOL 0x1F9B92 +#define BORDERCOL 0x000000 +#define GHOSTCOL 0x797979 +#define BORDER 4 + +#define MENUBORDER 0 +#define MBORDERCOL 0x000000 +#define MENUFGCOL 0x797979 +#define MENUBGCOL 0x000000 +#define SMENUFGCOL 0x000000 +#define SMENUBGCOL 0x797979 + +#define SHORTCUTMOD Mod4Mask +#define MODBITS (1<<6) + +#define MAX_KEY XK_m +#define ICON_KEY XK_i +#define MOVE_KEY XK_v +#define RESIZE_KEY XK_r +#define DESTROY_KEY XK_d + +#define SNAPLEFT_KEY XK_h +#define SNAPRIGHT_KEY XK_l +#define SNAPTOP_KEY XK_k +#define SNAPBOTTOM_KEY XK_j + +#define SNAPTOPLEFT_KEY XK_q +#define SNAPBOTTOMLEFT_KEY XK_w +#define SNAPBOTTOMRIGHT_KEY XK_o +#define SNAPTOPRIGHT_KEY XK_p + +#define SNAPCENTER_KEY XK_c + +#define NEXTVIRT_KEY XK_Right +#define PREVVIRT_KEY XK_Left + +#define LAUNCH_KEY XK_slash
A cursor.c

@@ -0,0 +1,381 @@

+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "dat.h" +#include "fns.h" + +typedef struct { + int width; + int hot[2]; + unsigned char mask[64]; + unsigned char fore[64]; +} Cursordata; + +Cursordata bigarrow = { + 16, + {0, 0}, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x1F, 0xFF, 0x3F, + 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, + 0xCF, 0x1F, 0x8F, 0x0F, 0x07, 0x07, 0x03, 0x02, + }, + { 0x00, 0x00, 0xFE, 0x7F, 0xFE, 0x3F, 0xFE, 0x0F, + 0xFE, 0x07, 0xFE, 0x07, 0xFE, 0x0F, 0xFE, 0x1F, + 0xFE, 0x3F, 0xFE, 0x7F, 0xFE, 0x3F, 0xCE, 0x1F, + 0x86, 0x0F, 0x06, 0x07, 0x02, 0x02, 0x00, 0x00, + } +}; + +Cursordata sweep0data = { + 16, + {7, 7}, + {0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, + 0xC0, 0x03, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0xC0, 0x03, + 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03}, + {0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xFE, 0x7F, + 0xFE, 0x7F, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00} +}; + +Cursordata boxcursdata = { + 16, + {7, 7}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, + 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0x00, 0x00, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, + 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, + 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, + 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0x00, 0x00} +}; + +Cursordata sightdata = { + 16, + {7, 7}, + {0xF8, 0x1F, 0xFC, 0x3F, 0xFE, 0x7F, 0xDF, 0xFB, + 0xCF, 0xF3, 0xC7, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xE3, 0xCF, 0xF3, + 0xDF, 0x7B, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F,}, + {0x00, 0x00, 0xF0, 0x0F, 0x8C, 0x31, 0x84, 0x21, + 0x82, 0x41, 0x82, 0x41, 0x82, 0x41, 0xFE, 0x7F, + 0xFE, 0x7F, 0x82, 0x41, 0x82, 0x41, 0x82, 0x41, + 0x84, 0x21, 0x8C, 0x31, 0xF0, 0x0F, 0x00, 0x00,} +}; + +Cursordata arrowdata = { + 16, + {1, 1}, + {0xFF, 0x07, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0x07, + 0xE7, 0x0F, 0xC7, 0x1F, 0x83, 0x3F, 0x00, 0x7F, + 0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10,}, + {0x00, 0x00, 0xFE, 0x03, 0xFE, 0x00, 0x3E, 0x00, + 0x7E, 0x00, 0xFE, 0x00, 0xF6, 0x01, 0xE6, 0x03, + 0xC2, 0x07, 0x82, 0x0F, 0x00, 0x1F, 0x00, 0x3E, + 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00,} +}; + +Cursordata whitearrow = { + 16, + {0, 0}, + {0xFF, 0x07, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0x07, + 0xE7, 0x0F, 0xC7, 0x1F, 0x83, 0x3F, 0x00, 0x7F, + 0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10,}, + {0xFF, 0x07, 0xFF, 0x07, 0x83, 0x03, 0xC3, 0x00, + 0xC3, 0x00, 0x83, 0x01, 0x1B, 0x03, 0x3F, 0x06, + 0x67, 0x0C, 0xC7, 0x18, 0x83, 0x31, 0x00, 0x63, + 0x00, 0xC6, 0x00, 0x6C, 0x00, 0x38, 0x00, 0x10,} +}; + +Cursordata blittarget = { + 18, + {8, 8}, + {0xe0, 0x1f, 0x00, 0xf0, 0x3f, 0x00, 0xf8, 0x7f, 0x00, + 0xfc, 0xff, 0x00, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x03, + 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, + 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, + 0xff, 0xff, 0x03, 0xfe, 0xff, 0x01, 0xfc, 0xff, 0x00, + 0xf8, 0x7f, 0x00, 0xf0, 0x3f, 0x00, 0xe0, 0x1f, 0x00}, + {0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3f, 0x00, + 0x38, 0x73, 0x00, 0x8c, 0xc7, 0x00, 0xec, 0xdf, 0x00, + 0x66, 0x9b, 0x01, 0x36, 0xb3, 0x01, 0xfe, 0xff, 0x01, + 0xfe, 0xff, 0x01, 0x36, 0xb3, 0x01, 0x66, 0x9b, 0x01, + 0xec, 0xdf, 0x00, 0x8c, 0xc7, 0x00, 0x38, 0x73, 0x00, + 0xf0, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00} +}; + +Cursordata blitarrow = { + 18, + {1, 1}, + {0xff, 0x0f, 0x00, 0xff, 0x07, 0x00, 0xff, 0x03, 0x00, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x01, 0x00, + 0xff, 0x03, 0x00, 0xff, 0x07, 0x00, 0xe7, 0x0f, 0x00, + 0xc7, 0x1f, 0x00, 0x87, 0x3f, 0x00, 0x03, 0x7f, 0x00, + 0x01, 0xfe, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf8, 0x03, + 0x00, 0xf0, 0x01, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x00}, + {0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0xfe, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0xf6, 0x01, 0x00, 0xe6, 0x03, 0x00, 0xc2, 0x07, 0x00, + 0x82, 0x0f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3e, 0x00, + 0x00, 0x7c, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf0, 0x01, + 0x00, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00} +}; + +Cursordata blitsweep = { + 18, + {8, 8}, + {0xc4, 0xff, 0x03, 0xce, 0xff, 0x03, 0xdf, 0xff, 0x03, + 0x3e, 0x80, 0x03, 0x7c, 0x83, 0x03, 0xf8, 0x83, 0x03, + 0xf7, 0x83, 0x03, 0xe7, 0x83, 0x03, 0xf7, 0x83, 0x03, + 0xf7, 0x83, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03, + 0x07, 0x80, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03, + 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03}, + {0x00, 0x00, 0x00, 0x84, 0xff, 0x01, 0x0e, 0x00, 0x01, + 0x1c, 0x00, 0x01, 0x38, 0x00, 0x01, 0x70, 0x01, 0x01, + 0xe0, 0x01, 0x01, 0xc2, 0x01, 0x01, 0xe2, 0x01, 0x01, + 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, + 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, + 0x02, 0x00, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00} +}; + +/* + * Grey tile pattern for root background + */ + +#define grey_width 4 +#define grey_height 2 +static char grey_bits[] = { + 0x01, 0x04 +}; + +static XColor bl, wh; + +Cursor +getcursor(c, s) +Cursordata *c; +ScreenInfo *s; +{ + Pixmap f, m; + + f = XCreatePixmapFromBitmapData(dpy, s->root, (char *)c->fore, + c->width, c->width, 1, 0, 1); + m = XCreatePixmapFromBitmapData(dpy, s->root, (char *)c->mask, + c->width, c->width, 1, 0, 1); + return XCreatePixmapCursor(dpy, f, m, &bl, &wh, + c->hot[0], c->hot[1]); +} + +void +initcurs(s) +ScreenInfo *s; +{ + XColor dummy; + + XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), + "black", &bl, &dummy); + XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), + "white", &wh, &dummy); + + if(nostalgia){ + s->arrow = getcursor(&blitarrow, s); + s->target = getcursor(&blittarget, s); + s->sweep0 = getcursor(&blitsweep, s); + s->boxcurs = getcursor(&blitsweep, s); + } + else { + s->arrow = getcursor(&bigarrow, s); + s->target = getcursor(&sightdata, s); + s->sweep0 = getcursor(&sweep0data, s); + s->boxcurs = getcursor(&boxcursdata, s); + } + + s->root_pixmap = XCreatePixmapFromBitmapData(dpy, + s->root, grey_bits, grey_width, grey_height, + s->black, s->white, s->depth); + + s->bordcurs[BorderN] = XCreateFontCursor(dpy, 138); + s->bordcurs[BorderNNE] = XCreateFontCursor(dpy, 136); + s->bordcurs[BorderENE] = s->bordcurs[BorderNNE] ; + s->bordcurs[BorderE] = XCreateFontCursor(dpy, 96); + s->bordcurs[BorderESE] = XCreateFontCursor(dpy, 14); + s->bordcurs[BorderSSE] = s->bordcurs[BorderESE]; + s->bordcurs[BorderS] = XCreateFontCursor(dpy, 16); + s->bordcurs[BorderSSW] = XCreateFontCursor(dpy, 12); + s->bordcurs[BorderWSW] = s->bordcurs[BorderSSW]; + s->bordcurs[BorderW] = XCreateFontCursor(dpy, 70); + s->bordcurs[BorderWNW] = XCreateFontCursor(dpy, 134); + s->bordcurs[BorderNNW] = s->bordcurs[BorderWNW]; +} + + +/* RIO + +Cursor crosscursor = { + {-7, -7}, + {0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, + 0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, }, + {0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, + 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, } +}; + +Cursor boxcursor = { + {-7, -7}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, + 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, + {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, + 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, + 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, + 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, } +}; + +Cursor sightcursor = { + {-7, -7}, + {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF, + 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF, + 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, }, + {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84, + 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE, + 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, + 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00, } +}; + +Cursor whitearrow = { + {0, 0}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, + 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, + 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, + 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }, + {0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C, + 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C, + 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C, + 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, } +}; + +Cursor query = { + {-7,-7}, + {0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8, + 0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0, + 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, }, + {0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c, + 0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0, + 0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80, + 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, } +}; + +Cursor tl = { + {-4, -4}, + {0xfe, 0x00, 0x82, 0x00, 0x8c, 0x00, 0x87, 0xff, + 0xa0, 0x01, 0xb0, 0x01, 0xd0, 0x01, 0x11, 0xff, + 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, + 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x1f, 0x00, }, + {0x00, 0x00, 0x7c, 0x00, 0x70, 0x00, 0x78, 0x00, + 0x5f, 0xfe, 0x4f, 0xfe, 0x0f, 0xfe, 0x0e, 0x00, + 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, + 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, 0x00, } +}; + +Cursor t = { + {-7, -8}, + {0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x06, 0xc0, + 0x1c, 0x70, 0x10, 0x10, 0x0c, 0x60, 0xfc, 0x7f, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80, 0x03, 0x80, + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } +}; + +Cursor tr = { + {-11, -4}, + {0x00, 0x7f, 0x00, 0x41, 0x00, 0x31, 0xff, 0xe1, + 0x80, 0x05, 0x80, 0x0d, 0x80, 0x0b, 0xff, 0x88, + 0x00, 0x88, 0x0, 0x88, 0x00, 0x88, 0x00, 0x88, + 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xf8, }, + {0x00, 0x00, 0x00, 0x3e, 0x00, 0x0e, 0x00, 0x1e, + 0x7f, 0xfa, 0x7f, 0xf2, 0x7f, 0xf0, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, } +}; + +Cursor r = { + {-8, -7}, + {0x07, 0xc0, 0x04, 0x40, 0x04, 0x40, 0x04, 0x58, + 0x04, 0x68, 0x04, 0x6c, 0x04, 0x06, 0x04, 0x02, + 0x04, 0x06, 0x04, 0x6c, 0x04, 0x68, 0x04, 0x58, + 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x07, 0xc0, }, + {0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, + 0x03, 0x90, 0x03, 0x90, 0x03, 0xf8, 0x03, 0xfc, + 0x03, 0xf8, 0x03, 0x90, 0x03, 0x90, 0x03, 0x80, + 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, } +}; + +Cursor br = { + {-11, -11}, + {0x00, 0xf8, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, + 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, + 0xff, 0x88, 0x80, 0x0b, 0x80, 0x0d, 0x80, 0x05, + 0xff, 0xe1, 0x00, 0x31, 0x00, 0x41, 0x00, 0x7f, }, + {0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, + 0x0, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, + 0x00, 0x70, 0x7f, 0xf0, 0x7f, 0xf2, 0x7f, 0xfa, + 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x3e, 0x00, 0x00, } +}; + +Cursor b = { + {-7, -7}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0xfc, 0x7f, 0x0c, 0x60, 0x10, 0x10, 0x1c, 0x70, + 0x06, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, }, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, + 0x03, 0x80, 0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } +}; + +Cursor bl = { + {-4, -11}, + {0x1f, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, + 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, + 0x11, 0xff, 0xd0, 0x01, 0xb0, 0x01, 0xa0, 0x01, + 0x87, 0xff, 0x8c, 0x00, 0x82, 0x00, 0xfe, 0x00, }, + {0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, + 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, + 0x0e, 0x00, 0x0f, 0xfe, 0x4f, 0xfe, 0x5f, 0xfe, + 0x78, 0x00, 0x70, 0x00, 0x7c, 0x00, 0x00, 0x0, } +}; + +Cursor l = { + {-7, -7}, + {0x03, 0xe0, 0x02, 0x20, 0x02, 0x20, 0x1a, 0x20, + 0x16, 0x20, 0x36, 0x20, 0x60, 0x20, 0x40, 0x20, + 0x60, 0x20, 0x36, 0x20, 0x16, 0x20, 0x1a, 0x20, + 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x03, 0xe0, }, + {0x00, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, + 0x09, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x3f, 0xc0, + 0x1f, 0xc0, 0x09, 0xc0, 0x09, 0xc0, 0x01, 0xc0, + 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, } +}; + +Cursor *corners[9] = { + &tl, &t, &tr, + &l, nil, &r, + &bl, &b, &br +}; + +*/
A dat.h

@@ -0,0 +1,191 @@

+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ + +#ifndef BORDER +#define BORDER _border +#endif +#define CORNER _corner +#define INSET _inset +#define MAXHIDDEN 128 +#define B3FIXED 5 +#define NUMVIRTUALS 12 + +#define AllButtonMask (Button1Mask|Button2Mask|Button3Mask \ + |Button4Mask|Button5Mask) +#define ButtonMask (ButtonPressMask|ButtonReleaseMask) +#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask) +#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask) + +#ifdef Plan9 +#define DEFSHELL "/bin/rc" +#else +#define DEFSHELL "/bin/sh" +#endif + +typedef struct Client Client; +typedef struct Menu Menu; +typedef struct ScreenInfo ScreenInfo; + +struct Client { + Window window; + Window parent; + Window trans; + Client *next; + Client *revert; + + int x; + int y; + int dx; + int dy; + int border; + + XSizeHints size; + int min_dx; + int min_dy; + + int state; + int init; + int reparenting; + int is9term; + int hold; + int proto; + int virt; + + char *label; + char *instance; + char *class; + char *name; + char *iconname; + + Colormap cmap; + int ncmapwins; + Window *cmapwins; + Colormap *wmcmaps; + ScreenInfo *screen; +}; + +#define hidden(c) ((c)->state == IconicState) +#define withdrawn(c) ((c)->state == WithdrawnState) +#define normal(c) ((c)->state == NormalState) + +/* c->proto */ +#define Pdelete 1 +#define Ptakefocus 2 +#define Plosefocus 4 + +struct Menu { + char **item; + char *(*gen)(); + int lasthit; +}; + +enum BorderOrient { + BorderUnknown = 0, /* we depend on this!*/ + BorderN, + BorderNNE, + BorderENE, + BorderE, + BorderESE, + BorderSSE, + BorderS, + BorderSSW, + BorderWSW, + BorderW, + BorderWNW, + BorderNNW, + NBorder +}; +typedef enum BorderOrient BorderOrient; + +struct ScreenInfo { + int num; + int depth; + Visual *vis; + int width; + int height; + Window root; + Window menuwin; + Window sweepwin; + Colormap def_cmap; + GC gc; + GC gccopy; + GC gcred; + GC gcsweep; + GC gcmenubg; + GC gcmenubgs; + GC gcmenufg; + GC gcmenufgs; + unsigned long black; + unsigned long white; + unsigned long activeholdborder; + unsigned long inactiveholdborder; + unsigned long activeborder; + unsigned long inactiveborder; + unsigned long red; + Pixmap bkup[2]; + int min_cmaps; + Cursor target; + Cursor sweep0; + Cursor boxcurs; + Cursor arrow; + Cursor bordcurs[NBorder]; + Pixmap root_pixmap; + char display[256]; /* arbitrary limit */ +}; + +/* main.c */ +extern Display *dpy; +extern ScreenInfo *screens; +extern int num_screens; +extern int initting; +extern XFontStruct *font; +extern int nostalgia; +extern char **myargv; +extern Bool shape; +extern char *termprog; +extern char *shell; +extern char *version[]; +extern int _border; +extern int _corner; +extern int _inset; +extern int curtime; +extern int debug; +extern int solidsweep; +extern int numvirtuals; +extern int scrolling; +extern int ffm; /* focus follows mouse */ + +extern Atom exit_rio; +extern Atom restart_rio; +extern Atom wm_state; +extern Atom wm_change_state; +extern Atom _rio_hold_mode; +extern Atom wm_protocols; +extern Atom wm_delete; +extern Atom wm_take_focus; +extern Atom wm_lose_focus; +extern Atom wm_colormaps; +extern Atom wm_state_fullscreen; +extern Atom wm_state; +/* client.c */ +extern Client *clients; +extern Client *current; +extern Client *currents[]; + +/* menu.c */ +extern Client *hiddenc[]; +extern int numhidden; +extern char *b2items[]; +extern Menu b2menu; +extern char *b3items[]; +extern Menu b3menu; +extern int virt; + +/* manage.c */ +extern int isNew; + +/* error.c */ +extern int ignore_badwindow; + +/* key.c and event.c share this */ + +extern int kbLaunch;
A error.c

@@ -0,0 +1,102 @@

+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ +#include <stdio.h> +#include <stdlib.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xproto.h> +#include "dat.h" +#include "fns.h" + +int ignore_badwindow; + +void +fatal(char *s) +{ + fprintf(stderr, "ryudo: "); + perror(s); + fprintf(stderr, "\n"); + exit(1); +} + +int +handler(Display *d, XErrorEvent *e) +{ + char msg[80], req[80], number[80]; + + if(initting && (e->request_code == X_ChangeWindowAttributes) && (e->error_code == BadAccess)){ + fprintf(stderr, "ryudo: it looks like there's already a window manager running; ryudo not started\n"); + exit(1); + } + + if(ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor)) + return 0; + + XGetErrorText(d, e->error_code, msg, sizeof(msg)); + sprintf(number, "%d", e->request_code); + XGetErrorDatabaseText(d, "XRequest", number, "", req, sizeof(req)); + if(req[0] == '\0') + sprintf(req, "<request-code-%d>", (int)e->request_code); + + fprintf(stderr, "ryudo: %s(0x%x): %s\n", req, (int)e->resourceid, msg); + + if(initting){ + fprintf(stderr, "ryudo: failure during initialisation; aborting\n"); + exit(1); + } + return 0; +} + +void +graberror(char *f, int err) +{ +#ifdef DEBUG /* sick of "bug" reports; grab errors "just happen" */ + char *s; + + switch (err){ + case GrabNotViewable: + s = "not viewable"; + break; + case AlreadyGrabbed: + s = "already grabbed"; + break; + case GrabFrozen: + s = "grab frozen"; + break; + case GrabInvalidTime: + s = "invalid time"; + break; + case GrabSuccess: + return; + default: + fprintf(stderr, "ryudo: %s: grab error: %d\n", f, err); + return; + } + fprintf(stderr, "ryudo: %s: grab error: %s\n", f, s); +#endif +} + +#ifdef DEBUG_EV +#include "showevent/ShowEvent.c" +#endif + +#ifdef DEBUG + +void +dotrace(char *s, Client *c, XEvent *e) +{ + if(debug == 0) + return; +setbuf(stdout, 0); + fprintf(stderr, "ryudo: %s: c=%p", s, (void*)c); + if(c) + fprintf(stderr, " x %d y %d dx %d dy %d w 0x%x parent 0x%x", c->x, c->y, c->dx, c->dy, (int)c->window, (int)c->parent); +#ifdef DEBUG_EV + if(e){ + fprintf(stderr, "\n\t"); + ShowEvent(e); + } +#endif + fprintf(stderr, "\n"); +} +#endif
A event.c

@@ -0,0 +1,619 @@

+/* + * Copyright (c) 2019 Derek Stevens, 2005 Rus Cox, 1994-1996 David Hogan + * see README for licence details + */ + +#include <stdio.h> +#include <stdlib.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/extensions/shape.h> +#include "dat.h" +#include "fns.h" +#include "patchlevel.h" + +void +mainloop(int shape_event) +{ + XEvent ev; + + for(;;){ + getevent(&ev); + +#ifdef DEBUG_EV + if(debug){ + ShowEvent(&ev); + printf("\n"); + } +#endif + switch (ev.type){ + default: +#ifdef SHAPE + if(shape && ev.type == shape_event) + shapenotify((XShapeEvent *)&ev); + else +#endif + fprintf(stderr, "ryudo: unknown ev.type %d\n", ev.type); + break; + case KeyPress: + keypress(&ev.xkey); + break; + case KeyRelease: + keyrelease(&ev.xkey); + break; + case ButtonPress: + button(&ev.xbutton); + break; + case ButtonRelease: + break; + case MapRequest: + mapreq(&ev.xmaprequest); + break; + case ConfigureRequest: + configurereq(&ev.xconfigurerequest); + break; + case CirculateRequest: + circulatereq(&ev.xcirculaterequest); + break; + case UnmapNotify: + unmap(&ev.xunmap); + break; + case CreateNotify: + newwindow(&ev.xcreatewindow); + break; + case DestroyNotify: + destroy(ev.xdestroywindow.window); + break; + case ClientMessage: + clientmesg(&ev.xclient); + break; + case ColormapNotify: + cmap(&ev.xcolormap); + break; + case PropertyNotify: + property(&ev.xproperty); + break; + case SelectionClear: + fprintf(stderr, "ryudo: SelectionClear (this should not happen)\n"); + break; + case SelectionNotify: + fprintf(stderr, "ryudo: SelectionNotify (this should not happen)\n"); + break; + case SelectionRequest: + fprintf(stderr, "ryudo: SelectionRequest (this should not happen)\n"); + break; + case EnterNotify: + enter(&ev.xcrossing); + break; + case LeaveNotify: + leave(&ev.xcrossing); + break; + case ReparentNotify: + reparent(&ev.xreparent); + break; + case FocusIn: + focusin(&ev.xfocus); + break; + case MotionNotify: + motionnotify(&ev.xmotion); + break; + case Expose: + case NoExpose: + case FocusOut: + case ConfigureNotify: + case MapNotify: + case MappingNotify: + case GraphicsExpose: + /* not interested */ + trace("ignore", 0, &ev); + break; + } + } +} + + +void +configurereq(XConfigureRequestEvent *e) +{ + XWindowChanges wc; + Client *c; + + /* we don't set curtime as nothing here uses it */ + c = getclient(e->window, 0); + trace("configurereq", c, e); + + e->value_mask &= ~CWSibling; + + if(c){ + if(e->value_mask & CWX) + c->x = e->x; + if(e->value_mask & CWY) + c->y = e->y; + if(e->value_mask & CWWidth) + c->dx = e->width; + if(e->value_mask & CWHeight) + c->dy = e->height; + if(e->value_mask & CWBorderWidth) + c->border = e->border_width; + + if(c->dx >= c->screen->width && c->dy >= c->screen->height) + c->border = 0; + else + c->border = BORDER; + + if(e->value_mask & CWStackMode){ + if(e->detail == Above) + top(c); + else + e->value_mask &= ~CWStackMode; + } + e->value_mask |= CWX|CWY|CWHeight|CWWidth; + + if(c->parent != c->screen->root && c->window == e->window){ + wc.x = c->x - c->border; + wc.y = c->y - c->border; + wc.width = c->dx+c->border+c->border; + wc.height = c->dy+c->border+c->border; + wc.border_width = 1; + wc.sibling = None; + wc.stack_mode = e->detail; + XConfigureWindow(dpy, c->parent, e->value_mask, &wc); + + if(e->value_mask & CWStackMode){ + top(c); + active(c); + } + } + } + + if(c && c->parent != c->screen->root){ + wc.x = c->border; + wc.y = c->border; + }else { + wc.x = c->x; + wc.y = c->y; + } + wc.width = c->dx; + wc.height = c->dy; + wc.border_width = 0; + wc.sibling = None; + wc.stack_mode = Above; + e->value_mask &= ~CWStackMode; + e->value_mask |= CWBorderWidth; + XConfigureWindow(dpy, c->window, e->value_mask, &wc); +} + +void +mapreq(XMapRequestEvent *e) +{ + Client *c; + int i; + + curtime = CurrentTime; + c = getclient(e->window, 0); + trace("mapreq", c, e); + + if(c == 0 || c->window != e->window){ + /* workaround for stupid NCDware */ + fprintf(stderr, "ryudo: bad mapreq c %p w %x, rescanning\n", + (void*)c, (int)e->window); + for(i = 0; i < num_screens; i++) + scanwins(&screens[i]); + c = getclient(e->window, 0); + if(c == 0 || c->window != e->window){ + fprintf(stderr, "ryudo: window not found after rescan\n"); + return; + } + } + + switch (c->state){ + case WithdrawnState: + if(c->parent == c->screen->root){ + if(!manage(c, 0)) + return; + break; + } + XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1); + XAddToSaveSet(dpy, c->window); + /* fall through... */ + case NormalState: + XMapWindow(dpy, c->window); + XMapRaised(dpy, c->parent); + top(c); + setstate(c, NormalState); + if(c->trans != None && current && c->trans == current->window) + active(c); + break; + case IconicState: + unhidec(c, 1); + break; + } +} + +void +unmap(XUnmapEvent *e) +{ + Client *c; + + curtime = CurrentTime; + c = getclient(e->window, 0); + if(c){ + switch (c->state){ + case IconicState: + if(e->send_event){ + unhidec(c, 0); + withdraw(c); + } + break; + case NormalState: + if(c == current) + nofocus(); + if(!c->reparenting) + withdraw(c); + break; + } + c->reparenting = 0; + } +} + +void +circulatereq(XCirculateRequestEvent *e) +{ + fprintf(stderr, "It must be the warlock Krill!\n"); /* ☺ */ +} + +void +newwindow(XCreateWindowEvent *e) +{ + Client *c; + ScreenInfo *s; + + /* we don't set curtime as nothing here uses it */ + if(e->override_redirect) + return; + c = getclient(e->window, 1); + if(c && c->window == e->window && (s = getscreen(e->parent))){ + c->x = e->x; + c->y = e->y; + c->dx = e->width; + c->dy = e->height; + c->border = e->border_width; + c->screen = s; + if(c->parent == None) + c->parent = c->screen->root; + } + if (kbLaunch) + { + quickreshape(c, c->screen->width/5, c->screen->height/5, 3*c->screen->width/5, 3*c->screen->height/5); + kbLaunch = 0; + } +} + +void +destroy(Window w) +{ + int i; + Client *c; + + curtime = CurrentTime; + c = getclient(w, 0); + if(c == 0) + return; + + if(numvirtuals > 1) + for(i=0; i<numvirtuals; i++) + if(currents[i] == c) + currents[i] = 0; + + rmclient(c); + + /* flush any errors generated by the window's sudden demise */ + ignore_badwindow = 1; + XSync(dpy, False); + ignore_badwindow = 0; +} + +void +clientmesg(XClientMessageEvent *e) +{ + Client *c; + + curtime = CurrentTime; + if(e->message_type == exit_rio){ + cleanup(); + exit(0); + } + if(e->message_type == restart_rio){ + fprintf(stderr, "*** rio restarting ***\n"); + cleanup(); + execvp(myargv[0], myargv); + perror("ryudo: exec failed"); + exit(1); + } + if(e->message_type == wm_protocols) + return; + if(e->message_type == wm_change_state){ + c = getclient(e->window, 0); + if(e->format == 32 && e->data.l[0] == IconicState && c != 0){ + if(normal(c)) + hide(c); + } + else + fprintf(stderr, "ryudo: WM_CHANGE_STATE: format %d data %d w 0x%x\n", + (int)e->format, (int)e->data.l[0], (int)e->window); + return; + } + if(e->message_type == wm_state){ +// c = getclient(e->window, 0); +// if(e->format == 32 && e->data.l[1] == wm_state_fullscreen){ +// }else + fprintf(stderr, "ryudo: WM_STATE: format %d data %d %d w 0x%x\n", + (int)e->format, (int)e->data.l[0], (int)e->data.l[1], + (int)e->window); + return; + } + fprintf(stderr, "ryudo: strange ClientMessage, type 0x%x window 0x%x\n", + (int)e->message_type, (int)e->window); +} + +void +cmap(XColormapEvent *e) +{ + Client *c; + int i; + + /* we don't set curtime as nothing here uses it */ + if(e->new){ + c = getclient(e->window, 0); + if(c){ + c->cmap = e->colormap; + if(c == current) + cmapfocus(c); + } + else + for(c = clients; c; c = c->next){ + for(i = 0; i < c->ncmapwins; i++) + if(c->cmapwins[i] == e->window){ + c->wmcmaps[i] = e->colormap; + if(c == current) + cmapfocus(c); + return; + } + } + } +} + +void +property(XPropertyEvent *e) +{ + Atom a; + int delete; + Client *c; + long msize; + + /* we don't set curtime as nothing here uses it */ + a = e->atom; + delete = (e->state == PropertyDelete); + c = getclient(e->window, 0); + if(c == 0) + return; + + switch (a){ + case XA_WM_ICON_NAME: + if(c->iconname != 0) + XFree((char*) c->iconname); + c->iconname = delete ? 0 : getprop(c->window, a); + setlabel(c); + renamec(c, c->label); + return; + case XA_WM_NAME: + if(c->name != 0) + XFree((char*) c->name); + c->name = delete ? 0 : getprop(c->window, a); + setlabel(c); + renamec(c, c->label); + return; + case XA_WM_TRANSIENT_FOR: + gettrans(c); + return; + case XA_WM_HINTS: + case XA_WM_SIZE_HINTS: + case XA_WM_ZOOM_HINTS: + /* placeholders to not forget. ignore for now. -Axel */ + return; + case XA_WM_NORMAL_HINTS: + if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0) + c->size.flags = PSize; /* not specified - punt */ + return; + } + if(a == _rio_hold_mode){ + c->hold = getiprop(c->window, _rio_hold_mode); + if(c == current) + draw_border(c, 1); + } + else if(a == wm_colormaps){ + getcmaps(c); + if(c == current) + cmapfocus(c); + } +} + +void +reparent(XReparentEvent *e) +{ + Client *c; + XWindowAttributes attr; + ScreenInfo *s; + + /* we don't set curtime as nothing here uses it */ + if(!getscreen(e->event) || e->override_redirect) + return; + if((s = getscreen(e->parent)) != 0){ + c = getclient(e->window, 1); + if(c != 0 && (c->dx == 0 || c->dy == 0)){ + /* flush any errors */ + ignore_badwindow = 1; + XGetWindowAttributes(dpy, c->window, &attr); + XSync(dpy, False); + ignore_badwindow = 0; + + c->x = attr.x; + c->y = attr.y; + c->dx = attr.width; + c->dy = attr.height; + c->border = attr.border_width; + c->screen = s; + if(c->parent == None) + c->parent = c->screen->root; + } + } + else { + c = getclient(e->window, 0); + if(c != 0 && (c->parent == c->screen->root || withdrawn(c))) + rmclient(c); + } +} + +#ifdef SHAPE +void +shapenotify(XShapeEvent *e) +{ + Client *c; + + /* we don't set curtime as nothing here uses it */ + c = getclient(e->window, 0); + if(c == 0) + return; + + setshape(c); +} +#endif + +void +enter(XCrossingEvent *e) +{ + Client *c; + + curtime = e->time; + if(!ffm) + if(e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual) + return; + c = getclient(e->window, 0); + if(c != 0 && c != current){ + /* someone grabbed the pointer; make them current */ + if(!ffm) + XMapRaised(dpy, c->parent); + top(c); + active(c); + } +} + +void +leave(XCrossingEvent *e) +{ + Client *c; + + c = getclient(e->window, 0); + if(c) + XUndefineCursor(dpy, c->parent); +/* XDefineCursor(dpy, c->parent, c->screen->arrow); */ +} + +void +focusin(XFocusChangeEvent *e) +{ + Client *c; + + curtime = CurrentTime; + if(e->detail != NotifyNonlinearVirtual) + return; + c = getclient(e->window, 0); + if(c != 0 && c->window == e->window && c != current){ + /* someone grabbed keyboard or seized focus; make them current */ + XMapRaised(dpy, c->parent); + top(c); + active(c); + } +} + +BorderOrient +borderorient(Client *c, int x, int y) +{ + if(x <= BORDER){ + if(y <= CORNER){ + if(debug) fprintf(stderr, "topleft\n"); + return BorderWNW; + } + if(y >= (c->dy + 2*BORDER) - CORNER){ + if(debug) fprintf(stderr, "botleft\n"); + return BorderWSW; + } + if(y > CORNER && + y < (c->dy + 2*BORDER) - CORNER){ + if(debug) fprintf(stderr, "left\n"); + return BorderW; + } + } else if(x <= CORNER){ + if(y <= BORDER){ + if(debug) fprintf(stderr, "topleft\n"); + return BorderNNW; + } + if (y >= (c->dy + BORDER)){ + if(debug) fprintf(stderr, "botleft\n"); + return BorderSSW; + } + } else if(x >= (c->dx + BORDER)){ + if(y <= CORNER){ + if(debug) fprintf(stderr, "topright\n"); + return BorderENE; + } + if(y >= (c->dy + 2*BORDER) - CORNER){ + if(debug) fprintf(stderr, "botright\n"); + return BorderESE; + } + if(y > CORNER && + y < (c->dy + 2*BORDER) - CORNER){ + if(debug) fprintf(stderr, "right\n"); + return BorderE; + } + } else if(x >= (c->dx + 2*BORDER) - CORNER){ + if(y <= BORDER){ + if(debug) fprintf(stderr, "topright\n"); + return BorderNNE; + } + if (y >= (c->dy + BORDER)){ + if(debug) fprintf(stderr, "botright\n"); + return BorderSSE; + } + } else if(x > CORNER && + x < (c->dx + 2*BORDER) - CORNER){ + if(y <= BORDER){ + if(debug) fprintf(stderr, "top\n"); + return BorderN; + } + if(y >= (c->dy + BORDER)){ + if(debug) fprintf(stderr, "bot\n"); + return BorderS; + } + } + return BorderUnknown; +} + +void +motionnotify(XMotionEvent *e) +{ + Client *c; + BorderOrient bl; + + c = getclient(e->window, 0); + if(c){ + bl = borderorient(c, e->x, e->y); + if(bl == BorderUnknown) + XUndefineCursor(dpy, c->parent); + else + XDefineCursor(dpy, c->parent, c->screen->bordcurs[bl]); + } +}
A fns.h

@@ -0,0 +1,118 @@

+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ + +#ifdef DEBUG +#define trace(s, c, e) dotrace((s), (c), (e)) +#else +#define trace(s, c, e) +#endif + +#define setstate setstaterio + + +/* color.c */ +unsigned long colorpixel(Display*, ScreenInfo*, int, unsigned long, unsigned long); + +/* main.c */ +void usage(); +void initscreen(); +ScreenInfo *getscreen(); +Time timestamp(); +void sendcmessage(); +void sendconfig(); +void sighandler(); +void getevent(); +void cleanup(); + +/* event.c */ +void mainloop(); +void configurereq(); +void mapreq(); +void circulatereq(); +void unmap(); +void newwindow(); +void destroy(); +void clientmesg(); +void cmap(); +void property(); +void shapenotify(); +void enter(); +void leave(); +void focusin(); +void reparent(); +void motionnotify(); +BorderOrient borderorient(); + +/* manage.c */ +int manage(); +void scanwins(); +void setshape(); +void withdraw(); +void gravitate(); +void cmapfocus(); +void cmapnofocus(); +void getcmaps(); +int _getprop(); +char *getprop(); +Window getwprop(); +int getiprop(); +int getstate(); +void setstate(); +void setlabel(); +void getproto(); +void gettrans(); + +/* key.c */ +void keypress(); +void keyrelease(); +void keysetup(); +void quickreshape(); + +/* menu.c */ +void button(); +void spawn(); +void reshape(); +void move(); +void delete(); +void hide(); +void unhide(); +void unhidec(); +void renamec(); +void button2(); +void initb2menu(); +void switch_to(); +void switch_to_c(); + + + +/* client.c */ +void setactive(); +void draw_border(); +void active(); +void nofocus(); +void top(); +Client *getclient(); +void rmclient(); +void dump_revert(); +void dump_clients(); +void shuffle(int); + +/* grab.c */ +int menuhit(); +Client *selectwin(); +int sweep(); +int drag(); +int pull(); +void getmouse(); +void setmouse(); + +/* error.c */ +int handler(); +void fatal(); +void graberror(); +void showhints(); +void dotrace(); + +/* cursor.c */ +void initcurs(); + +void ShowEvent(XEvent*);
A grab.c

@@ -0,0 +1,675 @@

+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "dat.h" +#include "fns.h" + +int +nobuttons(XButtonEvent *e) /* Einstuerzende */ +{ + int state; + + state = (e->state & AllButtonMask); + return (e->type == ButtonRelease) && (state & (state - 1)) == 0; +} + +int +grab(Window w, Window constrain, int mask, Cursor curs, int t) +{ + int status; + + if(t == 0) + t = timestamp(); + status = XGrabPointer(dpy, w, False, mask, + GrabModeAsync, GrabModeAsync, constrain, curs, t); + return status; +} + +void +ungrab(XButtonEvent *e) +{ + XEvent ev; + + if(!nobuttons(e)) + for(;;){ + XMaskEvent(dpy, ButtonMask | ButtonMotionMask, &ev); + if(ev.type == MotionNotify) + continue; + e = &ev.xbutton; + if(nobuttons(e)) + break; + } + XUngrabPointer(dpy, e->time); + curtime = e->time; +} + +static void +drawstring(Display *dpy, ScreenInfo *s, Menu *m, int wide, int high, int i, int selected) +{ + int tx, ty; + + tx = (wide - XTextWidth(font, m->item[i], strlen(m->item[i])))/2; + ty = i*high + font->ascent + 1; + XFillRectangle(dpy, s->menuwin, selected ? s->gcmenubgs : s->gcmenubg, 0, i*high, wide, high); + XDrawString(dpy, s->menuwin, selected ? s->gcmenufgs : s->gcmenufg, tx, ty, m->item[i], strlen(m->item[i])); +} + +int +menuhit(XButtonEvent *e, Menu *m) +{ + XEvent ev; + int i, n, cur, old, wide, high, status, drawn, warp; + int x, y, dx, dy, xmax, ymax; + ScreenInfo *s; + + if(font == 0) + return -1; + s = getscreen(e->root); + if(s == 0 || e->window == s->menuwin) /* ugly event mangling */ + return -1; + + dx = 0; + for(n = 0; m->item[n]; n++){ + wide = XTextWidth(font, m->item[n], strlen(m->item[n])) + 4; + if(wide > dx) + dx = wide; + } + wide = dx; + cur = m->lasthit; + if(cur >= n) + cur = n - 1; + + high = font->ascent + font->descent + 1; + dy = n*high; + x = e->x - wide/2; + y = e->y - cur*high - high/2; + warp = 0; + xmax = DisplayWidth(dpy, s->num); + ymax = DisplayHeight(dpy, s->num); + if(x < 0){ + e->x -= x; + x = 0; + warp++; + } + if(x+wide >= xmax){ + e->x -= x+wide-xmax; + x = xmax-wide; + warp++; + } + if(y < 0){ + e->y -= y; + y = 0; + warp++; + } + if(y+dy >= ymax){ + e->y -= y+dy-ymax; + y = ymax-dy; + warp++; + } + if(warp) + setmouse(e->x, e->y, s); + XMoveResizeWindow(dpy, s->menuwin, x, y, dx, dy); + XSelectInput(dpy, s->menuwin, MenuMask); + XMapRaised(dpy, s->menuwin); + status = grab(s->menuwin, None, MenuGrabMask, None, e->time); + if(status != GrabSuccess){ + /* graberror("menuhit", status); */ + XUnmapWindow(dpy, s->menuwin); + return -1; + } + drawn = 0; + for(;;){ + XMaskEvent(dpy, MenuMask, &ev); + switch (ev.type){ + default: + fprintf(stderr, "ryudo: menuhit: unknown ev.type %d\n", ev.type); + break; + case ButtonPress: + break; + case ButtonRelease: + if(ev.xbutton.button != e->button) + break; + x = ev.xbutton.x; + y = ev.xbutton.y; + i = y/high; + if(cur >= 0 && y >= cur*high-3 && y < (cur+1)*high+3) + i = cur; + if(x < 0 || x > wide || y < -3) + i = -1; + else if(i < 0 || i >= n) + i = -1; + else + m->lasthit = i; + if(!nobuttons(&ev.xbutton)) + i = -1; + ungrab(&ev.xbutton); + XUnmapWindow(dpy, s->menuwin); + return i; + case MotionNotify: + if(!drawn) + break; + x = ev.xbutton.x; + y = ev.xbutton.y; + old = cur; + cur = y/high; + if(old >= 0 && y >= old*high-3 && y < (old+1)*high+3) + cur = old; + if(x < 0 || x > wide || y < -3) + cur = -1; + else if(cur < 0 || cur >= n) + cur = -1; + if(cur == old) + break; + if(old >= 0 && old < n) + drawstring(dpy, s, m, wide, high, old, 0); + if(cur >= 0 && cur < n) + drawstring(dpy, s, m, wide, high, cur, 1); + break; + case Expose: + XClearWindow(dpy, s->menuwin); + for(i = 0; i < n; i++) + drawstring(dpy, s, m, wide, high, i, cur==i); + drawn = 1; + } + } +} + +Client * +selectwin(int release, int *shift, ScreenInfo *s) +{ + XEvent ev; + XButtonEvent *e; + int status; + Window w; + Client *c; + + status = grab(s->root, s->root, ButtonMask, s->target, 0); + if(status != GrabSuccess){ + graberror("selectwin", status); /* */ + return 0; + } + w = None; + for(;;){ + XMaskEvent(dpy, ButtonMask, &ev); + e = &ev.xbutton; + switch (ev.type){ + case ButtonPress: + if(e->button != Button3){ + ungrab(e); + return 0; + } + w = e->subwindow; + if(!release){ + c = getclient(w, 0); + if(c == 0) + ungrab(e); + if(shift != 0) + *shift = (e->state&ShiftMask) != 0; + return c; + } + break; + case ButtonRelease: + ungrab(e); + if(e->button != Button3 || e->subwindow != w) + return 0; + if(shift != 0) + *shift = (e->state&ShiftMask) != 0; + return getclient(w, 0); + } + } +} + +int +sweepcalc(Client *c, int x, int y, BorderOrient bl, int ignored) +{ + int dx, dy, sx, sy; + + dx = x - c->x; + dy = y - c->y; + sx = sy = 1; + x += dx; + if(dx < 0){ + dx = -dx; + sx = -1; + } + y += dy; + if(dy < 0){ + dy = -dy; + sy = -1; + } + + dx -= 2*BORDER; + dy -= 2*BORDER; + + if(!c->is9term){ + if(dx < c->min_dx) + dx = c->min_dx; + if(dy < c->min_dy) + dy = c->min_dy; + } + + if(c->size.flags & PResizeInc){ + dx = c->min_dx + (dx-c->min_dx)/c->size.width_inc*c->size.width_inc; + dy = c->min_dy + (dy-c->min_dy)/c->size.height_inc*c->size.height_inc; + } + + if(c->size.flags & PMaxSize){ + if(dx > c->size.max_width) + dx = c->size.max_width; + if(dy > c->size.max_height) + dy = c->size.max_height; + } + c->dx = sx*(dx + 2*BORDER); + c->dy = sy*(dy + 2*BORDER); + + return ignored; +} + +int +dragcalc(Client *c, int x, int y, BorderOrient bl, int ignored) +{ + c->x += x; + c->y += y; + + return ignored; +} + +int +pullcalc(Client *c, int x, int y, BorderOrient bl, int init) +{ + int dx, dy, sx, sy, px, py, spx, spy, rdx, rdy, xoff, yoff, xcorn, ycorn; + + px = c->x; + py = c->y; + dx = c->dx; + dy = c->dy; + sx = sy = 1; + spx = spy = 0; + xoff = yoff = 0; + xcorn = ycorn = 0; + + switch(bl){ + case BorderN: + py = y; + dy = (c->y + c->dy) - y; + spy = 1; + yoff = y - c->y; + break; + case BorderS: + dy = y - c->y; + yoff = (c->y + c->dy) - y; + break; + case BorderE: + dx = x - c->x; + xoff = (c->x + c->dx) - x; + break; + case BorderW: + px = x; + dx = (c->x + c->dx) - x; + spx = 1; + xoff = x - c->x; + break; + case BorderNNW: + case BorderWNW: + px = x; + dx = (c->x + c->dx) - x; + spx = 1; + py = y; + dy = (c->y + c->dy) - y; + spy = 1; + xoff = x - c->x; + yoff = y - c->y; + break; + case BorderNNE: + case BorderENE: + dx = x - c->x; + py = y; + dy = (c->y + c->dy) - y; + spy = 1; + xoff = (c->x + c->dx) - x; + yoff = y - c->y; + break; + case BorderSSE: + case BorderESE: + dx = x - c->x; + dy = y - c->y; + xoff = (c->x + c->dx) - x; + yoff = (c->y + c->dy) - y; + break; + case BorderSSW: + case BorderWSW: + px = x; + dx = (c->x + c->dx) - x; + spx = 1; + dy = y - c->y; + xoff = x - c->x; + yoff = (c->y + c->dy) - y; + break; + default: + break; + } + switch(bl){ + case BorderNNW: + case BorderNNE: + case BorderSSW: + case BorderSSE: + xcorn = 1; + break; + case BorderWNW: + case BorderENE: + case BorderWSW: + case BorderESE: + ycorn = 1; + break; + } + if(!init + || xoff < 0 || (xcorn && xoff > CORNER) || (!xcorn && xoff > BORDER) + || yoff < 0 || (ycorn && yoff > CORNER) || (!ycorn && yoff > BORDER)){ + xoff = 0; + yoff = 0; + init = 0; + } + + if(debug) fprintf(stderr, "c %dx%d+%d+%d m +%d+%d r %dx%d+%d+%d sp (%d,%d) bl %d\n", + c->dx, c->dy, c->x, c->y, x, y, dx, dy, px, py, spx, spy, bl); + if(dx < 0){ + dx = -dx; + sx = -1; + } + if(dy < 0){ + dy = -dy; + sy = -1; + } + + /* remember requested size; + * after applying size hints we may have to correct position + */ + rdx = sx*dx; + rdy = sy*dy; + + /* apply size hints */ + dx -= (2*BORDER - xoff); + dy -= (2*BORDER - yoff); + + if(!c->is9term){ + if(dx < c->min_dx) + dx = c->min_dx; + if(dy < c->min_dy) + dy = c->min_dy; + } + + if(c->size.flags & PResizeInc){ + dx = c->min_dx + (dx-c->min_dx)/c->size.width_inc*c->size.width_inc; + dy = c->min_dy + (dy-c->min_dy)/c->size.height_inc*c->size.height_inc; + } + + if(c->size.flags & PMaxSize){ + if(dx > c->size.max_width) + dx = c->size.max_width; + if(dy > c->size.max_height) + dy = c->size.max_height; + } + + /* set size and position */ + c->dx = sx*(dx + 2*BORDER ); + c->dy = sy*(dy + 2*BORDER ); + c->x = px; + c->y = py; + + /* compensate position for size changed due to size hints */ + if(spx) + c->x -= c->dx - rdx; + if(spy) + c->y -= c->dy - rdy; + + return init; +} + +static void +xcopy(int fwd, Display *dpy, Drawable src, Drawable dst, GC gc, int x, int y, int dx, int dy, int x1, int y1) +{ + if(fwd) + XCopyArea(dpy, src, dst, gc, x, y, dx, dy, x1, y1); + else + XCopyArea(dpy, dst, src, gc, x1, y1, dx, dy, x, y); +} + +void +drawbound(Client *c, int drawing) +{ + int x, y, dx, dy; + ScreenInfo *s; + + if(debug) fprintf(stderr, "drawbound %d %dx%d+%d+%d\n", drawing, c->dx, c->dy, c->x, c->y); + + s = c->screen; + x = c->x; + y = c->y; + dx = c->dx; + dy = c->dy; + if(dx < 0){ + x += dx; + dx = -dx; + } + if(dy < 0){ + y += dy; + dy = -dy; + } + if(dx <= 2 || dy <= 2) + return; + + if(solidsweep){ + if(drawing == -1){ + XUnmapWindow(dpy, s->sweepwin); + return; + } + + x += BORDER; + y += BORDER; + dx -= 2*BORDER; + dy -= 2*BORDER; + + if(drawing){ + XMoveResizeWindow(dpy, s->sweepwin, x, y, dx, dy); + XSelectInput(dpy, s->sweepwin, MenuMask); + XMapRaised(dpy, s->sweepwin); + } + return; + } + + if(drawing == -1) + return; + + xcopy(drawing, dpy, s->root, s->bkup[0], s->gccopy, x, y, dx, BORDER, 0, 0); + xcopy(drawing, dpy, s->root, s->bkup[0], s->gccopy, x, y+dy-BORDER, dx, BORDER, dx, 0); + xcopy(drawing, dpy, s->root, s->bkup[1], s->gccopy, x, y, BORDER, dy, 0, 0); + xcopy(drawing, dpy, s->root, s->bkup[1], s->gccopy, x+dx-BORDER, y, BORDER, dy, 0, dy); + + if(drawing){ + XFillRectangle(dpy, s->root, s->gcred, x, y, dx, BORDER); + XFillRectangle(dpy, s->root, s->gcred, x, y+dy-BORDER, dx, BORDER); + XFillRectangle(dpy, s->root, s->gcred, x, y, BORDER, dy); + XFillRectangle(dpy, s->root, s->gcred, x+dx-BORDER, y, BORDER, dy); + } +} + +void +misleep(int msec) +{ + struct timeval t; + + t.tv_sec = msec/1000; + t.tv_usec = (msec%1000)*1000; + select(0, 0, 0, 0, &t); +} + +int +sweepdrag(Client *c, int but, XButtonEvent *e0, BorderOrient bl, int (*recalc)(Client*, int, int, BorderOrient, int)) +{ + XEvent ev; + int idle; + int cx, cy, rx, ry; + int ox, oy, odx, ody; + XButtonEvent *e; + int notmoved; + + notmoved = 1; + ox = c->x; + oy = c->y; + odx = c->dx; + ody = c->dy; + c->x -= BORDER; + c->y -= BORDER; + c->dx += 2*BORDER; + c->dy += 2*BORDER; + if(bl != BorderUnknown || e0 == 0) + getmouse(&cx, &cy, c->screen); + else + getmouse(&c->x, &c->y, c->screen); + XGrabServer(dpy); + if(bl != BorderUnknown){ + notmoved = recalc(c, cx, cy, bl, notmoved); + } + drawbound(c, 1); + idle = 0; + for(;;){ + if(XCheckMaskEvent(dpy, ButtonMask, &ev) == 0){ + getmouse(&rx, &ry, c->screen); + if(rx != cx || ry != cy || ++idle > 300){ + drawbound(c, 0); + if(rx == cx && ry == cy){ + XUngrabServer(dpy); + XFlush(dpy); + misleep(500); + XGrabServer(dpy); + idle = 0; + } + if(e0 || bl != BorderUnknown) + notmoved = recalc(c, rx, ry, bl, notmoved); + else + notmoved = recalc(c, rx-cx, ry-cy, bl, notmoved); + cx = rx; + cy = ry; + drawbound(c, 1); + XFlush(dpy); + } + misleep(50); + continue; + } + e = &ev.xbutton; + switch (ev.type){ + case ButtonPress: + case ButtonRelease: + drawbound(c, 0); + ungrab(e); + XUngrabServer(dpy); + if(e->button != but && c->init) + goto bad; + if(c->dx < 0){ + c->x += c->dx; + c->dx = -c->dx; + } + if(c->dy < 0){ + c->y += c->dy; + c->dy = -c->dy; + } + c->x += BORDER; + c->y += BORDER; + c->dx -= 2*BORDER; + c->dy -= 2*BORDER; + if(c->dx < 4 || c->dy < 4 || c->dx < c->min_dx || c->dy < c->min_dy) + goto bad; + return 1; + } + } +bad: + if(debug) fprintf(stderr, "sweepdrag bad\n"); + c->x = ox; + c->y = oy; + c->dx = odx; + c->dy = ody; + drawbound(c, -1); + return 0; +} + +int +sweep(Client *c, int but, XButtonEvent *ignored) +{ + XEvent ev; + int status; + XButtonEvent *e; + ScreenInfo *s; + + s = c->screen; + c->dx = 0; + c->dy = 0; + status = grab(s->root, s->root, ButtonMask, s->sweep0, 0); + if(status != GrabSuccess){ + graberror("sweep", status); /* */ + return 0; + } + + XMaskEvent(dpy, ButtonMask, &ev); + e = &ev.xbutton; + if(e->button != but){ + ungrab(e); + return 0; + } + XChangeActivePointerGrab(dpy, ButtonMask, s->boxcurs, e->time); + return sweepdrag(c, but, e, BorderUnknown, sweepcalc); +} + +int +pull(Client *c, int but, XButtonEvent *e) +{ + int status; + ScreenInfo *s; + BorderOrient bl; + + bl = borderorient(c, e->x, e->y); + /* assert(bl > BorderUnknown && bl < NBorder); */ + + s = c->screen; + status = grab(s->root, s->root, ButtonMask, s->bordcurs[bl], 0); + if(status != GrabSuccess){ + graberror("pull", status); /* */ + return 0; + } + + return sweepdrag(c, but, 0, bl, pullcalc); +} + +int +drag(Client *c, int but) +{ + int status; + ScreenInfo *s; + + s = c->screen; + status = grab(s->root, s->root, ButtonMask, s->boxcurs, 0); + if(status != GrabSuccess){ + graberror("drag", status); /* */ + return 0; + } + return sweepdrag(c, but, 0, BorderUnknown, dragcalc); +} + +void +getmouse(int *x, int *y, ScreenInfo *s) +{ + Window dw1, dw2; + int t1, t2; + unsigned int t3; + + XQueryPointer(dpy, s->root, &dw1, &dw2, x, y, &t1, &t2, &t3); + if(debug) fprintf(stderr, "getmouse: %d %d\n", *x, *y); +} + +void +setmouse(int x, int y, ScreenInfo *s) +{ + XWarpPointer(dpy, None, s->root, None, None, None, None, x, y); +}
A key.c

@@ -0,0 +1,210 @@

+/* + * Copyright (c) 2019 Derek Stevens, 2005 Russ Cox, 1994-1996 David Hogan + * see README for license details + */ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include <X11/extensions/shape.h> +#include "config.h" +#include "dat.h" +#include "fns.h" +#include "patchlevel.h" + +enum +{ + GrabAltTab, + GrabAltAny +}; + +/*static int tabcode = 0x17; */ +/*static int altcode = 0x40; */ +/*static int pgupcode = 0x63; */ +/*static int pgdowncode = 0x69; */ + +static void alttab(int shift); +void quickreshape(Client*c, int x, int y, int dx, int dy); + +void +keysetup(void) +{ + int i; + int tabcode = XKeysymToKeycode(dpy, XK_Tab); + int dcode = XKeysymToKeycode(dpy, DESTROY_KEY); + int icode = XKeysymToKeycode(dpy, ICON_KEY); + int mcode = XKeysymToKeycode(dpy, MAX_KEY); + int vcode = XKeysymToKeycode(dpy, MOVE_KEY); + int rcode = XKeysymToKeycode(dpy, RESIZE_KEY); + int hcode = XKeysymToKeycode(dpy, SNAPLEFT_KEY); + int lcode = XKeysymToKeycode(dpy, SNAPRIGHT_KEY); + int jcode = XKeysymToKeycode(dpy, SNAPBOTTOM_KEY); + int kcode = XKeysymToKeycode(dpy, SNAPTOP_KEY); + int qcode = XKeysymToKeycode(dpy, SNAPTOPLEFT_KEY); + int wcode = XKeysymToKeycode(dpy, SNAPBOTTOMLEFT_KEY); + int ocode = XKeysymToKeycode(dpy, SNAPBOTTOMRIGHT_KEY); + int pcode = XKeysymToKeycode(dpy, SNAPTOPRIGHT_KEY); + int ccode = XKeysymToKeycode(dpy, SNAPCENTER_KEY); + int slcode = XKeysymToKeycode(dpy, LAUNCH_KEY); + int rightcode = XKeysymToKeycode(dpy, NEXTVIRT_KEY); + int leftcode = XKeysymToKeycode(dpy, PREVVIRT_KEY); + + for(i=0; i<num_screens; i++){ + XGrabKey(dpy, tabcode, Mod1Mask, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, dcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, icode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, rcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, vcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, mcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, hcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, lcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, jcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, kcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, qcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, wcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, ocode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, pcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, ccode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, leftcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, rightcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, slcode, SHORTCUTMOD, screens[i].root, 0, GrabModeSync, GrabModeAsync); + XGrabKey(dpy, tabcode, Mod1Mask|ShiftMask, screens[i].root, 0, GrabModeSync, GrabModeAsync); + /* XGrabKey(dpy, pgupcode, Mod1Mask, screens[i].root, 0, GrabModeSync, GrabModeAsync); */ + /* XGrabKey(dpy, pgdowncode, Mod1Mask, screens[i].root, 0, GrabModeSync, GrabModeAsync); */ + /* XGrabKey(dpy, altcode, 0, screens[i].root, 0, GrabModeSync, GrabModeAsync); */ + } +} + +void +keypress(XKeyEvent *e) +{ + /* + * process key press here + */ + int tabcode = XKeysymToKeycode(dpy, XK_Tab); + int dcode = XKeysymToKeycode(dpy, DESTROY_KEY); + int icode = XKeysymToKeycode(dpy, ICON_KEY); + int mcode = XKeysymToKeycode(dpy, MAX_KEY); + int vcode = XKeysymToKeycode(dpy, MOVE_KEY); + int rcode = XKeysymToKeycode(dpy, RESIZE_KEY); + int slcode = XKeysymToKeycode(dpy, LAUNCH_KEY); + int hcode = XKeysymToKeycode(dpy, SNAPLEFT_KEY); + int lcode = XKeysymToKeycode(dpy, SNAPRIGHT_KEY); + int jcode = XKeysymToKeycode(dpy, SNAPBOTTOM_KEY); + int kcode = XKeysymToKeycode(dpy, SNAPTOP_KEY); + int qcode = XKeysymToKeycode(dpy, SNAPTOPLEFT_KEY); + int wcode = XKeysymToKeycode(dpy, SNAPBOTTOMLEFT_KEY); + int ocode = XKeysymToKeycode(dpy, SNAPBOTTOMRIGHT_KEY); + int pcode = XKeysymToKeycode(dpy, SNAPTOPRIGHT_KEY); + int ccode = XKeysymToKeycode(dpy, SNAPCENTER_KEY); + int rightcode = XKeysymToKeycode(dpy, NEXTVIRT_KEY); + int leftcode = XKeysymToKeycode(dpy, PREVVIRT_KEY); + + XWindowAttributes ra; + XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra); + +/* alt tab */ + if(e->keycode == tabcode && (e->state&Mod1Mask) == (1<<3)) + alttab(e->state&ShiftMask); + +/* basic wm functionality */ + if(e->keycode == dcode && (e->state&SHORTCUTMOD) == (MODBITS)) + delete(current, 0); + if(e->keycode == icode && (e->state&SHORTCUTMOD) == (MODBITS)) + hide(current); + if (e->keycode == vcode && (e->state&SHORTCUTMOD) == (MODBITS)) + move(current, Button3); + if (e->keycode == rcode && (e->state&SHORTCUTMOD) == (MODBITS)) + reshape(current, Button3, sweep, 0); + if (e->keycode == mcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, 0, 0, ra.width, ra.height); + +/* half snap */ + if (e->keycode == hcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, 0, 0, ra.width/2, ra.height); + if (e->keycode == lcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, ra.width/2, 0, ra.width/2, ra.height); + if (e->keycode == jcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, 0, ra.height/2, ra.width, ra.height/2); + if (e->keycode == kcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, 0, 0, ra.width, ra.height/2); + +/* quarter snap */ + if (e->keycode == qcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, 0, 0, ra.width/2, ra.height/2); + if (e->keycode == wcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, 0, ra.height/2, ra.width/2, ra.height/2); + if (e->keycode == ocode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, ra.width/2, ra.height/2, ra.width/2, ra.height/2); + if (e->keycode == pcode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, ra.width/2, 0, ra.width/2, ra.height/2); + +/* center snap */ + if (e->keycode == ccode && (e->state&SHORTCUTMOD) == (MODBITS)) + quickreshape(current, ra.width/5, ra.height/5, 3*ra.width/5, 3*ra.height/5); + + +/* launch */ + if (e->keycode == slcode && (e->state&SHORTCUTMOD) == (MODBITS)){ + kbLaunch = 1; + if(fork() == 0){ + close(ConnectionNumber(dpy)); + if(dpy != '\0') + putenv(dpy); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + if(termprog != NULL){ + execl(shell, shell, "-c", termprog, (char*)0); + fprintf(stderr, "ryudo: exec %s", shell); + perror(" failed"); + } + execlp("urxvt", "urxvt", (char*)0); + execlp("9term", "9term", scrolling ? "-ws" : "-w", (char*)0); + execlp("xterm", "xterm", "-ut", (char*)0); + perror("ryudo: exec 9term/xterm failed"); + } + } + +/* switch virts */ + if (e->keycode == rightcode && (e->state&SHORTCUTMOD) == (MODBITS)) + if (numvirtuals > 1 && virt < numvirtuals - 1) + switch_to(virt + 1); + if (e->keycode == leftcode && (e->state&SHORTCUTMOD) == (MODBITS)) + if (numvirtuals >1 && virt > 0) + switch_to(virt - 1); + + XAllowEvents(dpy, SyncKeyboard, e->time); +} + +void +keyrelease(XKeyEvent *e) +{ + XAllowEvents(dpy, SyncKeyboard, e->time); +} + +void +quickreshape(Client *c, int x, int y, int dx, int dy) +{ + XMoveResizeWindow(dpy, c->parent, x,y, dx, dy); + c->x = x + BORDER; + c->y = y + BORDER; + c->dx = dx-2*BORDER; + c->dy = dy-2*BORDER; + XMoveResizeWindow(dpy, c->window, BORDER, BORDER, c->dx, c->dy); + sendconfig(c); +} + +static void +alttab(int shift) +{ + shuffle(shift); +/* fprintf(stderr, "%sTab\n", shift ? "Back" : ""); */ +} +
A main.c

@@ -0,0 +1,544 @@

+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#ifdef SHAPE +#include <X11/extensions/shape.h> +#endif +#include "config.h" +#include "dat.h" +#include "fns.h" +#include "patchlevel.h" + +char *version[] = +{ + "ryudo version 0.1, Copyright (c) 1994-1996 David Hogan, (c) 2004 Russ Cox, (c) 2019 Derek Stevens", 0 +}; + +Display *dpy; +ScreenInfo *screens; +int initting; +XFontStruct *font; +int nostalgia; +char **myargv; +char *termprog; +char *shell; +Bool shape; +int _border = 4; +int _corner = 25; +int _inset = 1; +int curtime; +int debug; +int signalled; +int scrolling; +int num_screens; +int solidsweep = 0; +int numvirtuals = 0; +int ffm = 0; +int kbLaunch = 0; + +Atom exit_rio; +Atom restart_rio; +Atom wm_state; +Atom wm_change_state; +Atom wm_protocols; +Atom wm_delete; +Atom wm_take_focus; +Atom wm_lose_focus; +Atom wm_colormaps; +Atom _rio_running; +Atom _rio_hold_mode; +Atom wm_state_fullscreen; +Atom wm_state; + +char *fontlist[] = { + "*-lucidatypewriter-medium-*-12-*-75-*", + "lucm.latin1.9", + "blit", + "*-lucidatypewriter-bold-*-14-*-75-*", + "9x15bold", + "fixed", + "*", + 0 +}; + +void +usage(void) +{ + fprintf(stderr, "usage: ryudo [-grey] [-font fname] [-s] [-term prog] [-version] [-virtuals num] [exit|restart]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int i, background, do_exit, do_restart; + char *fname; + int shape_event; +#ifdef SHAPE + int dummy; +#endif + + shape_event = 0; + myargv = argv; /* for restart */ + + do_exit = do_restart = 0; + background = 0; + font = 0; + fname = 0; + for(i = 1; i < argc; i++) + if(strcmp(argv[i], "-nostalgia") == 0) + nostalgia++; + else if(strcmp(argv[i], "-grey") == 0) + background = 1; + else if(strcmp(argv[i], "-debug") == 0) + debug++; + /* + else if(strcmp(argv[i], "-ffm") == 0) + ffm++; + */ + else if(strcmp(argv[i], "-font") == 0 && i+1<argc){ + i++; + fname = argv[i]; + } + else if(strcmp(argv[i], "-term") == 0 && i+1<argc) + termprog = argv[++i]; + else if(strcmp(argv[i], "-virtuals") == 0 && i+1<argc){ + numvirtuals = atoi(argv[++i]); + if(numvirtuals < 0 || numvirtuals > 12){ + fprintf(stderr, "ryudo: wrong number of virtual displays, defaulting to 4\n"); + numvirtuals = 4; + } + } else if(strcmp(argv[i], "-version") == 0){ + fprintf(stderr, "%s", version[0]); + if(PATCHLEVEL > 0) + fprintf(stderr, "; patch level %d", PATCHLEVEL); + fprintf(stderr, "\n"); + exit(0); + } + else if(strcmp(argv[i], "-s") == 0){ + scrolling = 1; + } + else if(argv[i][0] == '-') + usage(); + else + break; + for(; i < argc; i++) + if(strcmp(argv[i], "exit") == 0) + do_exit++; + else if(strcmp(argv[i], "restart") == 0) + do_restart++; + else + usage(); + + if(do_exit && do_restart) + usage(); + + shell = (char *)getenv("SHELL"); + if(shell == NULL) + shell = DEFSHELL; + + dpy = XOpenDisplay(""); + if(dpy == 0) + fatal("can't open display"); + + initting = 1; + XSetErrorHandler(handler); + if(signal(SIGTERM, sighandler) == SIG_IGN) + signal(SIGTERM, SIG_IGN); + if(signal(SIGINT, sighandler) == SIG_IGN) + signal(SIGINT, SIG_IGN); + if(signal(SIGHUP, sighandler) == SIG_IGN) + signal(SIGHUP, SIG_IGN); + + exit_rio = XInternAtom(dpy, "9WM_EXIT", False); + restart_rio = XInternAtom(dpy, "9WM_RESTART", False); + + curtime = -1; /* don't care */ + if(do_exit){ + sendcmessage(DefaultRootWindow(dpy), exit_rio, 0L, 1, 1); + XSync(dpy, False); + exit(0); + } + if(do_restart){ + sendcmessage(DefaultRootWindow(dpy), restart_rio, 0L, 1, 1); + XSync(dpy, False); + exit(0); + } + + if(0) XSynchronize(dpy, True); + + wm_state = XInternAtom(dpy, "WM_STATE", False); + wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False); + wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); + wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + wm_lose_focus = XInternAtom(dpy, "_9WM_LOSE_FOCUS", False); + wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); + _rio_running = XInternAtom(dpy, "_9WM_RUNNING", False); + _rio_hold_mode = XInternAtom(dpy, "_9WM_HOLD_MODE", False); + wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); + wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + + if(fname != 0) + if((font = XLoadQueryFont(dpy, fname)) == 0) + fprintf(stderr, "ryudo: warning: can't load font %s\n", fname); + + if(font == 0){ + i = 0; + for(;;){ + fname = fontlist[i++]; + if(fname == 0){ + fprintf(stderr, "ryudo: warning: can't find a font\n"); + break; + } + font = XLoadQueryFont(dpy, fname); + if(font != 0) + break; + } + } + if(nostalgia){ + _border--; + _inset--; + } + +#ifdef SHAPE + shape = XShapeQueryExtension(dpy, &shape_event, &dummy); +#endif + + num_screens = ScreenCount(dpy); + screens = (ScreenInfo *)malloc(sizeof(ScreenInfo) * num_screens); + + for(i = 0; i < num_screens; i++) + initscreen(&screens[i], i, background); + + initb2menu(numvirtuals); + + /* set selection so that 9term knows we're running */ + curtime = CurrentTime; + XSetSelectionOwner(dpy, _rio_running, screens[0].menuwin, timestamp()); + + XSync(dpy, False); + initting = 0; + + nofocus(); + + for(i = 0; i < num_screens; i++) + scanwins(&screens[i]); + + keysetup(); + mainloop(shape_event); + return 0; +} + +void +initscreen(ScreenInfo *s, int i, int background) +{ + char *ds, *colon, *dot1; + unsigned long mask; + unsigned long gmask; + XGCValues gv; + XSetWindowAttributes attr; + XVisualInfo xvi; + XSetWindowAttributes attrs; + + s->num = i; + s->root = RootWindow(dpy, i); + s->def_cmap = DefaultColormap(dpy, i); + s->min_cmaps = MinCmapsOfScreen(ScreenOfDisplay(dpy, i)); + s->depth = DefaultDepth(dpy, i); + + /* + * Figure out underlying screen format. + */ + if(XMatchVisualInfo(dpy, i, 16, TrueColor, &xvi) + || XMatchVisualInfo(dpy, i, 16, DirectColor, &xvi)){ + s->vis = xvi.visual; + s->depth = 16; + } + else + if(XMatchVisualInfo(dpy, i, 15, TrueColor, &xvi) + || XMatchVisualInfo(dpy, i, 15, DirectColor, &xvi)){ + s->vis = xvi.visual; + s->depth = 15; + } + else + if(XMatchVisualInfo(dpy, i, 24, TrueColor, &xvi) + || XMatchVisualInfo(dpy, i, 24, DirectColor, &xvi)){ + s->vis = xvi.visual; + s->depth = 24; + } + else + if(XMatchVisualInfo(dpy, i, 8, PseudoColor, &xvi) + || XMatchVisualInfo(dpy, i, 8, StaticColor, &xvi)){ + s->vis = xvi.visual; + s->depth = 8; + } + else{ + s->depth = DefaultDepth(dpy, i); + if(s->depth != 8){ + fprintf(stderr, "can't understand depth %d screen", s->depth); + exit(1); + } + s->vis = DefaultVisual(dpy, i); + } + if(DefaultDepth(dpy, i) != s->depth){ + s->def_cmap = XCreateColormap(dpy, s->root, s->vis, AllocNone); + } + + ds = DisplayString(dpy); + colon = rindex(ds, ':'); + if(colon && num_screens > 1){ + strcpy(s->display, "DISPLAY="); + strcat(s->display, ds); + colon = s->display + 8 + (colon - ds); /* use version in buf */ + dot1 = index(colon, '.'); /* first period after colon */ + if(!dot1) + dot1 = colon + strlen(colon); /* if not there, append */ + sprintf(dot1, ".%d", i); + } + else + s->display[0] = '\0'; + + s->black = BlackPixel(dpy, i); + s->white = WhitePixel(dpy, i); + s->activeholdborder = colorpixel(dpy, s, s->depth, SHOLDCOL, s->white); + s->inactiveholdborder = colorpixel(dpy, s, s->depth, HOLDCOL, s->black); + s->activeborder = colorpixel(dpy, s, s->depth, SBORDERCOL, s->black); + s->inactiveborder = colorpixel(dpy, s, s->depth, BORDERCOL, s->white); + s->red = colorpixel(dpy, s, s->depth, GHOSTCOL, s->white); + s->width = WidthOfScreen(ScreenOfDisplay(dpy, i)); + s->height = HeightOfScreen(ScreenOfDisplay(dpy, i)); + s->bkup[0] = XCreatePixmap(dpy, s->root, 2*s->width, BORDER, DefaultDepth(dpy, i)); + s->bkup[1] = XCreatePixmap(dpy, s->root, BORDER, 2*s->height, DefaultDepth(dpy, i)); + + gv.foreground = s->black^s->white; + gv.background = s->white; + gv.function = GXxor; + gv.line_width = 0; + gv.subwindow_mode = IncludeInferiors; + gmask = GCForeground | GCBackground | GCFunction | GCLineWidth + | GCSubwindowMode; + if(font != 0){ + gv.font = font->fid; + gmask |= GCFont; + } + s->gc = XCreateGC(dpy, s->root, gmask, &gv); + + gv.function = GXcopy; + s->gccopy = XCreateGC(dpy, s->root, gmask, &gv); + + gv.foreground = s->red; + s->gcred = XCreateGC(dpy, s->root, gmask, &gv); + + gv.foreground = colorpixel(dpy, s, s->depth, 0xEEEEEE, s->black); + s->gcsweep = XCreateGC(dpy, s->root, gmask, &gv); + + initcurs(s); + + attr.cursor = s->arrow; + attr.event_mask = SubstructureRedirectMask + | SubstructureNotifyMask | ColormapChangeMask + | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask + | KeyPressMask | EnterWindowMask; + mask = CWCursor|CWEventMask; + XChangeWindowAttributes(dpy, s->root, mask, &attr); + XSync(dpy, False); + + if(background){ + XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap); + XClearWindow(dpy, s->root); + } else + system("xsetroot -solid grey30"); + + attrs.border_pixel = colorpixel(dpy, s, s->depth, MBORDERCOL, s->black); + attrs.background_pixel = colorpixel(dpy, s, s->depth, MENUBGCOL, s->white); + attrs.colormap = s->def_cmap; + + s->menuwin = XCreateWindow(dpy, s->root, 0, 0, 1, 1, MENUBORDER, + s->depth, + CopyFromParent, + s->vis, + CWBackPixel | CWBorderPixel | CWColormap, + &attrs + ); + + + gv.foreground = colorpixel(dpy, s, s->depth, MENUBGCOL, s->black); + s->gcmenubg = XCreateGC(dpy, s->menuwin, gmask, &gv); + + gv.foreground = colorpixel(dpy, s, s->depth, SMENUBGCOL, s->white); + s->gcmenubgs = XCreateGC(dpy, s->menuwin, gmask, &gv); + + gv.foreground = colorpixel(dpy, s, s->depth, MENUFGCOL, s->white); + gv.background = colorpixel(dpy, s, s->depth, MENUBGCOL, s->black); + s->gcmenufg = XCreateGC(dpy, s->menuwin, gmask, &gv); + + gv.foreground = colorpixel(dpy, s, s->depth, SMENUFGCOL, s->white); + gv.background = colorpixel(dpy, s, s->depth, SMENUBGCOL, s->black); + s->gcmenufgs = XCreateGC(dpy, s->menuwin, gmask, &gv); + + attrs.border_pixel = s->red; + attrs.background_pixel = colorpixel(dpy, s, s->depth, 0xEEEEEE, s->black); + attrs.colormap = s->def_cmap; + s->sweepwin = XCreateWindow(dpy, s->root, 0, 0, 1, 1, 4, + s->depth, + CopyFromParent, + s->vis, + CWBackPixel | CWBorderPixel | CWColormap, + &attrs + ); +} + +ScreenInfo* +getscreen(Window w) +{ + int i; + + for(i = 0; i < num_screens; i++) + if(screens[i].root == w) + return &screens[i]; + + return 0; +} + +Time +timestamp(void) +{ + XEvent ev; + + if(curtime == CurrentTime){ + XChangeProperty(dpy, screens[0].root, _rio_running, _rio_running, 8, + PropModeAppend, (unsigned char *)"", 0); + XMaskEvent(dpy, PropertyChangeMask, &ev); + curtime = ev.xproperty.time; + } + return curtime; +} + +void +sendcmessage(Window w, Atom a, long x, int isroot, int usemask) +{ + XEvent ev; + int status; + long mask; + + memset(&ev, 0, sizeof(ev)); + ev.xclient.type = ClientMessage; + ev.xclient.window = w; + ev.xclient.message_type = a; + ev.xclient.format = 32; + ev.xclient.data.l[0] = x; + ev.xclient.data.l[1] = timestamp(); + mask = 0; + if(usemask){ + mask |= KeyPressMask; /* seems to be necessary */ + if(isroot) + mask |= SubstructureRedirectMask; /* magic! */ + else + mask |= ExposureMask; /* not really correct but so be it */ + } + status = XSendEvent(dpy, w, False, mask, &ev); + if(status == 0) + fprintf(stderr, "ryudo: sendcmessage failed\n"); +} + +void +sendconfig(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.event = c->window; + ce.window = c->window; + ce.x = c->x; + ce.y = c->y; + ce.width = c->dx; + ce.height = c->dy; + ce.border_width = c->border; + ce.above = None; + ce.override_redirect = 0; + XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent*)&ce); +} + +void +sighandler(void) +{ + signalled = 1; +} + +void +getevent(XEvent *e) +{ + int fd; + fd_set rfds; + struct timeval t; + + if(!signalled){ + if(QLength(dpy) > 0){ + XNextEvent(dpy, e); + return; + } + fd = ConnectionNumber(dpy); + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + t.tv_sec = t.tv_usec = 0; + if(select(fd+1, &rfds, NULL, NULL, &t) == 1){ + XNextEvent(dpy, e); + return; + } + XFlush(dpy); + FD_SET(fd, &rfds); + if(select(fd+1, &rfds, NULL, NULL, NULL) == 1){ + XNextEvent(dpy, e); + return; + } + if(errno != EINTR || !signalled){ + perror("ryudo: select failed"); + exit(1); + } + } + fprintf(stderr, "ryudo: exiting on signal\n"); + cleanup(); + exit(1); +} + +void +cleanup(void) +{ + Client *c, *cc[2], *next; + XWindowChanges wc; + int i; + + /* order of un-reparenting determines final stacking order... */ + cc[0] = cc[1] = 0; + for(c = clients; c; c = next){ + next = c->next; + i = normal(c); + c->next = cc[i]; + cc[i] = c; + } + + for(i = 0; i < 2; i++){ + for(c = cc[i]; c; c = c->next){ + if(!withdrawn(c)){ + XReparentWindow(dpy, c->window, c->screen->root, + c->x, c->y); + } + wc.border_width = c->border; + XConfigureWindow(dpy, c->window, CWBorderWidth, &wc); + } + } + + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, timestamp()); + for(i = 0; i < num_screens; i++) + cmapnofocus(&screens[i]); + XCloseDisplay(dpy); +}
A manage.c

@@ -0,0 +1,476 @@

+/* + * Window management. + */ + +/* + * Copyright (c) 2019 Derek Stevens, 2005 Russ Cox, 1994-1996 David Hogan + * see README for licence details + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/extensions/shape.h> +#include "dat.h" +#include "fns.h" + +int isNew; + +int +manage(Client *c, int mapped) +{ + int fixsize, dohide, doreshape, state; + long msize; + XClassHint class; + XWMHints *hints; + XSetWindowAttributes attrs; + + trace("manage", c, 0); + XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask | KeyPressMask); + + /* Get loads of hints */ + + if(XGetClassHint(dpy, c->window, &class) != 0){ /* ``Success'' */ + c->instance = class.res_name; + c->class = class.res_class; + c->is9term = 0; + if(isNew){ + c->is9term = strstr(c->class, "term") || strstr(c->class, "Term") || strstr (c->class, "urxvt") || strstr (c->class, "URxvt"); + isNew = 0; + } + } + else { + c->instance = 0; + c->class = 0; + c->is9term = 0; + } + c->iconname = getprop(c->window, XA_WM_ICON_NAME); + c->name = getprop(c->window, XA_WM_NAME); + setlabel(c); + + hints = XGetWMHints(dpy, c->window); + if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0) + c->size.flags = PSize; /* not specified - punt */ + + getcmaps(c); + getproto(c); + gettrans(c); + if(c->is9term) + c->hold = getiprop(c->window, _rio_hold_mode); + + /* Figure out what to do with the window from hints */ + + if(!getstate(c->window, &state)) + state = hints ? hints->initial_state : NormalState; + dohide = (state == IconicState); + + fixsize = 0; + if((c->size.flags & (USSize|PSize))) + fixsize = 1; + if((c->size.flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize) && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height) + fixsize = 1; + doreshape = !mapped; + if(fixsize){ + if(c->size.flags & USPosition) + doreshape = 0; + if(dohide && (c->size.flags & PPosition)) + doreshape = 0; + if(c->trans != None) + doreshape = 0; + } + if(c->is9term) + fixsize = 0; + if(c->size.flags & PBaseSize){ + c->min_dx = c->size.base_width; + c->min_dy = c->size.base_height; + } + else if(c->size.flags & PMinSize){ + c->min_dx = c->size.min_width; + c->min_dy = c->size.min_height; + } + else if(c->is9term){ + c->min_dx = 100; + c->min_dy = 50; + } + else + c->min_dx = c->min_dy = 0; + + if(hints) + XFree(hints); + + /* Now do it!!! */ + + if(doreshape){ + if(0) fprintf(stderr, "in doreshape is9term=%d fixsize=%d, x=%d, y=%d, min_dx=%d, min_dy=%d, dx=%d, dy=%d\n", + c->is9term, fixsize, c->x, c->y, c->min_dx, c->min_dy, c->dx, c->dy); + if(current && current->screen == c->screen) + cmapnofocus(c->screen); + if(!c->is9term && c->x==0 && c->y==0){ + static int nwin; + + c->x = 20*nwin+BORDER; + c->y = 20*nwin+BORDER; + nwin++; + nwin %= 10; + } + + if(c->is9term && !(fixsize ? drag(c, Button3) : sweep(c, Button3))){ + XKillClient(dpy, c->window); + rmclient(c); + if(current && current->screen == c->screen) + cmapfocus(current); + return 0; + } + } + + attrs.border_pixel = c->screen->black; + attrs.background_pixel = c->screen->white; + attrs.colormap = c->screen->def_cmap; + c->parent = XCreateWindow(dpy, c->screen->root, + c->x - BORDER, c->y - BORDER, + c->dx + 2*BORDER, c->dy + 2*BORDER, + 0, + c->screen->depth, + CopyFromParent, + c->screen->vis, + CWBackPixel | CWBorderPixel | CWColormap, + &attrs); + + XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask|ButtonPressMask| PointerMotionMask|LeaveWindowMask|KeyPressMask); + if(mapped) + c->reparenting = 1; + if(doreshape && !fixsize) + XResizeWindow(dpy, c->window, c->dx, c->dy); + XSetWindowBorderWidth(dpy, c->window, 0); + + /* + * To have something more than only a big white or black border + * XXX should replace this by a pattern in the white or black + * such that we can see the border also if all our + * windows are black and/or white + * (black (or white) border around black (or white) window + * is not very helpful. + */ + if(c->screen->depth <= 8){ + XSetWindowBorderWidth(dpy, c->parent, 1); + } + + XReparentWindow(dpy, c->window, c->parent, BORDER, BORDER); +#ifdef SHAPE + if(shape){ + XShapeSelectInput(dpy, c->window, ShapeNotifyMask); + ignore_badwindow = 1; /* magic */ + setshape(c); + ignore_badwindow = 0; + } +#endif + XAddToSaveSet(dpy, c->window); + if(dohide) + hide(c); + else { + XMapWindow(dpy, c->window); + XMapWindow(dpy, c->parent); + XUnmapWindow(dpy, c->screen->sweepwin); + if(nostalgia || doreshape) + active(c); + else if(c->trans != None && current && current->window == c->trans) + active(c); + else + setactive(c, 0); + setstate(c, NormalState); + } + if(current && (current != c)) + cmapfocus(current); + c->init = 1; + + /* + * If we swept the window, let's send a resize event to the + * guy who just got resized. It's not clear whether the apps + * should notice their new size via other means. Try as I might, + * I can't find a way to have them notice during initdraw, so + * I solve the problem this way instead. -rsc + */ + if(c->is9term) + sendconfig(c); + return 1; +} + +void +scanwins(ScreenInfo *s) +{ + unsigned int i, nwins; + Client *c; + Window dw1, dw2, *wins; + XWindowAttributes attr; + + XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins); + for(i = 0; i < nwins; i++){ + XGetWindowAttributes(dpy, wins[i], &attr); + if(attr.override_redirect || wins[i] == s->menuwin) + continue; + c = getclient(wins[i], 1); + if(c != 0 && c->window == wins[i] && !c->init){ + c->x = attr.x; + c->y = attr.y; + c->dx = attr.width; + c->dy = attr.height; + c->border = attr.border_width; + c->screen = s; + c->parent = s->root; + if(attr.map_state == IsViewable) + manage(c, 1); + } + } + XFree((void *) wins); /* cast is to shut stoopid compiler up */ +} + +void +gettrans(Client *c) +{ + Window trans; + + trans = None; + if(XGetTransientForHint(dpy, c->window, &trans) != 0) + c->trans = trans; + else + c->trans = None; +} + +void +withdraw(Client *c) +{ + XUnmapWindow(dpy, c->parent); + XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y); + XRemoveFromSaveSet(dpy, c->window); + setstate(c, WithdrawnState); + + /* flush any errors */ + ignore_badwindow = 1; + XSync(dpy, False); + ignore_badwindow = 0; +} + +static void +installcmap(ScreenInfo *s, Colormap cmap) +{ + if(cmap == None) + XInstallColormap(dpy, s->def_cmap); + else + XInstallColormap(dpy, cmap); +} + +void +cmapfocus(Client *c) +{ + int i, found; + Client *cc; + + if(c == 0) + return; + else if(c->ncmapwins != 0){ + found = 0; + for(i = c->ncmapwins-1; i >= 0; i--){ + installcmap(c->screen, c->wmcmaps[i]); + if(c->cmapwins[i] == c->window) + found++; + } + if(!found) + installcmap(c->screen, c->cmap); + } + else if(c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0) + cmapfocus(cc); + else + installcmap(c->screen, c->cmap); +} + +void +cmapnofocus(ScreenInfo *s) +{ + installcmap(s, None); +} + +void +getcmaps(Client *c) +{ + int n, i; + Window *cw; + XWindowAttributes attr; + + if(!c->init){ + ignore_badwindow = 1; + XGetWindowAttributes(dpy, c->window, &attr); + c->cmap = attr.colormap; + XSync(dpy, False); + ignore_badwindow = 0; + } + + n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (void*)&cw); + if(c->ncmapwins != 0){ + XFree((char *)c->cmapwins); + free((char *)c->wmcmaps); + } + if(n <= 0){ + c->ncmapwins = 0; + return; + } + + c->ncmapwins = n; + c->cmapwins = cw; + + c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap)); + for(i = 0; i < n; i++){ + if(cw[i] == c->window) + c->wmcmaps[i] = c->cmap; + else { + /* flush any errors (e.g., caused by mozilla tabs) */ + ignore_badwindow = 1; + XSelectInput(dpy, cw[i], ColormapChangeMask); + XGetWindowAttributes(dpy, cw[i], &attr); + c->wmcmaps[i] = attr.colormap; + XSync(dpy, False); + ignore_badwindow = 0; + } + } +} + +void +setlabel(Client *c) +{ + char *label, *p; + + if(c->iconname != 0) + label = c->iconname; + else if(c->name != 0) + label = c->name; + else if(c->instance != 0) + label = c->instance; + else if(c->class != 0) + label = c->class; + else + label = "no label"; + if((p = index(label, ':')) != 0) + *p = '\0'; + c->label = label; +} + +#ifdef SHAPE +void +setshape(Client *c) +{ + int n, order; + XRectangle *rect; + + /* don't try to add a border if the window is non-rectangular */ + rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order); + if(n > 1) + XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER, BORDER, + c->window, ShapeBounding, ShapeSet); + XFree((void*)rect); +} +#endif + +int +_getprop(Window w, Atom a, Atom type, long len, unsigned char **p) +{ + Atom real_type; + int format; + unsigned long n, extra; + int status; + + status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p); + if(status != Success || *p == 0) + return -1; + if(n == 0) + XFree((void*) *p); + /* could check real_type, format, extra here... */ + return n; +} + +char * +getprop(Window w, Atom a) +{ + unsigned char *p; + + if(_getprop(w, a, XA_STRING, 100L, &p) <= 0) + return 0; + return (char *)p; +} + +int +get1prop(Window w, Atom a, Atom type) +{ + char **p, *x; + + if(_getprop(w, a, type, 1L, (void*)&p) <= 0) + return 0; + x = *p; + XFree((void*) p); + return (int)(uintptr_t)x; +} + +Window +getwprop(Window w, Atom a) +{ + return get1prop(w, a, XA_WINDOW); +} + +int +getiprop(Window w, Atom a) +{ + return get1prop(w, a, XA_INTEGER); +} + +void +setstate(Client *c, int state) +{ + long data[2]; + + data[0] = (long) state; + data[1] = (long) None; + + c->state = state; + XChangeProperty(dpy, c->window, wm_state, wm_state, 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +getstate(Window w, int *state) +{ + long *p = 0; + + if(_getprop(w, wm_state, wm_state, 2L, (void*)&p) <= 0) + return 0; + + *state = (int) *p; + XFree((char *) p); + return 1; +} + +void +getproto(Client *c) +{ + Atom *p; + int i; + long n; + Window w; + + w = c->window; + c->proto = 0; + if((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (void*)&p)) <= 0) + return; + + for(i = 0; i < n; i++) + if(p[i] == wm_delete) + c->proto |= Pdelete; + else if(p[i] == wm_take_focus) + c->proto |= Ptakefocus; + else if(p[i] == wm_lose_focus) + c->proto |= Plosefocus; + + XFree((char *) p); +}
A mkfile

@@ -0,0 +1,45 @@

+<$PLAN9/src/mkhdr +<|sh /usr/lib/plan9/src/cmd/devdraw/mkwsysrules.sh # for X11 + +RIOFILES=\ + client.$O\ + color.$O\ + cursor.$O\ + error.$O\ + event.$O\ + grab.$O\ + key.$O\ + main.$O\ + manage.$O\ + menu.$O\ + +CFLAGS=$CFLAGS -DDEBUG +HFILES=dat.h fns.h + +TARG=rio xshove + +# need to add lib64 when it exists (on x86-64), but +# Darwin complains about the nonexistant directory +# Bug in mk? "$L64 -lXext" gobbles the space, so +# add trailing slash. +L64=`[ -d $X11/lib64 ] && echo 64; echo` +LDFLAGS=-L$X11/lib$L64/ -lXext -lX11 $LDFLAGS + +<|sh mkriorules.sh + +$O.rio: $RIOFILES + +CFLAGS=$CFLAGS -DSHAPE -DDEBUG_EV -DDEBUG + +$O.xevents: xevents.$O printevent.$O + $LD -o $target $prereq $LDFLAGS + +xevents.$O printevent.$O: printevent.h + +error.$O: showevent/ShowEvent.c + +$O.xshove: xshove.$O + $LD -o $O.xshove xshove.$O -lX11 $LDFLAGS + +ryudo: $O.rio + sh ryudomagic.sh
A mkriorules.sh

@@ -0,0 +1,8 @@

+if [ "x$WSYSTYPE" != xx11 ]; then + echo 'default:V: all' + echo + echo 'all install clean nuke:' + echo ' # WSYSTYPE is not x11, and ryudo is only for x11' + exit 0 +fi +cat $PLAN9/src/mkmany
A patchlevel.h

@@ -0,0 +1,1 @@

+#define PATCHLEVEL 0
A printevent.c

@@ -0,0 +1,986 @@

+/* + * Original code posted to comp.sources.x + * Modifications by Russ Cox <rsc@swtch.com>. + */ + +/* +Path: uunet!wyse!mikew +From: mikew@wyse.wyse.com (Mike Wexler) +Newsgroups: comp.sources.x +Subject: v02i056: subroutine to print events in human readable form, Part01/01 +Message-ID: <1935@wyse.wyse.com> +Date: 22 Dec 88 19:28:25 GMT +Organization: Wyse Technology, San Jose +Lines: 1093 +Approved: mikew@wyse.com + +Submitted-by: richsun!darkstar!ken +Posting-number: Volume 2, Issue 56 +Archive-name: showevent/part01 + + +There are times during debugging when it would be real useful to be able to +print the fields of an event in a human readable form. Too many times I found +myself scrounging around in section 8 of the Xlib manual looking for the valid +fields for the events I wanted to see, then adding printf's to display the +numeric values of the fields, and then scanning through X.h trying to decode +the cryptic detail and state fields. After playing with xev, I decided to +write a couple of standard functions that I could keep in a library and call +on whenever I needed a little debugging verbosity. The first function, +GetType(), is useful for returning the string representation of the type of +an event. The second function, ShowEvent(), is used to display all the fields +of an event in a readable format. The functions are not complicated, in fact, +they are mind-numbingly boring - but that's just the point nobody wants to +spend the time writing functions like this, they just want to have them when +they need them. + +A simple, sample program is included which does little else but to demonstrate +the use of these two functions. These functions have saved me many an hour +during debugging and I hope you find some benefit to these. If you have any +comments, suggestions, improvements, or if you find any blithering errors you +can get it touch with me at the following location: + + ken@richsun.UUCP +*/ + +#include <stdio.h> +#include <X11/Intrinsic.h> +#include <X11/Xproto.h> +#include "printevent.h" + +static char* sep = " "; + +/******************************************************************************/ +/**** Miscellaneous routines to convert values to their string equivalents ****/ +/******************************************************************************/ + +/* Returns the string equivalent of a boolean parameter */ +static char* +TorF(int bool) +{ + switch (bool) { + case True: + return ("True"); + + case False: + return ("False"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a property notify state */ +static char* +PropertyState(int state) +{ + switch (state) { + case PropertyNewValue: + return ("PropertyNewValue"); + + case PropertyDelete: + return ("PropertyDelete"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a visibility notify state */ +static char* +VisibilityState(int state) +{ + switch (state) { + case VisibilityUnobscured: + return ("VisibilityUnobscured"); + + case VisibilityPartiallyObscured: + return ("VisibilityPartiallyObscured"); + + case VisibilityFullyObscured: + return ("VisibilityFullyObscured"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a timestamp */ +static char* +ServerTime(Time time) +{ + unsigned long msec; + unsigned long sec; + unsigned long min; + unsigned long hr; + unsigned long day; + static char buffer[32]; + + msec = time % 1000; + time /= 1000; + sec = time % 60; + time /= 60; + min = time % 60; + time /= 60; + hr = time % 24; + time /= 24; + day = time; + +if(0) + sprintf(buffer, "%lu day%s %02lu:%02lu:%02lu.%03lu", + day, day == 1 ? "" : "(s)", hr, min, sec, msec); + + sprintf(buffer, "%lud%luh%lum%lu.%03lds", day, hr, min, sec, msec); + return (buffer); +} + +/* Simple structure to ease the interpretation of masks */ +typedef struct MaskType MaskType; +struct MaskType +{ + unsigned int value; + char *string; +}; + +/* Returns the string equivalent of a mask of buttons and/or modifier keys */ +static char* +ButtonAndOrModifierState(unsigned int state) +{ + static char buffer[256]; + static MaskType masks[] = { + {Button1Mask, "Button1Mask"}, + {Button2Mask, "Button2Mask"}, + {Button3Mask, "Button3Mask"}, + {Button4Mask, "Button4Mask"}, + {Button5Mask, "Button5Mask"}, + {ShiftMask, "ShiftMask"}, + {LockMask, "LockMask"}, + {ControlMask, "ControlMask"}, + {Mod1Mask, "Mod1Mask"}, + {Mod2Mask, "Mod2Mask"}, + {Mod3Mask, "Mod3Mask"}, + {Mod4Mask, "Mod4Mask"}, + {Mod5Mask, "Mod5Mask"}, + }; + int num_masks = sizeof(masks) / sizeof(MaskType); + int i; + Boolean first = True; + + buffer[0] = 0; + + for (i = 0; i < num_masks; i++) + if (state & masks[i].value) + if (first) { + first = False; + strcpy(buffer, masks[i].string); + } else { + strcat(buffer, " | "); + strcat(buffer, masks[i].string); + } + return (buffer); +} + +/* Returns the string equivalent of a mask of configure window values */ +static char* +ConfigureValueMask(unsigned int valuemask) +{ + static char buffer[256]; + static MaskType masks[] = { + {CWX, "CWX"}, + {CWY, "CWY"}, + {CWWidth, "CWWidth"}, + {CWHeight, "CWHeight"}, + {CWBorderWidth, "CWBorderWidth"}, + {CWSibling, "CWSibling"}, + {CWStackMode, "CWStackMode"}, + }; + int num_masks = sizeof(masks) / sizeof(MaskType); + int i; + Boolean first = True; + + buffer[0] = 0; + + for (i = 0; i < num_masks; i++) + if (valuemask & masks[i].value) + if (first) { + first = False; + strcpy(buffer, masks[i].string); + } else { + strcat(buffer, " | "); + strcat(buffer, masks[i].string); + } + + return (buffer); +} + +/* Returns the string equivalent of a motion hint */ +static char* +IsHint(char is_hint) +{ + switch (is_hint) { + case NotifyNormal: + return ("NotifyNormal"); + + case NotifyHint: + return ("NotifyHint"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of an id or the value "None" */ +static char* +MaybeNone(int value) +{ + static char buffer[16]; + + if (value == None) + return ("None"); + else { + sprintf(buffer, "0x%x", value); + return (buffer); + } +} + +/* Returns the string equivalent of a colormap state */ +static char* +ColormapState(int state) +{ + switch (state) { + case ColormapInstalled: + return ("ColormapInstalled"); + + case ColormapUninstalled: + return ("ColormapUninstalled"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a crossing detail */ +static char* +CrossingDetail(int detail) +{ + switch (detail) { + case NotifyAncestor: + return ("NotifyAncestor"); + + case NotifyInferior: + return ("NotifyInferior"); + + case NotifyVirtual: + return ("NotifyVirtual"); + + case NotifyNonlinear: + return ("NotifyNonlinear"); + + case NotifyNonlinearVirtual: + return ("NotifyNonlinearVirtual"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a focus change detail */ +static char* +FocusChangeDetail(int detail) +{ + switch (detail) { + case NotifyAncestor: + return ("NotifyAncestor"); + + case NotifyInferior: + return ("NotifyInferior"); + + case NotifyVirtual: + return ("NotifyVirtual"); + + case NotifyNonlinear: + return ("NotifyNonlinear"); + + case NotifyNonlinearVirtual: + return ("NotifyNonlinearVirtual"); + + case NotifyPointer: + return ("NotifyPointer"); + + case NotifyPointerRoot: + return ("NotifyPointerRoot"); + + case NotifyDetailNone: + return ("NotifyDetailNone"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a configure detail */ +static char* +ConfigureDetail(int detail) +{ + switch (detail) { + case Above: + return ("Above"); + + case Below: + return ("Below"); + + case TopIf: + return ("TopIf"); + + case BottomIf: + return ("BottomIf"); + + case Opposite: + return ("Opposite"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a grab mode */ +static char* +GrabMode(int mode) +{ + switch (mode) { + case NotifyNormal: + return ("NotifyNormal"); + + case NotifyGrab: + return ("NotifyGrab"); + + case NotifyUngrab: + return ("NotifyUngrab"); + + case NotifyWhileGrabbed: + return ("NotifyWhileGrabbed"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a mapping request */ +static char* +MappingRequest(int request) +{ + switch (request) { + case MappingModifier: + return ("MappingModifier"); + + case MappingKeyboard: + return ("MappingKeyboard"); + + case MappingPointer: + return ("MappingPointer"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a stacking order place */ +static char* +Place(int place) +{ + switch (place) { + case PlaceOnTop: + return ("PlaceOnTop"); + + case PlaceOnBottom: + return ("PlaceOnBottom"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a major code */ +static char* +MajorCode(int code) +{ + static char buffer[32]; + + switch (code) { + case X_CopyArea: + return ("X_CopyArea"); + + case X_CopyPlane: + return ("X_CopyPlane"); + + default: + sprintf(buffer, "0x%x", code); + return (buffer); + } +} + +/* Returns the string equivalent the keycode contained in the key event */ +static char* +Keycode(XKeyEvent *ev) +{ + static char buffer[256]; + KeySym keysym_str; + char *keysym_name; + char string[256]; + + XLookupString(ev, string, 64, &keysym_str, NULL); + + if (keysym_str == NoSymbol) + keysym_name = "NoSymbol"; + else if (!(keysym_name = XKeysymToString(keysym_str))) + keysym_name = "(no name)"; + sprintf(buffer, "%u (keysym 0x%x \"%s\")", + (int)ev->keycode, (int)keysym_str, keysym_name); + return (buffer); +} + +/* Returns the string equivalent of an atom or "None"*/ +static char* +AtomName(Display *dpy, Atom atom) +{ + static char buffer[256]; + char *atom_name; + + if (atom == None) + return ("None"); + + atom_name = XGetAtomName(dpy, atom); + strncpy(buffer, atom_name, 256); + XFree(atom_name); + return (buffer); +} + +/******************************************************************************/ +/**** Routines to print out readable values for the field of various events ***/ +/******************************************************************************/ + +static void +VerbMotion(XMotionEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("root=0x%x%s", (int)ev->root, sep); + printf("subwindow=0x%x%s", (int)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("is_hint=%s%s", IsHint(ev->is_hint), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void +VerbButton(XButtonEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("root=0x%x%s", (int)ev->root, sep); + printf("subwindow=0x%x%s", (int)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("button=%s%s", ButtonAndOrModifierState(ev->button), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void +VerbColormap(XColormapEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("colormap=%s%s", MaybeNone(ev->colormap), sep); + printf("new=%s%s", TorF(ev->new), sep); + printf("state=%s\n", ColormapState(ev->state)); +} + +static void +VerbCrossing(XCrossingEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("root=0x%x%s", (int)ev->root, sep); + printf("subwindow=0x%x%s", (int)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("mode=%s%s", GrabMode(ev->mode), sep); + printf("detail=%s%s", CrossingDetail(ev->detail), sep); + printf("same_screen=%s%s", TorF(ev->same_screen), sep); + printf("focus=%s%s", TorF(ev->focus), sep); + printf("state=%s\n", ButtonAndOrModifierState(ev->state)); +} + +static void +VerbExpose(XExposeEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("count=%d\n", ev->count); +} + +static void +VerbGraphicsExpose(XGraphicsExposeEvent *ev) +{ + printf("drawable=0x%x%s", (int)ev->drawable, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("major_code=%s%s", MajorCode(ev->major_code), sep); + printf("minor_code=%d\n", ev->minor_code); +} + +static void +VerbNoExpose(XNoExposeEvent *ev) +{ + printf("drawable=0x%x%s", (int)ev->drawable, sep); + printf("major_code=%s%s", MajorCode(ev->major_code), sep); + printf("minor_code=%d\n", ev->minor_code); +} + +static void +VerbFocus(XFocusChangeEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("mode=%s%s", GrabMode(ev->mode), sep); + printf("detail=%s\n", FocusChangeDetail(ev->detail)); +} + +static void +VerbKeymap(XKeymapEvent *ev) +{ + int i; + + printf("window=0x%x%s", (int)ev->window, sep); + printf("key_vector="); + for (i = 0; i < 32; i++) + printf("%02x", ev->key_vector[i]); + printf("\n"); +} + +static void +VerbKey(XKeyEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("root=0x%x%s", (int)ev->root, sep); + if(ev->subwindow) + printf("subwindow=0x%x%s", (int)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("[%d,%d]%s", ev->x, ev->y, sep); + printf("root=[%d,%d]%s", ev->x_root, ev->y_root, sep); + if(ev->state) + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("keycode=%s%s", Keycode(ev), sep); + if(!ev->same_screen) + printf("!same_screen", TorF(ev->same_screen)); + printf("\n"); + return; + + printf("window=0x%x%s", (int)ev->window, sep); + printf("root=0x%x%s", (int)ev->root, sep); + printf("subwindow=0x%x%s", (int)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("keycode=%s%s", Keycode(ev), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void +VerbProperty(XPropertyEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("atom=%s%s", AtomName(ev->display, ev->atom), sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("state=%s\n", PropertyState(ev->state)); +} + +static void +VerbResizeRequest(XResizeRequestEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("width=%d height=%d\n", ev->width, ev->height); +} + +static void +VerbCirculate(XCirculateEvent *ev) +{ + printf("event=0x%x%s", (int)ev->event, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("place=%s\n", Place(ev->place)); +} + +static void +VerbConfigure(XConfigureEvent *ev) +{ + printf("event=0x%x%s", (int)ev->event, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("above=%s%s", MaybeNone(ev->above), sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void +VerbCreateWindow(XCreateWindowEvent *ev) +{ + printf("parent=0x%x%s", (int)ev->parent, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void +VerbDestroyWindow(XDestroyWindowEvent *ev) +{ + printf("event=0x%x%s", (int)ev->event, sep); + printf("window=0x%x\n", (int)ev->window); +} + +static void +VerbGravity(XGravityEvent *ev) +{ + printf("event=0x%x%s", (int)ev->event, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("x=%d y=%d\n", ev->x, ev->y); +} + +static void +VerbMap(XMapEvent *ev) +{ + printf("event=0x%x%s", (int)ev->event, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void +VerbReparent(XReparentEvent *ev) +{ + printf("event=0x%x%s", (int)ev->event, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("parent=0x%x%s", (int)ev->parent, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void +VerbUnmap(XUnmapEvent *ev) +{ + printf("event=0x%x%s", (int)ev->event, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("from_configure=%s\n", TorF(ev->from_configure)); +} + +static void +VerbCirculateRequest(XCirculateRequestEvent *ev) +{ + printf("parent=0x%x%s", (int)ev->parent, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("place=%s\n", Place(ev->place)); +} + +static void +VerbConfigureRequest(XConfigureRequestEvent *ev) +{ + printf("parent=0x%x%s", (int)ev->parent, sep); + printf("window=0x%x%s", (int)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("above=%s%s", MaybeNone(ev->above), sep); + printf("detail=%s%s", ConfigureDetail(ev->detail), sep); + printf("value_mask=%s\n", ConfigureValueMask(ev->value_mask)); +} + +static void +VerbMapRequest(XMapRequestEvent *ev) +{ + printf("parent=0x%x%s", (int)ev->parent, sep); + printf("window=0x%x\n", (int)ev->window); +} + +static void +VerbClient(XClientMessageEvent *ev) +{ + int i; + + printf("window=0x%x%s", (int)ev->window, sep); + printf("message_type=%s%s", AtomName(ev->display, ev->message_type), sep); + printf("format=%d\n", ev->format); + printf("data (shown as longs)="); + for (i = 0; i < 5; i++) + printf(" 0x%08lx", ev->data.l[i]); + printf("\n"); +} + +static void +VerbMapping(XMappingEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("request=%s%s", MappingRequest(ev->request), sep); + printf("first_keycode=0x%x%s", ev->first_keycode, sep); + printf("count=0x%x\n", ev->count); +} + +static void +VerbSelectionClear(XSelectionClearEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void +VerbSelection(XSelectionEvent *ev) +{ + printf("requestor=0x%x%s", (int)ev->requestor, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("target=%s%s", AtomName(ev->display, ev->target), sep); + printf("property=%s%s", AtomName(ev->display, ev->property), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void +VerbSelectionRequest(XSelectionRequestEvent *ev) +{ + printf("owner=0x%x%s", (int)ev->owner, sep); + printf("requestor=0x%x%s", (int)ev->requestor, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("target=%s%s", AtomName(ev->display, ev->target), sep); + printf("property=%s%s", AtomName(ev->display, ev->property), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void +VerbVisibility(XVisibilityEvent *ev) +{ + printf("window=0x%x%s", (int)ev->window, sep); + printf("state=%s\n", VisibilityState(ev->state)); +} + +/******************************************************************************/ +/************ Return the string representation for type of an event ***********/ +/******************************************************************************/ + +char *eventtype(XEvent *ev) +{ + static char buffer[20]; + + switch (ev->type) { + case KeyPress: + return ("KeyPress"); + case KeyRelease: + return ("KeyRelease"); + case ButtonPress: + return ("ButtonPress"); + case ButtonRelease: + return ("ButtonRelease"); + case MotionNotify: + return ("MotionNotify"); + case EnterNotify: + return ("EnterNotify"); + case LeaveNotify: + return ("LeaveNotify"); + case FocusIn: + return ("FocusIn"); + case FocusOut: + return ("FocusOut"); + case KeymapNotify: + return ("KeymapNotify"); + case Expose: + return ("Expose"); + case GraphicsExpose: + return ("GraphicsExpose"); + case NoExpose: + return ("NoExpose"); + case VisibilityNotify: + return ("VisibilityNotify"); + case CreateNotify: + return ("CreateNotify"); + case DestroyNotify: + return ("DestroyNotify"); + case UnmapNotify: + return ("UnmapNotify"); + case MapNotify: + return ("MapNotify"); + case MapRequest: + return ("MapRequest"); + case ReparentNotify: + return ("ReparentNotify"); + case ConfigureNotify: + return ("ConfigureNotify"); + case ConfigureRequest: + return ("ConfigureRequest"); + case GravityNotify: + return ("GravityNotify"); + case ResizeRequest: + return ("ResizeRequest"); + case CirculateNotify: + return ("CirculateNotify"); + case CirculateRequest: + return ("CirculateRequest"); + case PropertyNotify: + return ("PropertyNotify"); + case SelectionClear: + return ("SelectionClear"); + case SelectionRequest: + return ("SelectionRequest"); + case SelectionNotify: + return ("SelectionNotify"); + case ColormapNotify: + return ("ColormapNotify"); + case ClientMessage: + return ("ClientMessage"); + case MappingNotify: + return ("MappingNotify"); + } + sprintf(buffer, "%d", ev->type); + return buffer; +} + +/******************************************************************************/ +/**************** Print the values of all fields for any event ****************/ +/******************************************************************************/ + +void printevent(XEvent *e) +{ + XAnyEvent *ev = (void*)e; + + printf("%3ld %-20s ", ev->serial, eventtype(e)); + if(ev->send_event) + printf("(sendevent) "); + if(0){ + printf("type=%s%s", eventtype(e), sep); + printf("serial=%lu%s", ev->serial, sep); + printf("send_event=%s%s", TorF(ev->send_event), sep); + printf("display=0x%p%s", ev->display, sep); + } + + switch (ev->type) { + case MotionNotify: + VerbMotion((void*)ev); + break; + + case ButtonPress: + case ButtonRelease: + VerbButton((void*)ev); + break; + + case ColormapNotify: + VerbColormap((void*)ev); + break; + + case EnterNotify: + case LeaveNotify: + VerbCrossing((void*)ev); + break; + + case Expose: + VerbExpose((void*)ev); + break; + + case GraphicsExpose: + VerbGraphicsExpose((void*)ev); + break; + + case NoExpose: + VerbNoExpose((void*)ev); + break; + + case FocusIn: + case FocusOut: + VerbFocus((void*)ev); + break; + + case KeymapNotify: + VerbKeymap((void*)ev); + break; + + case KeyPress: + case KeyRelease: + VerbKey((void*)ev); + break; + + case PropertyNotify: + VerbProperty((void*)ev); + break; + + case ResizeRequest: + VerbResizeRequest((void*)ev); + break; + + case CirculateNotify: + VerbCirculate((void*)ev); + break; + + case ConfigureNotify: + VerbConfigure((void*)ev); + break; + + case CreateNotify: + VerbCreateWindow((void*)ev); + break; + + case DestroyNotify: + VerbDestroyWindow((void*)ev); + break; + + case GravityNotify: + VerbGravity((void*)ev); + break; + + case MapNotify: + VerbMap((void*)ev); + break; + + case ReparentNotify: + VerbReparent((void*)ev); + break; + + case UnmapNotify: + VerbUnmap((void*)ev); + break; + + case CirculateRequest: + VerbCirculateRequest((void*)ev); + break; + + case ConfigureRequest: + VerbConfigureRequest((void*)ev); + break; + + case MapRequest: + VerbMapRequest((void*)ev); + break; + + case ClientMessage: + VerbClient((void*)ev); + break; + + case MappingNotify: + VerbMapping((void*)ev); + break; + + case SelectionClear: + VerbSelectionClear((void*)ev); + break; + + case SelectionNotify: + VerbSelection((void*)ev); + break; + + case SelectionRequest: + VerbSelectionRequest((void*)ev); + break; + + case VisibilityNotify: + VerbVisibility((void*)ev); + break; + } +} +
A printevent.h

@@ -0,0 +1,2 @@

+char *eventtype(XEvent*); +void printevent(XEvent*);
A rio.c

@@ -0,0 +1,4 @@

+// nothing to see here, but OS X Lion nm complains +// about object files with nothing + +int something_to_quiet_lion_nm = 1;
A ryudomagic.sh

@@ -0,0 +1,1 @@

+mv $O.rio ryudo
A showevent/Makefile

@@ -0,0 +1,13 @@

+CFLAGS = -g +INCLUDE = -I/global/include +LFLAGS = -L/global/lib +OBJS = ShowEvent.o sample.o +LIBS = -lX11 + +all: sample + +.c.o: + $(CC) $(INCLUDE) $(CFLAGS) -c $< + +sample: $(OBJS) + $(CC) $(LFLAGS) $(OBJS) $(LIBS) -o sample
A showevent/ShowEvent.c

@@ -0,0 +1,888 @@

+#include <X11/Intrinsic.h> +#include <X11/Xproto.h> + +Boolean use_separate_lines = True; +static char *sep; + +/******************************************************************************/ +/**** Miscellaneous routines to convert values to their string equivalents ****/ +/******************************************************************************/ + +/* Returns the string equivalent of a boolean parameter */ +static char *TorF(bool) +int bool; +{ + switch (bool) { + case True: + return ("True"); + + case False: + return ("False"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a property notify state */ +static char *PropertyState(state) +int state; +{ + switch (state) { + case PropertyNewValue: + return ("PropertyNewValue"); + + case PropertyDelete: + return ("PropertyDelete"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a visibility notify state */ +static char *VisibilityState(state) +int state; +{ + switch (state) { + case VisibilityUnobscured: + return ("VisibilityUnobscured"); + + case VisibilityPartiallyObscured: + return ("VisibilityPartiallyObscured"); + + case VisibilityFullyObscured: + return ("VisibilityFullyObscured"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a timestamp */ +static char *ServerTime(time) +Time time; +{ + unsigned long msec; + unsigned long sec; + unsigned long min; + unsigned long hr; + unsigned long day; + static char buffer[32]; + + msec = time % 1000; + time /= 1000; + sec = time % 60; + time /= 60; + min = time % 60; + time /= 60; + hr = time % 24; + time /= 24; + day = time; + + sprintf(buffer, "%ld day%s %02ld:%02ld:%02ld.%03ld", + day, day == 1 ? "" : "(s)", hr, min, sec, msec); + return (buffer); +} + +/* Simple structure to ease the interpretation of masks */ +typedef struct _MaskType { + unsigned int value; + char *string; +} MaskType; + +/* Returns the string equivalent of a mask of buttons and/or modifier keys */ +static char *ButtonAndOrModifierState(state) +unsigned int state; +{ + static char buffer[256]; + static MaskType masks[] = { + {Button1Mask, "Button1Mask"}, + {Button2Mask, "Button2Mask"}, + {Button3Mask, "Button3Mask"}, + {Button4Mask, "Button4Mask"}, + {Button5Mask, "Button5Mask"}, + {ShiftMask, "ShiftMask"}, + {LockMask, "LockMask"}, + {ControlMask, "ControlMask"}, + {Mod1Mask, "Mod1Mask"}, + {Mod2Mask, "Mod2Mask"}, + {Mod3Mask, "Mod3Mask"}, + {Mod4Mask, "Mod4Mask"}, + {Mod5Mask, "Mod5Mask"}, + }; + int num_masks = sizeof(masks) / sizeof(MaskType); + int i; + Boolean first = True; + + buffer[0] = 0; + + for (i = 0; i < num_masks; i++) + if (state & masks[i].value) + if (first) { + first = False; + strcpy(buffer, masks[i].string); + } else { + strcat(buffer, " | "); + strcat(buffer, masks[i].string); + } + return (buffer); +} + +/* Returns the string equivalent of a mask of configure window values */ +static char *ConfigureValueMask(valuemask) +unsigned int valuemask; +{ + static char buffer[256]; + static MaskType masks[] = { + {CWX, "CWX"}, + {CWY, "CWY"}, + {CWWidth, "CWWidth"}, + {CWHeight, "CWHeight"}, + {CWBorderWidth, "CWBorderWidth"}, + {CWSibling, "CWSibling"}, + {CWStackMode, "CWStackMode"}, + }; + int num_masks = sizeof(masks) / sizeof(MaskType); + int i; + Boolean first = True; + + buffer[0] = 0; + + for (i = 0; i < num_masks; i++) + if (valuemask & masks[i].value) + if (first) { + first = False; + strcpy(buffer, masks[i].string); + } else { + strcat(buffer, " | "); + strcat(buffer, masks[i].string); + } + + return (buffer); +} + +/* Returns the string equivalent of a motion hint */ +static char *IsHint(is_hint) +char is_hint; +{ + switch (is_hint) { + case NotifyNormal: + return ("NotifyNormal"); + + case NotifyHint: + return ("NotifyHint"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of an id or the value "None" */ +static char *MaybeNone(value) +int value; +{ + static char buffer[16]; + + if (value == None) + return ("None"); + else { + sprintf(buffer, "0x%x", value); + return (buffer); + } +} + +/* Returns the string equivalent of a colormap state */ +static char *ColormapState(state) +int state; +{ + switch (state) { + case ColormapInstalled: + return ("ColormapInstalled"); + + case ColormapUninstalled: + return ("ColormapUninstalled"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a crossing detail */ +static char *CrossingDetail(detail) +int detail; +{ + switch (detail) { + case NotifyAncestor: + return ("NotifyAncestor"); + + case NotifyInferior: + return ("NotifyInferior"); + + case NotifyVirtual: + return ("NotifyVirtual"); + + case NotifyNonlinear: + return ("NotifyNonlinear"); + + case NotifyNonlinearVirtual: + return ("NotifyNonlinearVirtual"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a focus change detail */ +static char *FocusChangeDetail(detail) +int detail; +{ + switch (detail) { + case NotifyAncestor: + return ("NotifyAncestor"); + + case NotifyInferior: + return ("NotifyInferior"); + + case NotifyVirtual: + return ("NotifyVirtual"); + + case NotifyNonlinear: + return ("NotifyNonlinear"); + + case NotifyNonlinearVirtual: + return ("NotifyNonlinearVirtual"); + + case NotifyPointer: + return ("NotifyPointer"); + + case NotifyPointerRoot: + return ("NotifyPointerRoot"); + + case NotifyDetailNone: + return ("NotifyDetailNone"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a configure detail */ +static char *ConfigureDetail(detail) +int detail; +{ + switch (detail) { + case Above: + return ("Above"); + + case Below: + return ("Below"); + + case TopIf: + return ("TopIf"); + + case BottomIf: + return ("BottomIf"); + + case Opposite: + return ("Opposite"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a grab mode */ +static char *GrabMode(mode) +int mode; +{ + switch (mode) { + case NotifyNormal: + return ("NotifyNormal"); + + case NotifyGrab: + return ("NotifyGrab"); + + case NotifyUngrab: + return ("NotifyUngrab"); + + case NotifyWhileGrabbed: + return ("NotifyWhileGrabbed"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a mapping request */ +static char *MappingRequest(request) +int request; +{ + switch (request) { + case MappingModifier: + return ("MappingModifier"); + + case MappingKeyboard: + return ("MappingKeyboard"); + + case MappingPointer: + return ("MappingPointer"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a stacking order place */ +static char *Place(place) +int place; +{ + switch (place) { + case PlaceOnTop: + return ("PlaceOnTop"); + + case PlaceOnBottom: + return ("PlaceOnBottom"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a major code */ +static char *MajorCode(code) +int code; +{ + static char buffer[32]; + + switch (code) { + case X_CopyArea: + return ("X_CopyArea"); + + case X_CopyPlane: + return ("X_CopyPlane"); + + default: + sprintf(buffer, "0x%x", code); + return (buffer); + } +} + +/* Returns the string equivalent the keycode contained in the key event */ +static char *Keycode(ev) +XKeyEvent *ev; +{ + static char buffer[256]; + KeySym keysym_str; + char *keysym_name; + char string[256]; + + XLookupString(ev, string, 64, &keysym_str, NULL); + + if (keysym_str == NoSymbol) + keysym_name = "NoSymbol"; + else if (!(keysym_name = XKeysymToString(keysym_str))) + keysym_name = "(no name)"; + sprintf(buffer, "%u (keysym 0x%x \"%s\")", + ev->keycode, (unsigned)keysym_str, keysym_name); + return (buffer); +} + +/* Returns the string equivalent of an atom or "None"*/ +static char *AtomName(Display *dpy, Atom atom) +{ + static char buffer[256]; + char *atom_name; + + if (atom == None) + return ("None"); + + atom_name = XGetAtomName(dpy, atom); + strncpy(buffer, atom_name, 256); + XFree(atom_name); + return (buffer); +} + +/******************************************************************************/ +/**** Routines to print out readable values for the field of various events ***/ +/******************************************************************************/ + +static void VerbMotion(XMotionEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("root=0x%x%s", (unsigned)ev->root, sep); + printf("subwindow=0x%x%s", (unsigned)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("is_hint=%s%s", IsHint(ev->is_hint), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void VerbButton(XButtonEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("root=0x%x%s", (unsigned)ev->root, sep); + printf("subwindow=0x%x%s", (unsigned)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("button=%s%s", ButtonAndOrModifierState(ev->button), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void VerbColormap(XColormapEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("colormap=%s%s", MaybeNone(ev->colormap), sep); + printf("new=%s%s", TorF(ev->new), sep); + printf("state=%s\n", ColormapState(ev->state)); +} + +static void VerbCrossing(XCrossingEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("root=0x%x%s", (unsigned)ev->root, sep); + printf("subwindow=0x%x%s", (unsigned)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("mode=%s%s", GrabMode(ev->mode), sep); + printf("detail=%s%s", CrossingDetail(ev->detail), sep); + printf("same_screen=%s%s", TorF(ev->same_screen), sep); + printf("focus=%s%s", TorF(ev->focus), sep); + printf("state=%s\n", ButtonAndOrModifierState(ev->state)); +} + +static void VerbExpose(XExposeEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("count=%d\n", ev->count); +} + +static void VerbGraphicsExpose(XGraphicsExposeEvent *ev) +{ + printf("drawable=0x%x%s", (unsigned)ev->drawable, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("major_code=%s%s", MajorCode(ev->major_code), sep); + printf("minor_code=%d\n", ev->minor_code); +} + +static void VerbNoExpose(XNoExposeEvent *ev) +{ + printf("drawable=0x%x%s", (unsigned)ev->drawable, sep); + printf("major_code=%s%s", MajorCode(ev->major_code), sep); + printf("minor_code=%d\n", ev->minor_code); +} + +static void VerbFocus(XFocusChangeEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("mode=%s%s", GrabMode(ev->mode), sep); + printf("detail=%s\n", FocusChangeDetail(ev->detail)); +} + +static void VerbKeymap(XKeymapEvent *ev) +{ + int i; + + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("key_vector="); + for (i = 0; i < 32; i++) + printf("%02x", ev->key_vector[i]); + printf("\n"); +} + +static void VerbKey(XKeyEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("root=0x%x%s", (unsigned)ev->root, sep); + printf("subwindow=0x%x%s", (unsigned)ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("keycode=%s%s", Keycode(ev), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void VerbProperty(XPropertyEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("atom=%s%s", AtomName(ev->display, ev->atom), sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("state=%s\n", PropertyState(ev->state)); +} + +static void VerbResizeRequest(XResizeRequestEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("width=%d height=%d\n", ev->width, ev->height); +} + +static void VerbCirculate(XCirculateEvent *ev) +{ + printf("event=0x%x%s", (unsigned)ev->event, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("place=%s\n", Place(ev->place)); +} + +static void VerbConfigure(XConfigureEvent *ev) +{ + printf("event=0x%x%s", (unsigned)ev->event, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("above=%s%s", MaybeNone(ev->above), sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbCreateWindow(XCreateWindowEvent *ev) +{ + printf("parent=0x%x%s", (unsigned)ev->parent, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbDestroyWindow(XDestroyWindowEvent *ev) +{ + printf("event=0x%x%s", (unsigned)ev->event, sep); + printf("window=0x%x\n", (unsigned)ev->window); +} + +static void VerbGravity(XGravityEvent *ev) +{ + printf("event=0x%x%s", (unsigned)ev->event, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("x=%d y=%d\n", ev->x, ev->y); +} + +static void VerbMap(XMapEvent *ev) +{ + printf("event=0x%x%s", (unsigned)ev->event, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbReparent(XReparentEvent *ev) +{ + printf("event=0x%x%s", (unsigned)ev->event, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("parent=0x%x%s", (unsigned)ev->parent, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbUnmap(XUnmapEvent *ev) +{ + printf("event=0x%x%s", (unsigned)ev->event, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("from_configure=%s\n", TorF(ev->from_configure)); +} + +static void VerbCirculateRequest(XCirculateRequestEvent *ev) +{ + printf("parent=0x%x%s", (unsigned)ev->parent, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("place=%s\n", Place(ev->place)); +} + +static void VerbConfigureRequest(XConfigureRequestEvent *ev) +{ + printf("parent=0x%x%s", (unsigned)ev->parent, sep); + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("above=%s%s", MaybeNone(ev->above), sep); + printf("detail=%s%s", ConfigureDetail(ev->detail), sep); + printf("value_mask=%s\n", ConfigureValueMask(ev->value_mask)); +} + +static void VerbMapRequest(XMapRequestEvent *ev) +{ + printf("parent=0x%x%s", (unsigned)ev->parent, sep); + printf("window=0x%x\n", (unsigned)ev->window); +} + +static void VerbClient(XClientMessageEvent *ev) +{ + int i; + + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("message_type=%s%s", AtomName(ev->display, ev->message_type), sep); + printf("format=%d\n", ev->format); + printf("data (shown as longs)="); + for (i = 0; i < 5; i++) + printf(" 0x%08lx", ev->data.l[i]); + printf("\n"); +} + +static void VerbMapping(XMappingEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("request=%s%s", MappingRequest(ev->request), sep); + printf("first_keycode=0x%x%s", ev->first_keycode, sep); + printf("count=0x%x\n", ev->count); +} + +static void VerbSelectionClear(XSelectionClearEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void VerbSelection(XSelectionEvent *ev) +{ + printf("requestor=0x%x%s", (unsigned)ev->requestor, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("target=%s%s", AtomName(ev->display, ev->target), sep); + printf("property=%s%s", AtomName(ev->display, ev->property), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void VerbSelectionRequest(XSelectionRequestEvent *ev) +{ + printf("owner=0x%x%s", (unsigned)ev->owner, sep); + printf("requestor=0x%x%s", (unsigned)ev->requestor, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("target=%s%s", AtomName(ev->display, ev->target), sep); + printf("property=%s%s", AtomName(ev->display, ev->property), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void VerbVisibility(XVisibilityEvent *ev) +{ + printf("window=0x%x%s", (unsigned)ev->window, sep); + printf("state=%s\n", VisibilityState(ev->state)); +} + +/******************************************************************************/ +/************ Return the string representation for type of an event ***********/ +/******************************************************************************/ + +char *GetType(ev) +XEvent *ev; +{ + switch (ev->type) { + case KeyPress: + return ("KeyPress"); + case KeyRelease: + return ("KeyRelease"); + case ButtonPress: + return ("ButtonPress"); + case ButtonRelease: + return ("ButtonRelease"); + case MotionNotify: + return ("MotionNotify"); + case EnterNotify: + return ("EnterNotify"); + case LeaveNotify: + return ("LeaveNotify"); + case FocusIn: + return ("FocusIn"); + case FocusOut: + return ("FocusOut"); + case KeymapNotify: + return ("KeymapNotify"); + case Expose: + return ("Expose"); + case GraphicsExpose: + return ("GraphicsExpose"); + case NoExpose: + return ("NoExpose"); + case VisibilityNotify: + return ("VisibilityNotify"); + case CreateNotify: + return ("CreateNotify"); + case DestroyNotify: + return ("DestroyNotify"); + case UnmapNotify: + return ("UnmapNotify"); + case MapNotify: + return ("MapNotify"); + case MapRequest: + return ("MapRequest"); + case ReparentNotify: + return ("ReparentNotify"); + case ConfigureNotify: + return ("ConfigureNotify"); + case ConfigureRequest: + return ("ConfigureRequest"); + case GravityNotify: + return ("GravityNotify"); + case ResizeRequest: + return ("ResizeRequest"); + case CirculateNotify: + return ("CirculateNotify"); + case CirculateRequest: + return ("CirculateRequest"); + case PropertyNotify: + return ("PropertyNotify"); + case SelectionClear: + return ("SelectionClear"); + case SelectionRequest: + return ("SelectionRequest"); + case SelectionNotify: + return ("SelectionNotify"); + case ColormapNotify: + return ("ColormapNotify"); + case ClientMessage: + return ("ClientMessage"); + case MappingNotify: + return ("MappingNotify"); + } + return "???"; +} + +/******************************************************************************/ +/**************** Print the values of all fields for any event ****************/ +/******************************************************************************/ + +void ShowEvent(XEvent *eev) +{ + XAnyEvent *ev = (XAnyEvent*)eev; + /* determine which field separator to use */ + if (use_separate_lines) + sep = "\n"; + else + sep = " "; + + printf("type=%s%s", GetType((XEvent*)ev), sep); + printf("serial=%ld%s", ev->serial, sep); + printf("send_event=%s%s", TorF(ev->send_event), sep); + printf("display=0x%p%s", ev->display, sep); + + switch (ev->type) { + case MotionNotify: + VerbMotion((void*)ev); + break; + + case ButtonPress: + case ButtonRelease: + VerbButton((void*)ev); + break; + + case ColormapNotify: + VerbColormap((void*)ev); + break; + + case EnterNotify: + case LeaveNotify: + VerbCrossing((void*)ev); + break; + + case Expose: + VerbExpose((void*)ev); + break; + + case GraphicsExpose: + VerbGraphicsExpose((void*)ev); + break; + + case NoExpose: + VerbNoExpose((void*)ev); + break; + + case FocusIn: + case FocusOut: + VerbFocus((void*)ev); + break; + + case KeymapNotify: + VerbKeymap((void*)ev); + break; + + case KeyPress: + case KeyRelease: + VerbKey((void*)ev); + break; + + case PropertyNotify: + VerbProperty((void*)ev); + break; + + case ResizeRequest: + VerbResizeRequest((void*)ev); + break; + + case CirculateNotify: + VerbCirculate((void*)ev); + break; + + case ConfigureNotify: + VerbConfigure((void*)ev); + break; + + case CreateNotify: + VerbCreateWindow((void*)ev); + break; + + case DestroyNotify: + VerbDestroyWindow((void*)ev); + break; + + case GravityNotify: + VerbGravity((void*)ev); + break; + + case MapNotify: + VerbMap((void*)ev); + break; + + case ReparentNotify: + VerbReparent((void*)ev); + break; + + case UnmapNotify: + VerbUnmap((void*)ev); + break; + + case CirculateRequest: + VerbCirculateRequest((void*)ev); + break; + + case ConfigureRequest: + VerbConfigureRequest((void*)ev); + break; + + case MapRequest: + VerbMapRequest((void*)ev); + break; + + case ClientMessage: + VerbClient((void*)ev); + break; + + case MappingNotify: + VerbMapping((void*)ev); + break; + + case SelectionClear: + VerbSelectionClear((void*)ev); + break; + + case SelectionNotify: + VerbSelection((void*)ev); + break; + + case SelectionRequest: + VerbSelectionRequest((void*)ev); + break; + + case VisibilityNotify: + VerbVisibility((void*)ev); + break; + + } +}
A showevent/ShowEvent.man

@@ -0,0 +1,20 @@

+.TH ShowEvent 3X11 "December 1988" +.SH NAME +.B ShowEvent \- display the fields of an event +.br +.B GetType - get a string representation of an event type + +.SH SYNOPSIS +.B void ShowEvent(event) +.br +.B XEvent *event; +.PP +.B char *GetType(event) +.br +.B XEvent *event; + +.SH DESCRIPTION +ShowEvent displays the fields of the specified event in a readable form. +.PP +GetType returns the string representation of the specified event type. +
A showevent/part01

@@ -0,0 +1,1103 @@

+Path: uunet!wyse!mikew +From: mikew@wyse.wyse.com (Mike Wexler) +Newsgroups: comp.sources.x +Subject: v02i056: subroutine to print events in human readable form, Part01/01 +Message-ID: <1935@wyse.wyse.com> +Date: 22 Dec 88 19:28:25 GMT +Organization: Wyse Technology, San Jose +Lines: 1093 +Approved: mikew@wyse.com + +Submitted-by: richsun!darkstar!ken +Posting-number: Volume 2, Issue 56 +Archive-name: showevent/part01 + + + +Following is a shar file of a debugging aid along with a sample program to +show how it is used. The README contains more details. + + Ken + +#! /bin/sh +# This is a shell archive, meaning: +# 1. Remove everything above the #! /bin/sh line. +# 2. Save the resulting text in a file. +# 3. Execute the file with /bin/sh (not csh) to create the files: +# Makefile +# README +# ShowEvent.c +# ShowEvent.man +# patchlevel.h +# sample.c +# This archive created: Thu Dec 22 12:13:46 1988 +export PATH; PATH=/bin:$PATH +if test -f 'Makefile' +then + echo shar: will not over-write existing file "'Makefile'" +else +cat << \SHAR_EOF > 'Makefile' +CFLAGS = -g +INCLUDE = -I/global/include +LFLAGS = -L/global/lib +OBJS = ShowEvent.o sample.o +LIBS = -lX11 + +all: sample + +.c.o: + $(CC) $(INCLUDE) $(CFLAGS) -c $< + +sample: $(OBJS) + $(CC) $(LFLAGS) $(OBJS) $(LIBS) -o sample +SHAR_EOF +fi # end of overwriting check +if test -f 'README' +then + echo shar: will not over-write existing file "'README'" +else +cat << \SHAR_EOF > 'README' +There are times during debugging when it would be real useful to be able to +print the fields of an event in a human readable form. Too many times I found +myself scrounging around in section 8 of the Xlib manual looking for the valid +fields for the events I wanted to see, then adding printf's to display the +numeric values of the fields, and then scanning through X.h trying to decode +the cryptic detail and state fields. After playing with xev, I decided to +write a couple of standard functions that I could keep in a library and call +on whenever I needed a little debugging verbosity. The first function, +GetType(), is useful for returning the string representation of the type of +an event. The second function, ShowEvent(), is used to display all the fields +of an event in a readable format. The functions are not complicated, in fact, +they are mind-numbingly boring - but that's just the point nobody wants to +spend the time writing functions like this, they just want to have them when +they need them. + +A simple, sample program is included which does little else but to demonstrate +the use of these two functions. These functions have saved me many an hour +during debugging and I hope you find some benefit to these. If you have any +comments, suggestions, improvements, or if you find any blithering errors you +can get it touch with me at the following location: + + ken@richsun.UUCP +SHAR_EOF +fi # end of overwriting check +if test -f 'ShowEvent.c' +then + echo shar: will not over-write existing file "'ShowEvent.c'" +else +cat << \SHAR_EOF > 'ShowEvent.c' +#include <X11/Intrinsic.h> +#include <X11/Xproto.h> + +Boolean use_separate_lines = True; +static char *sep; + +/******************************************************************************/ +/**** Miscellaneous routines to convert values to their string equivalents ****/ +/******************************************************************************/ + +/* Returns the string equivalent of a boolean parameter */ +static char *TorF(bool) +int bool; +{ + switch (bool) { + case True: + return ("True"); + + case False: + return ("False"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a property notify state */ +static char *PropertyState(state) +int state; +{ + switch (state) { + case PropertyNewValue: + return ("PropertyNewValue"); + + case PropertyDelete: + return ("PropertyDelete"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a visibility notify state */ +static char *VisibilityState(state) +int state; +{ + switch (state) { + case VisibilityUnobscured: + return ("VisibilityUnobscured"); + + case VisibilityPartiallyObscured: + return ("VisibilityPartiallyObscured"); + + case VisibilityFullyObscured: + return ("VisibilityFullyObscured"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a timestamp */ +static char *ServerTime(time) +Time time; +{ + unsigned long msec; + unsigned long sec; + unsigned long min; + unsigned long hr; + unsigned long day; + char buffer[32]; + + msec = time % 1000; + time /= 1000; + sec = time % 60; + time /= 60; + min = time % 60; + time /= 60; + hr = time % 24; + time /= 24; + day = time; + + sprintf(buffer, "%d day%s %02d:%02d:%02d.%03d", + day, day == 1 ? "" : "(s)", hr, min, sec, msec); + return (buffer); +} + +/* Simple structure to ease the interpretation of masks */ +typedef struct _MaskType { + unsigned int value; + char *string; +} MaskType; + +/* Returns the string equivalent of a mask of buttons and/or modifier keys */ +static char *ButtonAndOrModifierState(state) +unsigned int state; +{ + char buffer[256]; + static MaskType masks[] = { + {Button1Mask, "Button1Mask"}, + {Button2Mask, "Button2Mask"}, + {Button3Mask, "Button3Mask"}, + {Button4Mask, "Button4Mask"}, + {Button5Mask, "Button5Mask"}, + {ShiftMask, "ShiftMask"}, + {LockMask, "LockMask"}, + {ControlMask, "ControlMask"}, + {Mod1Mask, "Mod1Mask"}, + {Mod2Mask, "Mod2Mask"}, + {Mod3Mask, "Mod3Mask"}, + {Mod4Mask, "Mod4Mask"}, + {Mod5Mask, "Mod5Mask"}, + }; + int num_masks = sizeof(masks) / sizeof(MaskType); + int i; + Boolean first = True; + + buffer[0] = NULL; + + for (i = 0; i < num_masks; i++) + if (state & masks[i].value) + if (first) { + first = False; + strcpy(buffer, masks[i].string); + } else { + strcat(buffer, " | "); + strcat(buffer, masks[i].string); + } + return (buffer); +} + +/* Returns the string equivalent of a mask of configure window values */ +static char *ConfigureValueMask(valuemask) +unsigned int valuemask; +{ + char buffer[256]; + static MaskType masks[] = { + {CWX, "CWX"}, + {CWY, "CWY"}, + {CWWidth, "CWWidth"}, + {CWHeight, "CWHeight"}, + {CWBorderWidth, "CWBorderWidth"}, + {CWSibling, "CWSibling"}, + {CWStackMode, "CWStackMode"}, + }; + int num_masks = sizeof(masks) / sizeof(MaskType); + int i; + Boolean first = True; + + buffer[0] = NULL; + + for (i = 0; i < num_masks; i++) + if (valuemask & masks[i].value) + if (first) { + first = False; + strcpy(buffer, masks[i].string); + } else { + strcat(buffer, " | "); + strcat(buffer, masks[i].string); + } + + return (buffer); +} + +/* Returns the string equivalent of a motion hint */ +static char *IsHint(is_hint) +char is_hint; +{ + switch (is_hint) { + case NotifyNormal: + return ("NotifyNormal"); + + case NotifyHint: + return ("NotifyHint"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of an id or the value "None" */ +static char *MaybeNone(value) +int value; +{ + char buffer[16]; + + if (value == None) + return ("None"); + else { + sprintf(buffer, "0x%x", value); + return (buffer); + } +} + +/* Returns the string equivalent of a colormap state */ +static char *ColormapState(state) +int state; +{ + switch (state) { + case ColormapInstalled: + return ("ColormapInstalled"); + + case ColormapUninstalled: + return ("ColormapUninstalled"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a crossing detail */ +static char *CrossingDetail(detail) +int detail; +{ + switch (detail) { + case NotifyAncestor: + return ("NotifyAncestor"); + + case NotifyInferior: + return ("NotifyInferior"); + + case NotifyVirtual: + return ("NotifyVirtual"); + + case NotifyNonlinear: + return ("NotifyNonlinear"); + + case NotifyNonlinearVirtual: + return ("NotifyNonlinearVirtual"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a focus change detail */ +static char *FocusChangeDetail(detail) +int detail; +{ + switch (detail) { + case NotifyAncestor: + return ("NotifyAncestor"); + + case NotifyInferior: + return ("NotifyInferior"); + + case NotifyVirtual: + return ("NotifyVirtual"); + + case NotifyNonlinear: + return ("NotifyNonlinear"); + + case NotifyNonlinearVirtual: + return ("NotifyNonlinearVirtual"); + + case NotifyPointer: + return ("NotifyPointer"); + + case NotifyPointerRoot: + return ("NotifyPointerRoot"); + + case NotifyDetailNone: + return ("NotifyDetailNone"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a configure detail */ +static char *ConfigureDetail(detail) +int detail; +{ + switch (detail) { + case Above: + return ("Above"); + + case Below: + return ("Below"); + + case TopIf: + return ("TopIf"); + + case BottomIf: + return ("BottomIf"); + + case Opposite: + return ("Opposite"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a grab mode */ +static char *GrabMode(mode) +int mode; +{ + switch (mode) { + case NotifyNormal: + return ("NotifyNormal"); + + case NotifyGrab: + return ("NotifyGrab"); + + case NotifyUngrab: + return ("NotifyUngrab"); + + case NotifyWhileGrabbed: + return ("NotifyWhileGrabbed"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a mapping request */ +static char *MappingRequest(request) +int request; +{ + switch (request) { + case MappingModifier: + return ("MappingModifier"); + + case MappingKeyboard: + return ("MappingKeyboard"); + + case MappingPointer: + return ("MappingPointer"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a stacking order place */ +static char *Place(place) +int place; +{ + switch (place) { + case PlaceOnTop: + return ("PlaceOnTop"); + + case PlaceOnBottom: + return ("PlaceOnBottom"); + + default: + return ("?"); + } +} + +/* Returns the string equivalent of a major code */ +static char *MajorCode(code) +int code; +{ + char buffer[32]; + + switch (code) { + case X_CopyArea: + return ("X_CopyArea"); + + case X_CopyPlane: + return ("X_CopyPlane"); + + default: + sprintf(buffer, "0x%x", code); + return (buffer); + } +} + +/* Returns the string equivalent the keycode contained in the key event */ +static char *Keycode(ev) +XKeyEvent *ev; +{ + char buffer[256]; + KeySym keysym_str; + char *keysym_name; + char string[256]; + + XLookupString(ev, string, 64, &keysym_str, NULL); + + if (keysym_str == NoSymbol) + keysym_name = "NoSymbol"; + else if (!(keysym_name = XKeysymToString(keysym_str))) + keysym_name = "(no name)"; + sprintf(buffer, "%u (keysym 0x%x \"%s\")", + ev->keycode, keysym_str, keysym_name); + return (buffer); +} + +/* Returns the string equivalent of an atom or "None"*/ +static char *AtomName(dpy, atom) +Display *dpy; +Atom atom; +{ + char buffer[256]; + char *atom_name; + + if (atom == None) + return ("None"); + + atom_name = XGetAtomName(dpy, atom); + strncpy(buffer, atom_name, 256); + XFree(atom_name); + return (buffer); +} + +/******************************************************************************/ +/**** Routines to print out readable values for the field of various events ***/ +/******************************************************************************/ + +static void VerbMotion(ev) +XMotionEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("root=0x%x%s", ev->root, sep); + printf("subwindow=0x%x%s", ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("is_hint=%s%s", IsHint(ev->is_hint), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void VerbButton(ev) +XButtonEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("root=0x%x%s", ev->root, sep); + printf("subwindow=0x%x%s", ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("button=%s%s", ButtonAndOrModifierState(ev->button), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void VerbColormap(ev) +XColormapEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("colormap=%s%s", MaybeNone(ev->colormap), sep); + printf("new=%s%s", TorF(ev->new), sep); + printf("state=%s\n", ColormapState(ev->state)); +} + +static void VerbCrossing(ev) +XCrossingEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("root=0x%x%s", ev->root, sep); + printf("subwindow=0x%x%s", ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("mode=%s%s", GrabMode(ev->mode), sep); + printf("detail=%s%s", CrossingDetail(ev->detail), sep); + printf("same_screen=%s%s", TorF(ev->same_screen), sep); + printf("focus=%s%s", TorF(ev->focus), sep); + printf("state=%s\n", ButtonAndOrModifierState(ev->state)); +} + +static void VerbExpose(ev) +XExposeEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("count=%d\n", ev->count); +} + +static void VerbGraphicsExpose(ev) +XGraphicsExposeEvent *ev; +{ + printf("drawable=0x%x%s", ev->drawable, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("major_code=%s%s", MajorCode(ev->major_code), sep); + printf("minor_code=%d\n", ev->minor_code); +} + +static void VerbNoExpose(ev) +XNoExposeEvent *ev; +{ + printf("drawable=0x%x%s", ev->drawable, sep); + printf("major_code=%s%s", MajorCode(ev->major_code), sep); + printf("minor_code=%d\n", ev->minor_code); +} + +static void VerbFocus(ev) +XFocusChangeEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("mode=%s%s", GrabMode(ev->mode), sep); + printf("detail=%s\n", FocusChangeDetail(ev->detail)); +} + +static void VerbKeymap(ev) +XKeymapEvent *ev; +{ + int i; + + printf("window=0x%x%s", ev->window, sep); + printf("key_vector="); + for (i = 0; i < 32; i++) + printf("%02x", ev->key_vector[i]); + printf("\n"); +} + +static void VerbKey(ev) +XKeyEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("root=0x%x%s", ev->root, sep); + printf("subwindow=0x%x%s", ev->subwindow, sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep); + printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep); + printf("keycode=%s%s", Keycode(ev), sep); + printf("same_screen=%s\n", TorF(ev->same_screen)); +} + +static void VerbProperty(ev) +XPropertyEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("atom=%s%s", AtomName(ev->display, ev->atom), sep); + printf("time=%s%s", ServerTime(ev->time), sep); + printf("state=%s\n", PropertyState(ev->state)); +} + +static void VerbResizeRequest(ev) +XResizeRequestEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("width=%d height=%d\n", ev->width, ev->height); +} + +static void VerbCirculate(ev) +XCirculateEvent *ev; +{ + printf("event=0x%x%s", ev->event, sep); + printf("window=0x%x%s", ev->window, sep); + printf("place=%s\n", Place(ev->place)); +} + +static void VerbConfigure(ev) +XConfigureEvent *ev; +{ + printf("event=0x%x%s", ev->event, sep); + printf("window=0x%x%s", ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("above=%s%s", MaybeNone(ev->above), sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbCreateWindow(ev) +XCreateWindowEvent *ev; +{ + printf("parent=0x%x%s", ev->parent, sep); + printf("window=0x%x%s", ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbDestroyWindow(ev) +XDestroyWindowEvent *ev; +{ + printf("event=0x%x%s", ev->event, sep); + printf("window=0x%x\n", ev->window); +} + +static void VerbGravity(ev) +XGravityEvent *ev; +{ + printf("event=0x%x%s", ev->event, sep); + printf("window=0x%x%s", ev->window, sep); + printf("x=%d y=%d\n", ev->x, ev->y); +} + +static void VerbMap(ev) +XMapEvent *ev; +{ + printf("event=0x%x%s", ev->event, sep); + printf("window=0x%x%s", ev->window, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbReparent(ev) +XReparentEvent *ev; +{ + printf("event=0x%x%s", ev->event, sep); + printf("window=0x%x%s", ev->window, sep); + printf("parent=0x%x%s", ev->parent, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("override_redirect=%s\n", TorF(ev->override_redirect)); +} + +static void VerbUnmap(ev) +XUnmapEvent *ev; +{ + printf("event=0x%x%s", ev->event, sep); + printf("window=0x%x%s", ev->window, sep); + printf("from_configure=%s\n", TorF(ev->from_configure)); +} + +static void VerbCirculateRequest(ev) +XCirculateRequestEvent *ev; +{ + printf("parent=0x%x%s", ev->parent, sep); + printf("window=0x%x%s", ev->window, sep); + printf("place=%s\n", Place(ev->place)); +} + +static void VerbConfigureRequest(ev) +XConfigureRequestEvent *ev; +{ + printf("parent=0x%x%s", ev->parent, sep); + printf("window=0x%x%s", ev->window, sep); + printf("x=%d y=%d%s", ev->x, ev->y, sep); + printf("width=%d height=%d%s", ev->width, ev->height, sep); + printf("border_width=%d%s", ev->border_width, sep); + printf("above=%s%s", MaybeNone(ev->above), sep); + printf("detail=0x%x%s", ConfigureDetail(ev->detail), sep); + printf("value_mask=%s\n", ConfigureValueMask(ev->value_mask)); +} + +static void VerbMapRequest(ev) +XMapRequestEvent *ev; +{ + printf("parent=0x%x%s", ev->parent, sep); + printf("window=0x%x\n", ev->window); +} + +static void VerbClient(ev) +XClientMessageEvent *ev; +{ + int i; + + printf("window=0x%x%s", ev->window, sep); + printf("message_type=%s%s", AtomName(ev->display, ev->message_type), sep); + printf("format=%d\n", ev->format); + printf("data (shown as longs)="); + for (i = 0; i < 5; i++) + printf(" 0x%08x", ev->data.l[i]); + printf("\n"); +} + +static void VerbMapping(ev) +XMappingEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("request=0x%x%s", MappingRequest(ev->request), sep); + printf("first_keycode=0x%x%s", ev->first_keycode, sep); + printf("count=0x%x\n", ev->count); +} + +static void VerbSelectionClear(ev) +XSelectionClearEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void VerbSelection(ev) +XSelectionEvent *ev; +{ + printf("requestor=0x%x%s", ev->requestor, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("target=%s%s", AtomName(ev->display, ev->target), sep); + printf("property=%s%s", AtomName(ev->display, ev->property), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void VerbSelectionRequest(ev) +XSelectionRequestEvent *ev; +{ + printf("owner=0x%x%s", ev->owner, sep); + printf("requestor=0x%x%s", ev->requestor, sep); + printf("selection=%s%s", AtomName(ev->display, ev->selection), sep); + printf("target=%s%s", AtomName(ev->display, ev->target), sep); + printf("property=%s%s", AtomName(ev->display, ev->property), sep); + printf("time=%s\n", ServerTime(ev->time)); +} + +static void VerbVisibility(ev) +XVisibilityEvent *ev; +{ + printf("window=0x%x%s", ev->window, sep); + printf("state=%s\n", VisibilityState(ev->state)); +} + +/******************************************************************************/ +/************ Return the string representation for type of an event ***********/ +/******************************************************************************/ + +char *GetType(ev) +XEvent *ev; +{ + switch (ev->type) { + case KeyPress: + return ("KeyPress"); + case KeyRelease: + return ("KeyRelease"); + case ButtonPress: + return ("ButtonPress"); + case ButtonRelease: + return ("ButtonRelease"); + case MotionNotify: + return ("MotionNotify"); + case EnterNotify: + return ("EnterNotify"); + case LeaveNotify: + return ("LeaveNotify"); + case FocusIn: + return ("FocusIn"); + case FocusOut: + return ("FocusOut"); + case KeymapNotify: + return ("KeymapNotify"); + case Expose: + return ("Expose"); + case GraphicsExpose: + return ("GraphicsExpose"); + case NoExpose: + return ("NoExpose"); + case VisibilityNotify: + return ("VisibilityNotify"); + case CreateNotify: + return ("CreateNotify"); + case DestroyNotify: + return ("DestroyNotify"); + case UnmapNotify: + return ("UnmapNotify"); + case MapNotify: + return ("MapNotify"); + case MapRequest: + return ("MapRequest"); + case ReparentNotify: + return ("ReparentNotify"); + case ConfigureNotify: + return ("ConfigureNotify"); + case ConfigureRequest: + return ("ConfigureRequest"); + case GravityNotify: + return ("GravityNotify"); + case ResizeRequest: + return ("ResizeRequest"); + case CirculateNotify: + return ("CirculateNotify"); + case CirculateRequest: + return ("CirculateRequest"); + case PropertyNotify: + return ("PropertyNotify"); + case SelectionClear: + return ("SelectionClear"); + case SelectionRequest: + return ("SelectionRequest"); + case SelectionNotify: + return ("SelectionNotify"); + case ColormapNotify: + return ("ColormapNotify"); + case ClientMessage: + return ("ClientMessage"); + case MappingNotify: + return ("MappingNotify"); + } +} + +/******************************************************************************/ +/**************** Print the values of all fields for any event ****************/ +/******************************************************************************/ + +void ShowEvent(ev) +XAnyEvent *ev; +{ + /* determine which field separator to use */ + if (use_separate_lines) + sep = "\n"; + else + sep = " "; + + printf("type=%s%s", GetType(ev), sep); + printf("serial=%d%s", ev->serial, sep); + printf("send_event=%s%s", TorF(ev->send_event), sep); + printf("display=0x%x%s", ev->display, sep); + + switch (ev->type) { + case MotionNotify: + VerbMotion(ev); + break; + + case ButtonPress: + case ButtonRelease: + VerbButton(ev); + break; + + case ColormapNotify: + VerbColormap(ev); + break; + + case EnterNotify: + case LeaveNotify: + VerbCrossing(ev); + break; + + case Expose: + VerbExpose(ev); + break; + + case GraphicsExpose: + VerbGraphicsExpose(ev); + break; + + case NoExpose: + VerbNoExpose(ev); + break; + + case FocusIn: + case FocusOut: + VerbFocus(ev); + break; + + case KeymapNotify: + VerbKeymap(ev); + break; + + case KeyPress: + case KeyRelease: + VerbKey(ev); + break; + + case PropertyNotify: + VerbProperty(ev); + break; + + case ResizeRequest: + VerbResizeRequest(ev); + break; + + case CirculateNotify: + VerbCirculate(ev); + break; + + case ConfigureNotify: + VerbConfigure(ev); + break; + + case CreateNotify: + VerbCreateWindow(ev); + break; + + case DestroyNotify: + VerbDestroyWindow(ev); + break; + + case GravityNotify: + VerbGravity(ev); + break; + + case MapNotify: + VerbMap(ev); + break; + + case ReparentNotify: + VerbReparent(ev); + break; + + case UnmapNotify: + VerbUnmap(ev); + break; + + case CirculateRequest: + VerbCirculateRequest(ev); + break; + + case ConfigureRequest: + VerbConfigureRequest(ev); + break; + + case MapRequest: + VerbMapRequest(ev); + break; + + case ClientMessage: + VerbClient(ev); + break; + + case MappingNotify: + VerbMapping(ev); + break; + + case SelectionClear: + VerbSelectionClear(ev); + break; + + case SelectionNotify: + VerbSelection(ev); + break; + + case SelectionRequest: + VerbSelectionRequest(ev); + break; + + case VisibilityNotify: + VerbVisibility(ev); + break; + + } +} +SHAR_EOF +fi # end of overwriting check +if test -f 'ShowEvent.man' +then + echo shar: will not over-write existing file "'ShowEvent.man'" +else +cat << \SHAR_EOF > 'ShowEvent.man' +.TH ShowEvent 3X11 "December 1988" +.SH NAME +.B ShowEvent \- display the fields of an event +.br +.B GetType - get a string representation of an event type + +.SH SYNOPSIS +.B void ShowEvent(event) +.br +.B XEvent *event; +.PP +.B char *GetType(event) +.br +.B XEvent *event; + +.SH DESCRIPTION +ShowEvent displays the fields of the specified event in a readable form. +.PP +GetType returns the string representation of the specified event type. + +SHAR_EOF +fi # end of overwriting check +if test -f 'patchlevel.h' +then + echo shar: will not over-write existing file "'patchlevel.h'" +else +cat << \SHAR_EOF > 'patchlevel.h' +#define PATCHLEVEL 0 +SHAR_EOF +fi # end of overwriting check +if test -f 'sample.c' +then + echo shar: will not over-write existing file "'sample.c'" +else +cat << \SHAR_EOF > 'sample.c' +#include <X11/Intrinsic.h> + +/* + * Disclaimer: No I don't actually code like this but this is a simple, + * "Quick-n-Dirty", plain, vanilla, "No ups, No extras" piece of code. + */ + +main(argc, argv) +int argc; +char **argv; +{ + Display *dpy; + int screen; + Window window; + XEvent event; + extern Boolean use_separate_lines; + + if (!(dpy = XOpenDisplay(""))) { + printf("Failed to open display...\n"); + exit(1); + } + screen = DefaultScreen(dpy); + + window = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), 100, 100, + 300, 200, 2, BlackPixel(dpy, screen), WhitePixel(dpy, screen)); + + XSelectInput(dpy, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | + ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | PointerMotionHintMask | Button1MotionMask | + Button2MotionMask | Button3MotionMask | Button4MotionMask | + Button5MotionMask | ButtonMotionMask | KeymapStateMask | + ExposureMask | VisibilityChangeMask | StructureNotifyMask | + SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | + PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask); + + XMapWindow(dpy, window); + + /* set this to false to make ShowEvent take up less vertival space */ + use_separate_lines = True; + + while (1) { + XNextEvent(dpy, &event); + printf("Detail of %s event:\n", GetType(&event)); + ShowEvent(&event); + printf("\n\n"); + } +} + +SHAR_EOF +fi # end of overwriting check +# End of shell archive +exit 0 +-- +Mike Wexler(wyse!mikew) Phone: (408)433-1000 x1330 +Moderator of comp.sources.x
A showevent/patchlevel.h

@@ -0,0 +1,1 @@

+#define PATCHLEVEL 0
A showevent/readme

@@ -0,0 +1,28 @@

+I have edited this code to work on modern compilers. + +Russ Cox + +--- + +There are times during debugging when it would be real useful to be able to +print the fields of an event in a human readable form. Too many times I found +myself scrounging around in section 8 of the Xlib manual looking for the valid +fields for the events I wanted to see, then adding printf's to display the +numeric values of the fields, and then scanning through X.h trying to decode +the cryptic detail and state fields. After playing with xev, I decided to +write a couple of standard functions that I could keep in a library and call +on whenever I needed a little debugging verbosity. The first function, +GetType(), is useful for returning the string representation of the type of +an event. The second function, ShowEvent(), is used to display all the fields +of an event in a readable format. The functions are not complicated, in fact, +they are mind-numbingly boring - but that's just the point nobody wants to +spend the time writing functions like this, they just want to have them when +they need them. + +A simple, sample program is included which does little else but to demonstrate +the use of these two functions. These functions have saved me many an hour +during debugging and I hope you find some benefit to these. If you have any +comments, suggestions, improvements, or if you find any blithering errors you +can get it touch with me at the following location: + + ken@richsun.UUCP
A showevent/sample.c

@@ -0,0 +1,48 @@

+#include <X11/Intrinsic.h> + +/* + * Disclaimer: No I don't actually code like this but this is a simple, + * "Quick-n-Dirty", plain, vanilla, "No ups, No extras" piece of code. + */ + +main(argc, argv) +int argc; +char **argv; +{ + Display *dpy; + int screen; + Window window; + XEvent event; + extern Boolean use_separate_lines; + + if (!(dpy = XOpenDisplay(""))) { + printf("Failed to open display...\n"); + exit(1); + } + screen = DefaultScreen(dpy); + + window = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), 100, 100, + 300, 200, 2, BlackPixel(dpy, screen), WhitePixel(dpy, screen)); + + XSelectInput(dpy, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | + ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | PointerMotionHintMask | Button1MotionMask | + Button2MotionMask | Button3MotionMask | Button4MotionMask | + Button5MotionMask | ButtonMotionMask | KeymapStateMask | + ExposureMask | VisibilityChangeMask | StructureNotifyMask | + SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | + PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask); + + XMapWindow(dpy, window); + + /* set this to false to make ShowEvent take up less vertival space */ + use_separate_lines = True; + + while (1) { + XNextEvent(dpy, &event); + printf("Detail of %s event:\n", GetType(&event)); + ShowEvent(&event); + printf("\n\n"); + } +} +
A xevents.c

@@ -0,0 +1,45 @@

+/* + * Original code posted to comp.sources.x (see printevent.c). + * Modifications by Russ Cox <rsc@swtch.com>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Intrinsic.h> +#include "printevent.h" + +int +main(int argc, char **argv) +{ + int screen; + Display *dpy; + Window window; + XEvent event; + + if (!(dpy = XOpenDisplay(""))) { + printf("Failed to open display...\n"); + exit(1); + } + + screen = DefaultScreen(dpy); + + window = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), 100, 100, + 300, 200, 2, BlackPixel(dpy, screen), WhitePixel(dpy, screen)); + + XSelectInput(dpy, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | + ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | PointerMotionHintMask | Button1MotionMask | + Button2MotionMask | Button3MotionMask | Button4MotionMask | + Button5MotionMask | ButtonMotionMask | KeymapStateMask | + ExposureMask | VisibilityChangeMask | StructureNotifyMask | + SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | + PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask); + + XMapWindow(dpy, window); + + for(;;){ + XNextEvent(dpy, &event); + printevent(&event); + } +} +
A xshove.c

@@ -0,0 +1,318 @@

+#include <u.h> +#include <X11/X.h> +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <libc.h> +#include <ctype.h> + +AUTOLIB(X11); + +typedef struct Rectangle Rectangle; +struct Rectangle +{ + struct { + int x; + int y; + } min, max; +}; +#define Dx(r) ((r).max.x - (r).min.x) +#define Dy(r) ((r).max.y - (r).min.y) + +typedef struct Win Win; +struct Win +{ + Window xw; + int x; + int y; + int dx; + int dy; + char *class; + char *instance; + char *name; + char *iconname; +}; + +Display *dpy; +Window root; + +Win *w; +int nw; + +void getinfo(void); +void listwindows(void); +int parsewinsize(char*, Rectangle*, int*, int*, int*); +void shove(char*, char*); + +void +usage(void) +{ + fprint(2, "usage: xshove [window rectangle]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int screen; + + screen = 0; + ARGBEGIN{ + case 's': + screen = atoi(EARGF(usage())); + break; + default: + usage(); + break; + }ARGEND + + dpy = XOpenDisplay(""); + if(dpy == nil) + sysfatal("open display: %r"); + + root = RootWindow(dpy, screen); + getinfo(); + + if(argc == 0){ + listwindows(); + exits(0); + } + if(argc != 2) + usage(); + shove(argv[0], argv[1]); + exits(0); +} + +char* +getproperty(Window w, Atom a) +{ + uchar *p; + int fmt; + Atom type; + ulong n, dummy; + + n = 100; + p = nil; + XGetWindowProperty(dpy, w, a, 0, 100L, 0, + AnyPropertyType, &type, &fmt, + &n, &dummy, &p); + if(p == nil || *p == 0) + return nil; + return strdup((char*)p); +} + +Window +findname(Window w) +{ + int i; + uint nxwin; + Window dw1, dw2, *xwin; + + if(getproperty(w, XA_WM_NAME)) + return w; + if(!XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin)) + return 0; + for(i=0; i<nxwin; i++) + if((w = findname(xwin[i])) != 0) + return w; + return 0; +} + +void +getinfo(void) +{ + int i; + uint nxwin; + Window dw1, dw2, *xwin; + XClassHint class; + XWindowAttributes attr; + + if(!XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin)) + return; + w = mallocz(nxwin*sizeof w[0], 1); + if(w == 0) + sysfatal("malloc: %r"); + + Win *ww = w; + for(i=0; i<nxwin; i++){ + memset(&attr, 0, sizeof attr); + xwin[i] = findname(xwin[i]); + if(xwin[i] == 0) + continue; + XGetWindowAttributes(dpy, xwin[i], &attr); + if(attr.width <= 0 || attr.override_redirect || attr.map_state != IsViewable) + continue; + ww->xw = xwin[i]; + ww->x = attr.x; + ww->y = attr.y; + ww->dx = attr.width; + ww->dy = attr.height; + XTranslateCoordinates(dpy, ww->xw, root, 0, 0, &ww->x, &ww->y, &dw1); + if(XGetClassHint(dpy, ww->xw, &class)){ + ww->class = strdup(class.res_class); + ww->instance = strdup(class.res_name); + } + ww->iconname = getproperty(ww->xw, XA_WM_ICON_NAME); + ww->name = getproperty(ww->xw, XA_WM_NAME); + ww++; + } + nw = ww - w; +} + +void +listwindows(void) +{ + int i; + + for(i=0; i<nw; i++){ + Win *ww = &w[i]; + char rect[50]; + snprint(rect, sizeof rect, "%d,%d,%d,%d", ww->x, ww->y, ww->x+ww->dx, ww->y+ww->dy); + print("%08x %-20s %-10s %s\n", + (uint)ww->xw, + rect, + ww->instance, + ww->class); + } +} + +void +shove(char *name, char *geom) +{ + int i; + int isdelta, havemin, havesize; + int old, new; + Rectangle r; + + if(parsewinsize(geom, &r, &isdelta, &havemin, &havesize) < 0) + sysfatal("bad window spec: %s", name); + + old = 0; + new = 1; + if(isdelta){ + old = 1; + new = isdelta; + } + for(i=0; i<nw; i++){ + Win *ww = &w[i]; + if(ww->instance && strstr(ww->instance, name) + || ww->class && strstr(ww->class, name)){ + int value_mask; + XWindowChanges e; + + memset(&e, 0, sizeof e); + if(havemin){ + e.x = old*ww->x + new*r.min.x; + e.y = old*ww->y + new*r.min.y; + }else{ + e.x = ww->x; + e.y = ww->y; + } + if(havesize){ + e.width = old*ww->dx + new*Dx(r); + e.height = old*ww->dy + new*Dy(r); + }else{ + e.width = ww->dx; + e.height = ww->dy; + } + value_mask = CWX | CWY | CWWidth | CWHeight; + XConfigureWindow(dpy, ww->xw, value_mask, &e); + XFlush(dpy); + } + } +} + +int +parsewinsize(char *s, Rectangle *r, int *isdelta, int *havemin, int *havesize) +{ + char c, *os; + int i, j, k, l; + + os = s; + if(*s == '-'){ + s++; + *isdelta = -1; + }else if(*s == '+'){ + s++; + *isdelta = 1; + }else + *isdelta = 0; + *havemin = 0; + *havesize = 0; + memset(r, 0, sizeof *r); + if(!isdigit((uchar)*s)) + goto oops; + i = strtol(s, &s, 0); + if(*s == 'x'){ + s++; + if(!isdigit((uchar)*s)) + goto oops; + j = strtol(s, &s, 0); + r->max.x = i; + r->max.y = j; + *havesize = 1; + if(*s == 0) + return 0; + if(*s != '@') + goto oops; + + s++; + if(!isdigit((uchar)*s)) + goto oops; + i = strtol(s, &s, 0); + if(*s != ',' && *s != ' ') + goto oops; + s++; + if(!isdigit((uchar)*s)) + goto oops; + j = strtol(s, &s, 0); + if(*s != 0) + goto oops; + r->min.x += i; + r->max.x += i; + r->min.y += j; + r->max.y += j; + *havesize = 1; + *havemin = 1; + return 0; + } + + c = *s; + if(c != ' ' && c != ',') + goto oops; + s++; + if(!isdigit((uchar)*s)) + goto oops; + j = strtol(s, &s, 0); + if(*s == 0){ + r->min.x = i; + r->min.y = j; + *havemin = 1; + return 0; + } + if(*s != c) + goto oops; + s++; + if(!isdigit((uchar)*s)) + goto oops; + k = strtol(s, &s, 0); + if(*s != c) + goto oops; + s++; + if(!isdigit((uchar)*s)) + goto oops; + l = strtol(s, &s, 0); + if(*s != 0) + goto oops; + r->min.x = i; + r->min.y = j; + r->max.x = k; + r->max.y = l; + *havemin = 1; + *havesize = 1; + return 0; + +oops: + werrstr("bad syntax in window size '%s'", os); + return -1; +}