changeset: 2033:de2320e9f616
tag: tip
user: Kris Maglione <jg_AT_suckless.org>
date: Mon Mar 26 00:48:00 2007 -0400
summary: New tree layout and make system. Note: This will currently *not* install configuration scripts.
diff -r 7ce25d709bbe -r de2320e9f616 9menu.c
--- a/9menu.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,527 +0,0 @@
-/* Licence
- * =======
- *
- * 9menu is free software, and is Copyright (c) 1994 by David Hogan and
- * Arnold Robbins. 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 9menu
- * and whose documentation gives credit where it is due
- * (4) the authors are 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.
- *
- * --
- * Arnold Robbins
- * arnold_AT_skeeve.com
- *
- * 9menu.c
- *
- * This program puts up a window that is just a menu, and executes
- * commands that correspond to the items selected.
- *
- * Initial idea: Arnold Robbins
- * Version using libXg: Matty Farrow (some ideas borrowed)
- * This code by: David Hogan and Arnold Robbins
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xutil.h>
-
-#define nil ((void*)0)
-
-char version[] = "@(#) wmii9menu version 1.8";
-
-/* lovely X stuff */
-Display *dpy;
-int screen;
-Window root;
-Window menuwin;
-Colormap defcmap;
-XColor color;
-XFontStruct *font;
-GC gc;
-
-unsigned long selbg;
-unsigned long selfg;
-unsigned long normbg;
-unsigned long normfg;
-unsigned long border;
-char *sfgname = nil;
-char *sbgname = nil;
-char *nfgname = nil;
-char *nbgname = nil;
-char *brcname = nil;
-
-/* for XSetWMProperties to use */
-int g_argc;
-char **g_argv;
-
-/* for labels read from files */
-int f_argc;
-char **f_argv;
-
-char *initial = "";
-int cur;
-
-char *fontlist[] = { /* default font list if no -font */
- "pelm.latin1.9",
- "lucm.latin1.9",
- "blit",
- "9x15bold",
- "9x15",
- "lucidasanstypewriter-12",
- "fixed",
- nil
-};
-
-char *progname; /* my name */
-char *displayname; /* X display */
-char *fontname; /* font */
-char *filename; /* file to read options or labels from */
-
-char **labels; /* list of labels and commands */
-char **commands;
-int numitems;
-
-void usage(), run_menu();
-void create_window();
-void redraw(), warpmouse();
-void memory();
-int args();
-
-/* memory --- print the out of memory message and die */
-
-void
-memory(s)
-char *s;
-{
- fprintf(stderr, "%s: couldn't allocate memory for %s\n", progname, s);
- exit(1);
-}
-
-/* args --- go through the argument list, set options */
-
-int
-args(int argc, char **argv)
-{
- int i;
- if (argc == 0 || argv == nil || argv[0] == '\0')
- return -1;
- for (i = 0; i < argc && argv[i] != nil; i++) {
- if (strcmp(argv[i], "-display") == 0)
- displayname = argv[++i];
- else if (strcmp(argv[i], "-file") == 0)
- filename = argv[++i];
- else if (strcmp(argv[i], "-font") == 0)
- fontname = argv[++i];
- else if (strncmp(argv[i], "-initial", 9) == 0)
- initial = argv[++i];
- else if (strncmp(argv[i], "-nb", 3) == 0)
- nbgname = argv[i][3] ? &argv[i][3] : argv[++i];
- else if (strncmp(argv[i], "-nf", 3) == 0)
- nfgname = argv[i][3] ? &argv[i][3] : argv[++i];
- else if (strncmp(argv[i], "-sb", 3) == 0)
- sbgname = argv[i][3] ? &argv[i][3] : argv[++i];
- else if (strncmp(argv[i], "-sf", 3) == 0)
- sfgname = argv[i][3] ? &argv[i][3] : argv[++i];
- else if (strncmp(argv[i], "-br", 3) == 0)
- brcname = argv[i][3] ? &argv[i][3] : argv[++i];
- else if (strcmp(argv[i], "-version") == 0) {
- printf("%s\n", version);
- exit(0);
- } else if (argv[i][0] == '-')
- usage();
- else
- break;
- }
- return i;
-}
-
-/* main --- crack arguments, set up X stuff, run the main menu loop */
-
-int
-main(int argc, char **argv)
-{
- int i, j;
- char *cp;
- XGCValues gv;
- unsigned long mask;
- int nlabels = 0;
-
- g_argc = argc;
- g_argv = argv;
-
- /* set default label name */
- if ((cp = strrchr(argv[0], '/')) == nil)
- progname = argv[0];
- else
- progname = ++cp;
-
- ++argv;
- --argc;
-
- i = args(argc, argv);
-
- numitems = argc - i;
-
- if (numitems <= 0 && filename == nil)
- usage();
-
- if (filename) {
- /* Read options and labels from file */
- char fbuf[1024];
- FILE *fp;
-
- fp = fopen(filename, "r");
- if (fp == nil) {
- fprintf(stderr, "%s: couldn't open '%s'\n", progname,
- filename);
- exit(1);
- }
- while (fgets(fbuf, sizeof fbuf, fp)) {
- char *s = fbuf;
- strtok(s, "\n");
- if (s[0] == '-') {
- char *temp[3];
- temp[0] = s;
- temp[1] = strchr(s, ' ');
- if (temp[1]) {
- *(temp[1]++) = '\0';
- s = malloc(strlen(temp[1]) + 1);
- if (s == nil)
- memory("temporary argument");
- strcpy(s, temp[1]);
- temp[1] = s;
- }
- temp[2] = 0;
- args(temp[1] ? 2 : 1, temp);
- continue;
- }
- if (s[0] == '#')
- continue;
- /* allow - in menu items to be escaped */
- if (s[0] == '\\')
- ++s;
- /* allocate space */
- if (f_argc < nlabels + 1) {
- int k;
- char **temp = malloc(sizeof(char *) * (f_argc + 5));
- if (temp == 0)
- memory("temporary item");
-
- for (k = 0; k < nlabels; k++)
- temp[k] = f_argv[k];
-
- free(f_argv);
- f_argv = temp;
- f_argc += 5;
- }
- f_argv[nlabels] = malloc(strlen(s) + 1);
- if (f_argv[nlabels] == nil)
- memory("temporary text");
- strcpy(f_argv[nlabels], s);
- ++nlabels;
- }
- }
-
- labels = (char **) malloc((numitems + nlabels) * sizeof(char *));
- commands = (char **) malloc((numitems + nlabels) * sizeof(char *));
- if (commands == nil || labels == nil)
- memory("command and label arrays");
-
- for (j = 0; j < numitems; j++) {
- labels[j] = argv[i + j];
- if ((cp = strchr(labels[j], ':')) != nil) {
- *cp++ = '\0';
- commands[j] = cp;
- } else
- commands[j] = labels[j];
- if(strcmp(labels[j], initial) == 0)
- cur = j;
- }
-
- /*
- * Now we no longer need i (our offset into argv) so we recycle it,
- * while keeping the old value of j!
- */
- for (i = 0; i < nlabels; i++) {
- labels[j] = f_argv[i];
- if ((cp = strchr(labels[j], ':')) != nil) {
- *cp++ = '\0';
- commands[j] = cp;
- } else
- commands[j] = labels[j];
- ++j;
- }
-
- /* And now we merge the totals */
- numitems += nlabels;
-
- dpy = XOpenDisplay(displayname);
- if (dpy == nil) {
- fprintf(stderr, "%s: cannot open display", progname);
- if (displayname != nil)
- fprintf(stderr, " %s", displayname);
- fprintf(stderr, "\n");
- exit(1);
- }
- screen = DefaultScreen(dpy);
- root = RootWindow(dpy, screen);
- /*
- * This used to be
- * black = BlackPixel(dpy, screen);
- * white = WhitePixel(dpy, screen);
- */
- defcmap = DefaultColormap(dpy, screen);
- if (sbgname == nil
- || XParseColor(dpy, defcmap, sbgname, &color) == 0
- || XAllocColor(dpy, defcmap, &color) == 0)
- selbg = BlackPixel(dpy, screen);
- else
- selbg = color.pixel;
-
- if (sfgname == nil
- || XParseColor(dpy, defcmap, sfgname, &color) == 0
- || XAllocColor(dpy, defcmap, &color) == 0)
- selfg = WhitePixel(dpy, screen);
- else
- selfg = color.pixel;
-
- if (nbgname == nil
- || XParseColor(dpy, defcmap, nbgname, &color) == 0
- || XAllocColor(dpy, defcmap, &color) == 0)
- normbg = selfg;
- else
- normbg = color.pixel;
-
- if (nfgname == nil
- || XParseColor(dpy, defcmap, nfgname, &color) == 0
- || XAllocColor(dpy, defcmap, &color) == 0)
- normfg = selbg;
- else
- normfg = color.pixel;
-
- if (brcname == nil
- || XParseColor(dpy, defcmap, brcname, &color) == 0
- || XAllocColor(dpy, defcmap, &color) == 0)
- border = selbg;
- else
- border = color.pixel;
-
- /* try user's font first */
- if (fontname != nil) {
- font = XLoadQueryFont(dpy, fontname);
- if (font == nil)
- fprintf(stderr, "%s: warning: can't load font %s\n",
- progname, fontname);
- }
-
- /* if no user font, try one of our default fonts */
- if (font == nil) {
- for (i = 0; fontlist[i] != nil; i++) {
- font = XLoadQueryFont(dpy, fontlist[i]);
- if (font != nil)
- break;
- }
- }
-
- if (font == nil) {
- fprintf(stderr, "%s: fatal: cannot load a font\n", progname);
- exit(1);
- }
-
- gv.foreground = normfg;
- gv.background = normbg;
- gv.font = font->fid;
- gv.line_width = 0;
- mask = GCForeground | GCBackground | GCFont | GCLineWidth;
- gc = XCreateGC(dpy, root, mask, &gv);
-
- run_menu();
-
- XCloseDisplay(dpy);
- exit(0);
-}
-
-/* usage --- print a usage message and die */
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [-display <displayname>] [-font <fontname>] ", progname);
- fprintf(stderr, "[-file filename] ");
- fprintf(stderr, "[-{n,s}{f,b} <color>] [-br <color>] ");
- fprintf(stderr, "[-version] menitem[:command] ...\n");
- exit(0);
-}
-
-/* run_menu --- put up the window, execute selected commands */
-
-void
-run_menu()
-{
- XEvent ev;
- int i, old, wide, high, dx, dy;
-
- dx = 0;
- for (i = 0; i < numitems; i++) {
- wide = XTextWidth(font, labels[i], strlen(labels[i])) + 4;
- if (wide > dx)
- dx = wide;
- }
- wide = dx;
-
- high = font->ascent + font->descent + 1;
- dy = numitems * high;
-
- enum {
- MouseMask =
- ButtonPressMask
- | ButtonReleaseMask
- | ButtonMotionMask
- | PointerMotionMask,
- MenuMask =
- MouseMask
- | StructureNotifyMask
- | ExposureMask
- };
-
- create_window(wide, high);
- warpmouse(wide, high);
-
- XSelectInput(dpy, menuwin, MenuMask);
-
- XMapWindow(dpy, menuwin);
-
- i = 0; /* save menu Item position */
-
- for (;;) {
- XNextEvent(dpy, &ev);
- switch (ev.type) {
- default:
- fprintf(stderr, "%s: unknown ev.type %d\n",
- progname, ev.type);
- break;
- case ButtonRelease:
- i = ev.xbutton.y/high;
- if (ev.xbutton.x < 0 || ev.xbutton.x > wide)
- return;
- else if (i < 0 || i >= numitems)
- return;
-
- printf("%s\n", commands[i]);
- return;
- case ButtonPress:
- case MotionNotify:
- old = cur;
- cur = ev.xbutton.y/high;
- if (ev.xbutton.x < 0 || ev.xbutton.x > wide)
- cur = ~0;
- if (cur == old)
- break;
- redraw(high, wide);
- break;
- case MapNotify:
- redraw(high, wide);
- if(XGrabPointer(dpy, menuwin, False, MouseMask,
- GrabModeAsync, GrabModeAsync,
- 0, None, CurrentTime
- ) != GrabSuccess) {
- fprintf(stderr, "Failed to grab the mouse\n");
- }
- break;
- case Expose:
- redraw(high, wide);
- break;
- case MappingNotify: /* why do we get this? */
- break;
- }
- }
-}
-
-/* set_wm_hints --- set all the window manager hints */
-
-void
-create_window(int wide, int high)
-{
- XSetWindowAttributes wa = { 0 };
- unsigned int h;
- int x, y, dummy;
- Window wdummy;
-
- h = high * numitems;
-
- XQueryPointer(dpy, root, &wdummy, &wdummy, &x, &y,
- &dummy, &dummy, (uint*)&dummy);
- x -= wide / 2;
- if (x < 0)
- x = 0;
- else if (x + wide > DisplayWidth(dpy, screen))
- x = DisplayWidth(dpy, screen) - wide;
-
- y -= cur * high + high / 2;
- if (y < 0)
- y = 0;
- else if (y + h > DisplayHeight(dpy, screen))
- y = DisplayHeight(dpy, screen) - h;
-
- wa.override_redirect = True;
- wa.border_pixel = border;
- wa.background_pixel = normbg;
- menuwin = XCreateWindow(dpy, root, x, y, wide, h,
- 1, DefaultDepth(dpy, screen), CopyFromParent,
- DefaultVisual(dpy, screen),
- CWOverrideRedirect
- | CWBackPixel
- | CWBorderPixel
- | CWEventMask,
- &wa);
-
- XSetCommand(dpy, menuwin, g_argv, g_argc);
-}
-
-/* redraw --- actually redraw the menu */
-
-void
-redraw(int high, int wide)
-{
- int tx, ty, i;
-
- for (i = 0; i < numitems; i++) {
- tx = (wide - XTextWidth(font, labels[i], strlen(labels[i]))) / 2;
- ty = i*high + font->ascent + 1;
- if (cur == i)
- XSetForeground(dpy, gc, selbg);
- else
- XSetForeground(dpy, gc, normbg);
- XFillRectangle(dpy, menuwin, gc, 0, i*high, wide, high);
- if (cur == i)
- XSetForeground(dpy, gc, selfg);
- else
- XSetForeground(dpy, gc, normfg);
- XDrawString(dpy, menuwin, gc, tx, ty, labels[i], strlen(labels[i]));
- }
-}
-
-/* warpmouse --- bring the mouse to the menu */
-
-void
-warpmouse(int wide, int high)
-{
- int offset;
-
- /* move tip of pointer into middle of menu item */
- offset = (font->ascent + font->descent + 1) / 2;
- offset += 6; /* fudge factor */
-
- XWarpPointer(dpy, None, menuwin, 0, 0, 0, 0,
- wide/2, cur*high-high/2+offset);
-}
diff -r 7ce25d709bbe -r de2320e9f616 LICENSE.p9p
--- a/LICENSE.p9p Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-The bulk of this software is derived from Plan 9 and is thus distributed
-under the Lucent Public License, Version 1.02, reproduced below.
-
-There are a few exceptions: libutf, libfmt, and libregexp are distributed
-under simpler BSD-like boilerplates. See the LICENSE files in those
-directories. There are other exceptions, also marked with LICENSE files
-in their directories.
-
-The bitmap fonts in the font/luc, font/lucm, font/lucsans, and font/pelm
-directory are copyright B&H Inc. and distributed under more restricted
-terms under agreement with B&H. See the NOTICE file in those directories.
-
-===================================================================
-
-Lucent Public License Version 1.02
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
-LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
-PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
- a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
- Program, and
- b. in the case of each Contributor,
-
- i. changes to the Program, and
- ii. additions to the Program;
-
- where such changes and/or additions to the Program were added to the
- Program by such Contributor itself or anyone acting on such
- Contributor's behalf, and the Contributor explicitly consents, in
- accordance with Section 3C, to characterization of the changes and/or
- additions as Contributions.
-
-"Contributor" means LUCENT and any other entity that has Contributed a
-Contribution to the Program.
-
-"Distributor" means a Recipient that distributes the Program,
-modifications to the Program, or any part thereof.
-
-"Licensed Patents" mean patent claims licensable by a Contributor
-which are necessarily infringed by the use or sale of its Contribution
-alone or when combined with the Program.
-
-"Original Program" means the original version of the software
-accompanying this Agreement as released by LUCENT, including source
-code, object code and documentation, if any.
-
-"Program" means the Original Program and Contributions or any part
-thereof
-
-"Recipient" means anyone who receives the Program under this
-Agreement, including all Contributors.
-
-2. GRANT OF RIGHTS
-
- a. Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free copyright
- license to reproduce, prepare derivative works of, publicly display,
- publicly perform, distribute and sublicense the Contribution of such
- Contributor, if any, and such derivative works, in source code and
- object code form.
-
- b. Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free patent
- license under Licensed Patents to make, use, sell, offer to sell,
- import and otherwise transfer the Contribution of such Contributor, if
- any, in source code and object code form. The patent license granted
- by a Contributor shall also apply to the combination of the
- Contribution of that Contributor and the Program if, at the time the
- Contribution is added by the Contributor, such addition of the
- Contribution causes such combination to be covered by the Licensed
- Patents. The patent license granted by a Contributor shall not apply
- to (i) any other combinations which include the Contribution, nor to
- (ii) Contributions of other Contributors. No hardware per se is
- licensed hereunder.
-
- c. Recipient understands that although each Contributor grants the
- licenses to its Contributions set forth herein, no assurances are
- provided by any Contributor that the Program does not infringe the
- patent or other intellectual property rights of any other entity. Each
- Contributor disclaims any liability to Recipient for claims brought by
- any other entity based on infringement of intellectual property rights
- or otherwise. As a condition to exercising the rights and licenses
- granted hereunder, each Recipient hereby assumes sole responsibility
- to secure any other intellectual property rights needed, if any. For
- example, if a third party patent license is required to allow
- Recipient to distribute the Program, it is Recipient's responsibility
- to acquire that license before distributing the Program.
-
- d. Each Contributor represents that to its knowledge it has sufficient
- copyright rights in its Contribution, if any, to grant the copyright
- license set forth in this Agreement.
-
-3. REQUIREMENTS
-
-A. Distributor may choose to distribute the Program in any form under
-this Agreement or under its own license agreement, provided that:
-
- a. it complies with the terms and conditions of this Agreement;
-
- b. if the Program is distributed in source code or other tangible
- form, a copy of this Agreement or Distributor's own license agreement
- is included with each copy of the Program; and
-
- c. if distributed under Distributor's own license agreement, such
- license agreement:
-
- i. effectively disclaims on behalf of all Contributors all warranties
- and conditions, express and implied, including warranties or
- conditions of title and non-infringement, and implied warranties or
- conditions of merchantability and fitness for a particular purpose;
- ii. effectively excludes on behalf of all Contributors all liability
- for damages, including direct, indirect, special, incidental and
- consequential damages, such as lost profits; and
- iii. states that any provisions which differ from this Agreement are
- offered by that Contributor alone and not by any other party.
-
-B. Each Distributor must include the following in a conspicuous
- location in the Program:
-
- Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
- Reserved.
-
-C. In addition, each Contributor must identify itself as the
-originator of its Contribution in a manner that reasonably allows
-subsequent Recipients to identify the originator of the Contribution.
-Also, each Contributor must agree that the additions and/or changes
-are intended to be a Contribution. Once a Contribution is contributed,
-it may not thereafter be revoked.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain
-responsibilities with respect to end users, business partners and the
-like. While this license is intended to facilitate the commercial use
-of the Program, the Distributor who includes the Program in a
-commercial product offering should do so in a manner which does not
-create potential liability for Contributors. Therefore, if a
-Distributor includes the Program in a commercial product offering,
-such Distributor ("Commercial Distributor") hereby agrees to defend
-and indemnify every Contributor ("Indemnified Contributor") against
-any losses, damages and costs (collectively"Losses") arising from
-claims, lawsuits and other legal actions brought by a third party
-against the Indemnified Contributor to the extent caused by the acts
-or omissions of such Commercial Distributor in connection with its
-distribution of the Program in a commercial product offering. The
-obligations in this section do not apply to any claims or Losses
-relating to any actual or alleged intellectual property infringement.
-In order to qualify, an Indemnified Contributor must: a) promptly
-notify the Commercial Distributor in writing of such claim, and b)
-allow the Commercial Distributor to control, and cooperate with the
-Commercial Distributor in, the defense and any related settlement
-negotiations. The Indemnified Contributor may participate in any such
-claim at its own expense.
-
-For example, a Distributor might include the Program in a commercial
-product offering, Product X. That Distributor is then a Commercial
-Distributor. If that Commercial Distributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Distributor's responsibility
-alone. Under this section, the Commercial Distributor would have to
-defend claims against the Contributors related to those performance
-claims and warranties, and if a court requires any Contributor to pay
-any damages as a result, the Commercial Distributor must pay those
-damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
-PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
-OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
-responsible for determining the appropriateness of using and
-distributing the Program and assumes all risks associated with its
-exercise of rights under this Agreement, including but not limited to
-the risks and costs of program errors, compliance with applicable
-laws, damage to or loss of data, programs or equipment, and
-unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. EXPORT CONTROL
-
-Recipient agrees that Recipient alone is responsible for compliance
-with the United States export administration regulations (and the
-export control laws and regulation of any other countries).
-
-8. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further
-action by the parties hereto, such provision shall be reformed to the
-minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against a Contributor with
-respect to a patent applicable to software (including a cross-claim or
-counterclaim in a lawsuit), then any patent licenses granted by that
-Contributor to such Recipient under this Agreement shall terminate as
-of the date such litigation is filed. In addition, if Recipient
-institutes patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it
-fails to comply with any of the material terms or conditions of this
-Agreement and does not cure such failure in a reasonable period of
-time after becoming aware of such noncompliance. If all Recipient's
-rights under this Agreement terminate, Recipient agrees to cease use
-and distribution of the Program as soon as reasonably practicable.
-However, Recipient's obligations under this Agreement and any licenses
-granted by Recipient relating to the Program shall continue and
-survive.
-
-LUCENT may publish new versions (including revisions) of this
-Agreement from time to time. Each new version of the Agreement will be
-given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the
-Agreement under which it was received. In addition, after a new
-version of the Agreement is published, Contributor may elect to
-distribute the Program (including its Contributions) under the new
-version. No one other than LUCENT has the right to modify this
-Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
-Recipient receives no rights or licenses to the intellectual property
-of any Contributor under this Agreement, whether expressly, by
-implication, estoppel or otherwise. All rights in the Program not
-expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and
-the intellectual property laws of the United States of America. No
-party to this Agreement will bring a legal action under this Agreement
-more than one year after the cause of action arose. Each party waives
-its rights to a jury trial in any resulting litigation.
-
diff -r 7ce25d709bbe -r de2320e9f616 Makefile
--- a/Makefile Sun Mar 25 15:16:24 2007 -0400
+++ b/Makefile Mon Mar 26 00:48:00 2007 -0400
@@ -1,101 +1,8 @@
-# window manager improved 2 - window manager improved 2
-# © 2006 Anselm R. Garbe
-# © 2006-2007 Kris Maglione
-.POSIX:
+ROOT=.
+include ${ROOT}/mk/hdr.mk
-include config.mk
+DIRS = libixp \
+ cmd \
+ man
-SRC = area.c bar.c client.c column.c draw.c event.c frame.c fs.c \
- geom.c key.c main.c mouse.c rule.c printevent.c util.c view.c
-OBJ = ${SRC:.c=.o}
-MAN1 = wmii wmiir wmiiwm wmiiloop
-SCRIPTS = wmiistartrc wmiir wmiiloop wmii9rc
-BIN = wmii wmii9menu
-
-all: options ${BIN}
-
-options:
- @echo wmii build options:
- @echo "CFLAGS = ${CFLAGS}"
- @echo "LDFLAGS = ${LDFLAGS}"
- @echo "CC = ${CC}"
-
-.c.o:
- @echo CC $<
- @${CC} -c ${CFLAGS} $<
-
-# In case this isn't from hg
-.hg/00changelog.i:
- @mkdir .hg
- @touch .hg/00changelog.i
-# VERSION must be updated on every commit/pull
-config.mk: .hg/00changelog.i
-
-${OBJ}: wmii.h config.mk
-
-9menu.o: config.mk
-
-wmii: ${OBJ}
- @echo LD $@
- @${CC} -o $@ ${OBJ} ${LDFLAGS} ${LIBIXP}
-
-wmii9menu: 9menu.o
- @echo LD $@
- @${CC} -o $@ 9menu.o ${LDFLAGS}
-
-clean:
- @echo cleaning
- @rm -f ${BIN} ${OBJ} 9menu.o wmii-${VERSION}.tar.gz
-
-dist: clean
- @echo creating dist tarball
- @mkdir -p wmii-${VERSION}
- @ln LICENSE Makefile config.mk README rc/ \
- wmii.eps wmii.mp \
- ${MAN1:=.1} ${SRC} ${SCRIPTS} wmii.h 9menu.c \
- wmii-${VERSION}/
- @tar -zcf wmii-${VERSION}.tgz wmii-${VERSION}
- @rm -rf wmii-${VERSION}
-
-install: all
- @echo installing executable files to ${DESTDIR}${PREFIX}/bin
- @mkdir -p -m 0755 ${DESTDIR}${PREFIX}/bin
- @for i in ${SCRIPTS}; do \
- sed "s|CONFPREFIX|${CONFPREFIX}|g; \
- s|CONFVERSION|${CONFVERSION}|g; \
- s|P9PATHS|${P9PATHS}|g; \
- s|AWKPATH|${AWKPATH}|g" \
- $$i \
- >${DESTDIR}${PREFIX}/bin/$$i; \
- chmod 755 ${DESTDIR}${PREFIX}/bin/$$i; \
- done
- @for i in ${BIN}; do\
- cp -f $$i ${DESTDIR}${PREFIX}/bin; \
- chmod 755 ${DESTDIR}${PREFIX}/bin/$$i; \
- done
- @echo installing scripts to ${DESTDIR}${CONFPREFIX}/wmii-${CONFVERSION}
- @mkdir -p -m 0755 ${DESTDIR}${CONFPREFIX}/wmii-${CONFVERSION}
- @cd rc; for i in *; do \
- sed "s|CONFPREFIX|${CONFPREFIX}|g" $$i \
- >${DESTDIR}${CONFPREFIX}/wmii-${CONFVERSION}/$$i; \
- chmod 755 ${DESTDIR}${CONFPREFIX}/wmii-${CONFVERSION}/$$i; \
- done
- @echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
- @mkdir -p -m 0755 ${DESTDIR}${MANPREFIX}/man1
- @for i in ${MAN1:=.1}; do \
- sed "s/VERSION/${VERSION}/g; \
- s|CONFPREFIX|${CONFPREFIX}|g" \
- $$i \
- >${DESTDIR}${MANPREFIX}/man1/$$i; \
- chmod 644 ${DESTDIR}${MANPREFIX}/man1/$$i; \
- done
-
-uninstall:
- @echo removing executable files from ${DESTDIR}${PREFIX}/bin
- @cd ${DESTDIR}${PREFIX}/bin && rm -f ${SCRIPTS} ${BIN}
- @echo removing scripts from ${DESTDIR}${CONFPREFIX}/wmii-${CONFVERSION}
- @rm -rf ${DESTDIR}${CONFPREFIX}/wmii-${CONFVERSION}
- @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
- @cd ${DESTDIR}${MANPREFIX}/man1 && rm -f ${MAN1:=.1}
-
-.PHONY: all options clean dist install uninstall
+include ${ROOT}/mk/dir.mk
diff -r 7ce25d709bbe -r de2320e9f616 area.c
--- a/area.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,438 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <assert.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include "wmii.h"
-
-static void place_frame(Frame *f);
-
-Client *
-sel_client_of_area(Area *a) {
- if(a && a->sel)
- return a->sel->client;
- return nil;
-}
-
-Area *
-create_area(View *v, Area *pos, uint w) {
- static ushort id = 1;
- uint area_num, col_num, i;
- uint min_width;
- Area *a, **p;
-
- min_width = screen->rect.width/NCOL;
- p = pos ? &pos->next : &v->area;
-
- area_num = 0;
- i = 0;
- for(a = v->area; a != *p; a = a->next)
- area_num++, i++;
- for(; a; a = a->next) area_num++;
-
- col_num = max((area_num - 1), 0);
- if(w == 0) {
- if(col_num) {
- w = newcolw_of_view(v);
- if (w == 0)
- w = screen->rect.width / (col_num + 1);
- }
- else w = screen->rect.width;
- }
- if(w < min_width)
- w = min_width;
- if(col_num && (col_num * min_width + w) > screen->rect.width)
- return nil;
- if(pos)
- scale_view(v, screen->rect.width - w);
-
- a = emallocz(sizeof(Area));
- a->view = v;
- a->id = id++;
- a->rect = screen->rect;
- a->rect.height = screen->rect.height - screen->brect.height;
- a->mode = def.colmode;
- a->rect.width = w;
- a->frame = nil;
- a->sel = nil;
- a->next = *p;
- *p = a;
-
- if(a == v->area)
- a->floating = True;
- if((!v->sel) ||
- (v->sel->floating && v->area->next == a && a->next == nil))
- focus_area(a);
-
- if(i)
- write_event("CreateColumn %d\n", i);
- return a;
-}
-
-void
-destroy_area(Area *a) {
- Client *c;
- Area *ta;
- View *v;
- uint i;
-
- v = a->view;
-
- if(a->frame)
- fatal("destroying non-empty area");
- if(v->revert == a)
- v->revert = nil;
- for(c=client; c; c=c->next)
- if(c->revert == a)
- c->revert = nil;
-
- i = 1;
- for(ta=v->area; ta; ta=ta->next)
- if(ta->next == a) break;
- else i++;
- if(ta) {
- ta->next = a->next;
- if(ta->floating && ta->next)
- ta = ta->next;
- if(v->sel == a)
- focus_area(ta);
- }
- if(i) write_event("DestroyColumn %d\n", i);
- free(a);
-}
-
-void
-send_to_area(Area *to, Frame *f) {
- Area *from;
- assert(to->view == f->view);
- from = f->area;
- if(to->floating != from->floating) {
- XRectangle temp = f->revert;
- f->revert = f->rect;
- f->rect = temp;
- }
- f->client->revert = from;
- detach_from_area(f);
- attach_to_area(to, f, True);
-}
-
-void
-attach_to_area(Area *a, Frame *f, Bool send) {
- uint h, n_frame;
- Frame *ft;
- Client *c;
- View *v;
-
- v = a->view;
- c = f->client;
- h = 0;
-
- f->area = a;
-
- n_frame = 0;
- for(ft=a->frame; ft; ft=ft->anext)
- n_frame++;
- if(n_frame == 0)
- n_frame = 1;
-
- c->floating = a->floating;
- if(!a->floating)
- f->rect.height = a->rect.height / n_frame;
-
- insert_frame(a->sel, f, False);
-
- if(a->floating)
- place_frame(f);
-
- focus_frame(f, False);
- resize_frame(f, &f->rect);
- restack_view(a->view);
- if(!a->floating)
- arrange_column(a, False);
- else
- resize_frame(f, &f->rect);
-
- update_client_grab(f->client);
- if(a->frame)
- assert(a->sel);
-}
-
-void
-detach_from_area(Frame *f) {
- Frame *pr;
- Client *c;
- Area *a;
- View *v;
- Area *ta;
- uint i;
-
- a = f->area;
- v = a->view;
- c = f->client;
-
- for(pr = a->frame; pr; pr = pr->anext)
- if(pr->anext == f) break;
- remove_frame(f);
-
- if(a->sel == f) {
- if(!pr)
- pr = a->frame;
- if((a->view->sel == a) && (pr))
- focus_frame(pr, False);
- else
- a->sel = pr;
- }
-
- if(!a->floating) {
- if(a->frame)
- arrange_column(a, False);
- else {
- i = 0;
- for(ta=v->area; ta && ta != a; ta=ta->next)
- i++;
- if(v->area->next->next)
- destroy_area(a);
- else if(!a->frame && v->area->frame)
- /* focus floating area if it contains something */
- focus_area(v->area);
- arrange_view(v);
- }
- }
- else if(!a->frame) {
- if(c->trans) {
- /* focus area of transient, if possible */
- Client *cl = client_of_win(c->trans);
- if(cl && cl->frame) {
- a = cl->sel->area;
- if(a->view == v)
- focus_area(a);
- }
- }
- else if(v->area->next->frame)
- focus_area(v->area->next);
- }else
- assert(a->sel);
-}
-
-static void
-bit_twiddle(uint *field, uint width, uint x, uint y, Bool set) {
- enum { devisor = sizeof(uint) * 8 };
- uint bx, mask;
-
- bx = x / devisor;
- mask = 1 << x % devisor;
- if(set)
- field[y*width + bx] |= mask;
- else
- field[y*width + bx] &= ~mask;
-}
-
-static Bool
-bit_get(uint *field, uint width, uint x, uint y) {
- enum { devisor = sizeof(uint) * 8 };
- uint bx, mask;
-
- bx = x / devisor;
- mask = 1 << x % devisor;
-
- return (field[y*width + bx] & mask) != 0;
-}
-
-static void
-place_frame(Frame *f) {
- enum { devisor = sizeof(uint) * 8 };
- enum { dx = 8, dy = 8 };
- static uint mwidth, mx, my;
- static uint *field = nil;
- BlitzAlign align;
- XPoint p1 = {0, 0};
- XPoint p2 = {0, 0};
- XRectangle *rects;
- Frame *fr;
- Client *c;
- Area *a;
- Bool fit;
- uint i, j, x, y, cx, cy, maxx, maxy, diff, num;
- int snap;
-
- snap = screen->rect.height / 66;
- num = 0;
- fit = False;
- align = CENTER;
-
- a = f->area;
- c = f->client;
-
- if(c->trans)
- return;
- if(c->rect.width >= a->rect.width
- || c->rect.height >= a->rect.height
- || c->size.flags & USPosition
- || c->size.flags & PPosition)
- return;
- if(!field) {
- mx = screen->rect.width / dx;
- my = screen->rect.height / dy;
- mwidth = ceil((float)mx / devisor);
- field = emallocz(sizeof(uint) * mwidth * my);
- }
- memset(field, ~0, (sizeof(uint) * mwidth * my));
- for(fr=a->frame; fr; fr=fr->anext) {
- if(fr == f) {
- cx = f->rect.width / dx;
- cy = f->rect.height / dy;
- continue;
- }
- if(fr->rect.x < 0)
- x = 0;
- else
- x = fr->rect.x / dx;
- if(fr->rect.y < 0)
- y = 0;
- else
- y = fr->rect.y / dy;
- maxx = r_east(&fr->rect) / dx;
- maxy = r_south(&fr->rect) / dy;
- for(j = y; j < my && j < maxy; j++)
- for(i = x; i < mx && i < maxx; i++)
- bit_twiddle(field, mwidth, i, j, False);
- }
- for(y = 0; y < my; y++)
- for(x = 0; x < mx; x++) {
- if(bit_get(field, mwidth, x, y)) {
- for(i = x; (i < mx) && bit_get(field, mwidth, i, y); i++);
- for(j = y; (j < my) && bit_get(field, mwidth, x, j); j++);
- if(((i - x) * (j - y) > (p2.x - p1.x) * (p2.y - p1.y))
- && (i - x > cx) && (j - y > cy))
- {
- fit = True;
- p1.x = x;
- p1.y = y;
- p2.x = i;
- p2.y = j;
- }
- }
- }
- if(fit) {
- p1.x *= dx;
- p1.y *= dy;
- }
- if(fit && (p1.x + f->rect.width < r_south(&a->rect)))
- f->rect.x = p1.x;
- else {
- diff = a->rect.width - f->rect.width;
- f->rect.x = a->rect.x + (random() % (diff ? diff : 1));
- }
- if(fit && (p1.y + f->rect.height < (r_south(&a->rect))))
- f->rect.y = p1.y;
- else {
- diff = a->rect.height - f->rect.height;
- f->rect.y = a->rect.y + (random() % (diff ? diff : 1));
- }
-
- rects = rects_of_view(a->view, &num, nil);
- snap_rect(rects, num, &f->rect, &align, snap);
- if(rects)
- free(rects);
-}
-
-void
-focus_area(Area *a) {
- Frame *f;
- View *v;
- Area *old_a;
- int i;
-
- v = a->view;
- f = a->sel;
- old_a = v->sel;
-
- v->sel = a;
-
- if((old_a)
- && (a->floating != old_a->floating))
- v->revert = old_a;
-
- if(v != screen->sel)
- return;
-
- if(f)
- focus_client(f->client);
- else
- focus_client(nil);
-
- if(a != old_a) {
- i = 0;
- for(a = v->area; a != v->sel; a = a->next)
- i++;
- if(i)
- write_event("ColumnFocus %d\n", i);
- else
- write_event("FocusFloating\n");
- if(a->frame)
- write_event("ClientFocus 0x%x\n", a->sel->client->win);
- }
-}
-
-char *
-select_area(Area *a, char *arg) {
- Area *new;
- uint i;
- Frame *p, *f;
- View *v;
- static char Ebadvalue[] = "bad value";
-
- v = a->view;
- f = a->sel;
- if(!strncmp(arg, "toggle", 7)) {
- if(!a->floating)
- new = v->area;
- else if(v->revert)
- new = v->revert;
- else
- new = v->area->next;
- } else if(!strncmp(arg, "left", 5)) {
- if(a->floating)
- return Ebadvalue;
- for(new=v->area->next; new->next; new=new->next)
- if(new->next == a) break;
- } else if(!strncmp(arg, "right", 5)) {
- if(a->floating)
- return Ebadvalue;
- new = a->next ? a->next : v->area->next;
- }
- else if(!strncmp(arg, "up", 3)) {
- if(!f)
- return Ebadvalue;
- for(p=a->frame; p->anext; p=p->anext)
- if(p->anext == f) break;
- goto focus_frame;
- }
- else if(!strncmp(arg, "down", 5)) {
- if(!f)
- return Ebadvalue;
- p = f->anext ? f->anext : a->frame;
- goto focus_frame;
- }
- else if(!strncmp(arg, "~", 2)) {
- new = v->area;
- }
- else {
- if(sscanf(arg, "%u", &i) != 1 || i == 0)
- return Ebadvalue;
- for(new=v->area->next; new->next; new=new->next)
- if(!--i) break;
- }
- focus_area(new);
- return nil;
-
-focus_frame:
- focus_frame(p, False);
- frame_to_top(p);
- if(v == screen->sel)
- restack_view(v);
- return nil;
-}
diff -r 7ce25d709bbe -r de2320e9f616 bar.c
--- a/bar.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <string.h>
-#include "wmii.h"
-
-Bar *free_bars = nil;
-
-Bar *
-create_bar(Bar **b_link, char *name) {
- static uint id = 1;
- Bar **i, *b = bar_of_name(*b_link, name);;
-
- if(b)
- return b;
- if(free_bars) {
- b = free_bars;
- free_bars = b->next;
- memset(b, 0, sizeof(*b));
- }
- else
- b = emallocz(sizeof(Bar));
- b->id = id++;
- strncpy(b->name, name, sizeof(b->name));
- b->brush = screen->bbrush;
- b->brush.color = def.normcolor;
- for(i = b_link; *i; i = &(*i)->next)
- if(strcmp((*i)->name, name) >= 0)
- break;
- b->next = *i;
- *i = b;
-
- return b;
-}
-
-void
-destroy_bar(Bar **b_link, Bar *b) {
- Bar **p;
-
- for(p = b_link; *p; p = &(*p)->next)
- if(*p == b) break;
- *p = b->next;
- b->next = free_bars;
- free_bars = b;
-}
-
-void
-resize_bar(WMScreen *s) {
- View *v;
-
- s->brect = s->rect;
- s->brect.height = labelh(&def.font);
- s->brect.y = s->rect.height - s->brect.height;
- XMoveResizeWindow(blz.dpy, s->barwin, s->brect.x, s->brect.y, s->brect.width, s->brect.height);
- XSync(blz.dpy, False);
- draw_bar(s);
- for(v = view; v; v = v->next)
- arrange_view(v);
-}
-
-void
-draw_bar(WMScreen *s) {
- uint width, tw, nb, size;
- float shrink;
- Bar *b, *tb, *largest, **pb;
-
- draw_tile(&s->bbrush);
- if(!s->bar[BarLeft] && !s->bar[BarRight])
- goto MapBar;
-
- largest = b = tb = nil;
- tw = width = nb = size = 0;
- for(nb = 0; nb < nelem(s->bar); nb++)
- for(b = s->bar[nb]; b; b=b->next) {
- b->brush.rect.x = b->brush.rect.y = 0;
- b->brush.rect.width = def.font.height & ~1;
- if(b->text && strlen(b->text))
- b->brush.rect.width += textwidth(b->brush.font, b->text);
- b->brush.rect.height = s->brect.height;
- width += b->brush.rect.width;
- }
- /* Not enough room. Shrink bars until they all fit */
- if(width > s->brect.width) {
- for(nb = 0; nb < nelem(s->bar); nb++)
- for(b = s->bar[nb]; b; b=b->next) {
- for(pb = &largest; *pb; pb = &(*pb)->smaller)
- if((*pb)->brush.rect.width < b->brush.rect.width)
- break;
- b->smaller = *pb;
- *pb = b;
- }
- for(tb = largest; tb; tb = tb->smaller) {
- width -= tb->brush.rect.width;
- tw += tb->brush.rect.width;
- shrink = (s->brect.width - width) / (float)tw;
- if(tb->smaller)
- if(tb->brush.rect.width * shrink >= tb->smaller->brush.rect.width)
- break;
- }
- if(tb)
- for(b = largest; b != tb->smaller; b = b->smaller)
- b->brush.rect.width = (int)(b->brush.rect.width * shrink);
- width += tw * shrink;
- tb = nil;
- }
- for(nb = 0; nb < nelem(s->bar); nb++)
- for(b = s->bar[nb]; b; tb=b, b=b->next) {
- if(b == s->bar[BarRight]) {
- b->brush.align = EAST;
- b->brush.rect.width += (s->brect.width - width);
- }else
- b->brush.align = CENTER;
- if(tb)
- b->brush.rect.x = tb->brush.rect.x + tb->brush.rect.width;
- draw_label(&b->brush, b->text);
- draw_border(&b->brush);
- }
-MapBar:
- XCopyArea(blz.dpy, s->bbrush.drawable, s->barwin, s->bbrush.gc, 0, 0,
- s->brect.width, s->brect.height, 0, 0);
- XSync(blz.dpy, False);
-}
-
-Bar *
-bar_of_name(Bar *b_link, const char *name) {
- static char buf[256];
- Bar *b;
-
- strncpy(buf, name, sizeof(buf));
- for(b = b_link; b; b = b->next)
- if(!strncmp(b->name, name, sizeof(b->name))) break;
- return b;
-}
diff -r 7ce25d709bbe -r de2320e9f616 client.c
--- a/client.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,958 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xatom.h>
-#include "wmii.h"
-
-static void update_client_name(Client *c);
-
-static char Ebadcmd[] = "bad command",
- Ebadvalue[] = "bad value";
-
-enum {
- ClientMask =
- StructureNotifyMask
- | PropertyChangeMask
- | EnterWindowMask
- | FocusChangeMask,
- ButtonMask =
- ButtonPressMask | ButtonReleaseMask
-};
-
-Client *
-create_client(Window w, XWindowAttributes *wa) {
- Client **t, *c;
- XSetWindowAttributes fwa;
-
- c = emallocz(sizeof(Client));
- c->win = w;
- c->rect.x = wa->x;
- c->rect.y = wa->y;
- c->border = wa->border_width;
- c->rect.width = wa->width;
- c->rect.height = wa->height;
-
- c->proto = win_proto(c->win);
- prop_client(c, XA_WM_TRANSIENT_FOR);
- prop_client(c, XA_WM_NORMAL_HINTS);
- prop_client(c, XA_WM_HINTS);
- prop_client(c, XA_WM_NAME);
-
- XSetWindowBorderWidth(blz.dpy, c->win, 0);
- XAddToSaveSet(blz.dpy, c->win);
-
- fwa.override_redirect = True;
- fwa.background_pixmap = ParentRelative;
- fwa.backing_store = Always;
- fwa.event_mask =
- SubstructureRedirectMask
- | SubstructureNotifyMask
- | ExposureMask
- | EnterWindowMask
- | PointerMotionMask
- | KeyPressMask
- | ButtonPressMask
- | ButtonReleaseMask;
- c->framewin = XCreateWindow(
- /* display */ blz.dpy,
- /* parent */ blz.root,
- /* x */ c->rect.x,
- /* y */ c->rect.y,
- /* width */ c->rect.width + 2 * def.border,
- /* height */ c->rect.height + def.border + labelh(&def.font),
- /* border */ 0,
- /* depth */ DefaultDepth(blz.dpy, blz.screen),
- /* class */ CopyFromParent,
- /* visual */ DefaultVisual(blz.dpy, blz.screen),
- /* valuemask */ CWOverrideRedirect | CWEventMask | CWBackPixmap | CWBackingStore,
- /* attributes */&fwa
- );
-
- c->gc = XCreateGC(blz.dpy, c->framewin, 0, 0);
- XSync(blz.dpy, False);
-
- for(t=&client ;; t=&(*t)->next)
- if(!*t) {
- c->next = *t;
- *t = c;
- break;
- }
-
- write_event("CreateClient 0x%x\n", c->win);
- return c;
-}
-
-static int
-dummy_error_handler(Display *dpy, XErrorEvent *error) {
- return 0;
-}
-
-void
-destroy_client(Client *c) {
- char *dummy;
- Client **tc;
- XEvent ev;
-
- XGrabServer(blz.dpy);
- /* In case the client is already unmapped */
- XSetErrorHandler(dummy_error_handler);
-
- for(tc=&client; *tc; tc=&(*tc)->next)
- if(*tc == c) {
- *tc = c->next;
- break;
- }
-
- dummy = nil;
- update_client_views(c, &dummy);
-
- unmap_client(c, WithdrawnState);
- gravitate_client(c, True);
- reparent_client(c, blz.root, c->rect.x, c->rect.y);
-
- XFreeGC(blz.dpy, c->gc);
- XDestroyWindow(blz.dpy, c->framewin);
- XSync(blz.dpy, False);
-
- XSetErrorHandler(wmii_error_handler);
- XUngrabServer(blz.dpy);
- flushevents(EnterWindowMask, False);
-
- while(XCheckMaskEvent(blz.dpy, StructureNotifyMask, &ev))
- if(ev.type != UnmapNotify || ev.xunmap.window != c->win)
- dispatch_event(&ev);
-
- write_event("DestroyClient 0x%x\n", c->win);
- free(c);
-}
-
-void
-manage_client(Client *c) {
- XTextProperty tags = { 0 };
- Client *trans;
-
- XGetTextProperty(blz.dpy, c->win, &tags, atom[TagsAtom]);
-
- if((trans = client_of_win(c->trans)))
- strncpy(c->tags, trans->tags, sizeof(c->tags));
- else if(tags.nitems)
- strncpy(c->tags, (char *)tags.value, sizeof(c->tags));
- XFree(tags.value);
-
- gravitate_client(c, False);
- reparent_client(c, c->framewin, def.border, labelh(&def.font));
-
- if(!strlen(c->tags))
- apply_rules(c);
- else
- apply_tags(c, c->tags);
-
- if(!starting)
- update_views();
- XSync(blz.dpy, False);
-
- if(c->sel->view == screen->sel)
- focus(c, True);
- flushevents(EnterWindowMask, False);
-}
-
-Client *
-sel_client() {
- if(screen->sel && screen->sel->sel->sel)
- return screen->sel->sel->sel->client;
- return nil;
-}
-
-Client *
-client_of_win(Window w) {
- Client *c;
- for(c=client; c; c=c->next)
- if(c->win == w) break;
- return c;
-}
-
-Frame *
-frame_of_win(Window w) {
- Client *c;
- for(c=client; c; c=c->next)
- if(c->framewin == w) break;
- if(c)
- return c->sel;
- return nil;
-}
-
-static void
-update_client_name(Client *c) {
- XTextProperty name;
- XClassHint ch;
- int n;
- char **list = nil;
-
- name.nitems = 0;
- c->name[0] = 0;
- XGetTextProperty(blz.dpy, c->win, &name, atom[NetWMName]);
- if(!name.nitems)
- XGetWMName(blz.dpy, c->win, &name);
- if(!name.nitems)
- return;
- if(name.encoding == XA_STRING)
- strncpy(c->name, (char *)name.value, sizeof(c->name));
- else {
- if(XmbTextPropertyToTextList(blz.dpy, &name, &list, &n) >= Success
- && n > 0 && *list)
- {
- strncpy(c->name, *list, sizeof(c->name));
- XFreeStringList(list);
- }
- }
- XFree(name.value);
- if(XGetClassHint(blz.dpy, c->win, &ch)) {
- snprintf(c->props, sizeof(c->props),
- "%s:%s:%s",
- str_nil(ch.res_class),
- str_nil(ch.res_name),
- c->name);
- if(ch.res_class)
- XFree(ch.res_class);
- if(ch.res_name)
- XFree(ch.res_name);
- }
-}
-
-void
-update_client_grab(Client *c) {
- Frame *f;
- f = c->sel;
- if((f->client != sel_client())
- || (f->area->floating && f != f->area->stack)) {
- if(verbose)
- fprintf(stderr, "update_client_grab(%p) AnyButton => %s\n", c, str_nil(c->name));
- grab_button(c->framewin, AnyButton, AnyModifier);
- }else {
- if(verbose)
- fprintf(stderr, "update_client_grab(%p) def.mod => %s\n", c, str_nil(c->name));
- XUngrabButton(blz.dpy, AnyButton, AnyModifier, c->framewin);
- grab_button(c->framewin, Button1, def.mod);
- grab_button(c->framewin, Button3, def.mod);
- }
-}
-
-void
-set_client_state(Client * c, int state) {
- long data[] = { state, None };
- XChangeProperty(
- /* display */ blz.dpy,
- /* parent */ c->win,
- /* property */ atom[WMState],
- /* type */ atom[WMState],
- /* format */ 32,
- /* mode */ PropModeReplace,
- /* data */ (uchar *) data,
- /* npositions */2
- );
-}
-
-void
-map_client(Client *c) {
- if(!c->mapped) {
- XSelectInput(blz.dpy, c->win, ClientMask & ~StructureNotifyMask);
- XMapWindow(blz.dpy, c->win);
- XSelectInput(blz.dpy, c->win, ClientMask);
- set_client_state(c, NormalState);
- c->mapped = 1;
- }
-}
-
-void
-unmap_client(Client *c, int state) {
- if(c->mapped) {
- c->unmapped++;
- XSelectInput(blz.dpy, c->win, ClientMask & ~StructureNotifyMask);
- XUnmapWindow(blz.dpy, c->win);
- XSelectInput(blz.dpy, c->win, ClientMask);
- set_client_state(c, state);
- c->mapped = 0;
- }
-}
-
-void
-map_frame(Client *c) {
- if(!c->frame_mapped) {
- XMapWindow(blz.dpy, c->framewin);
- c->frame_mapped = True;
- }
-}
-
-void
-unmap_frame(Client *c) {
- if(c->frame_mapped) {
- XUnmapWindow(blz.dpy, c->framewin);
- c->frame_mapped = False;
- }
-}
-
-void
-reparent_client(Client *c, Window w, int x, int y) {
- XSelectInput(blz.dpy, c->win, ClientMask & ~StructureNotifyMask);
- XReparentWindow(blz.dpy, c->win, w, x, y);
- XSelectInput(blz.dpy, c->win, ClientMask);
-}
-
-void
-set_cursor(Client *c, Cursor cur) {
- XSetWindowAttributes wa;
-
- if(c->cursor != cur) {
- c->cursor = cur;
- wa.cursor = cur;
- XChangeWindowAttributes(blz.dpy, c->framewin, CWCursor, &wa);
- }
-}
-
-void
-configure_client(Client *c) {
- XConfigureEvent e;
- Frame *f;
-
- f = c->sel;
- if(!f)
- return;
-
- e.type = ConfigureNotify;
- e.event = c->win;
- e.window = c->win;
- e.x = f->crect.x + f->rect.x - c->border;
- e.y = f->crect.y + f->rect.y - c->border;
- e.width = f->crect.width;
- e.height = f->crect.height;
- e.border_width = c->border;
- e.above = None;
- e.override_redirect = False;
- XSendEvent(blz.dpy, c->win, False,
- StructureNotifyMask, (XEvent *) & e);
- XSync(blz.dpy, False);
-}
-
-static void
-send_client_message(Window w, Atom a, long value) {
- XEvent e;
-
- e.type = ClientMessage;
- e.xclient.window = w;
- e.xclient.message_type = a;
- e.xclient.format = 32;
- e.xclient.data.l[0] = value;
- e.xclient.data.l[1] = CurrentTime;
- XSendEvent(blz.dpy, w, False, NoEventMask, &e);
- XSync(blz.dpy, False);
-}
-
-void
-kill_client(Client * c) {
- if(c->proto & WM_PROTOCOL_DELWIN)
- send_client_message(c->win, atom[WMProtocols], atom[WMDelete]);
- else
- XKillClient(blz.dpy, c->win);
-}
-
-static void
-set_urgent(Client *c, Bool urgent, Bool write) {
- XWMHints *wmh;
- char *cwrite, *cnot;
- Frame *f, *ff;
- Area *a;
-
- cwrite = "Client";
- if(write)
- cwrite = "Manager";
- cnot = "Not";
- if(urgent)
- cnot = "";
-
- if(urgent != c->urgent) {
- write_event("%sUrgent 0x%x %s\n", cnot, c->win, cwrite);
- c->urgent = urgent;
- if(c->sel) {
- if(c->sel->view == screen->sel)
- draw_frame(c->sel);
- if(!urgent || c->sel->view != screen->sel)
- for(f=c->frame; f; f=f->cnext) {
- for(a=f->view->area; a; a=a->next)
- for(ff=a->frame; ff; ff=ff->anext)
- if(ff->client->urgent) break;
- if(!ff)
- write_event("%sUrgentTag %s %s\n", cnot, cwrite, f->view->name);
- }
- }
- }
-
- if(write) {
- wmh = XGetWMHints(blz.dpy, c->win);
- if(wmh) {
- if(urgent)
- wmh->flags |= XUrgencyHint;
- else
- wmh->flags &= ~XUrgencyHint;
- XSetWMHints(blz.dpy, c->win, wmh);
- XFree(wmh);
- }
- }
-}
-
-void
-prop_client(Client *c, Atom a) {
- XWMHints *wmh;
- long msize;
-
- if(a == atom[WMProtocols])
- c->proto = win_proto(c->win);
- else if(a== atom[NetWMName]) {
-wmname:
- update_client_name(c);
- if(c->frame)
- draw_frame(c->sel);
- }else switch (a) {
- case XA_WM_TRANSIENT_FOR:
- XGetTransientForHint(blz.dpy, c->win, &c->trans);
- break;
- case XA_WM_NORMAL_HINTS:
- if(!XGetWMNormalHints(blz.dpy, c->win, &c->size, &msize) || !c->size.flags)
- c->size.flags = PSize;
- c->fixedsize = False;
- if((c->size.flags & PMinSize) && (c->size.flags & PMaxSize)
- &&(c->size.min_width == c->size.max_width)
- &&(c->size.min_height == c->size.max_height))
- c->fixedsize = True;
- break;
- case XA_WM_HINTS:
- wmh = XGetWMHints(blz.dpy, c->win);
- if(wmh) {
- set_urgent(c, (wmh->flags & XUrgencyHint) != 0, False);
- XFree(wmh);
- }
- break;
- case XA_WM_NAME:
- goto wmname;
- }
-}
-
-void
-gravitate_client(Client *c, Bool invert) {
- int dx, dy;
- int gravity;
-
- gravity = NorthWestGravity;
- if(c->size.flags & PWinGravity) {
- gravity = c->size.win_gravity;
- }
-
- dy = 0;
- switch (gravity) {
- case StaticGravity:
- case NorthWestGravity:
- case NorthGravity:
- case NorthEastGravity:
- dy = labelh(&def.font);
- break;
- case EastGravity:
- case CenterGravity:
- case WestGravity:
- dy = -(c->rect.height / 2) + labelh(&def.font);
- break;
- case SouthEastGravity:
- case SouthGravity:
- case SouthWestGravity:
- dy = -c->rect.height;
- break;
- default:
- break;
- }
-
- dx = 0;
- switch (gravity) {
- case StaticGravity:
- case NorthWestGravity:
- case WestGravity:
- case SouthWestGravity:
- dx = def.border;
- break;
- case NorthGravity:
- case CenterGravity:
- case SouthGravity:
- dx = -(c->rect.width / 2) + def.border;
- break;
- case NorthEastGravity:
- case EastGravity:
- case SouthEastGravity:
- dx = -(c->rect.width + def.border);
- break;
- default:
- break;
- }
-
- if(invert) {
- dx = -dx;
- dy = -dy;
- }
- c->rect.x += dx;
- c->rect.y += dy;
-}
-
-void
-apply_sizehints(Client *c, XRectangle *r, Bool floating, Bool frame, BlitzAlign sticky) {
- XSizeHints *s;
- XRectangle orig;
- uint bw, bh;
-
- s = &c->size;
- orig = *r;
- if(frame)
- frame2client(r);
- bw = 0;
- bh = 0;
-
- if(s->flags & PMinSize) {
- bw = s->min_width;
- bh = s->min_height;
- if(floating) {
- if(r->width < s->min_width)
- r->width = s->min_width;
- if(r->height < s->min_height)
- r->height = s->min_height;
- }
- }
- if(s->flags & PMaxSize) {
- if(r->width > s->max_width)
- r->width = s->max_width;
- if(r->height > s->max_height)
- r->height = s->max_height;
- }
-
- if(s->flags & PBaseSize) {
- bw = s->base_width;
- bh = s->base_height;
- }
-
- if(s->flags & PResizeInc) {
- if(s->width_inc > 0)
- r->width -= (r->width - bw) % s->width_inc;
- if(s->height_inc > 0)
- r->height -= (r->height - bh) % s->height_inc;
- }
-
- if((s->flags & (PBaseSize|PMinSize)) == PMinSize) {
- bw = 0;
- bh = 0;
- }
-
- if(s->flags & PAspect) {
- double min, max, initial;
-
- min = (double)s->min_aspect.x / s->min_aspect.y;
- max = (double)s->max_aspect.x / s->max_aspect.y;
- initial = (double)(r->width - bw) / (r->height - bh);
- if(initial < min)
- r->height = bh + (r->width - bw) / min;
- if(initial > max)
- r->width = bw + (r->height - bh) * max;
- }
-
- if(frame)
- client2frame(r);
-
- if(!(s->flags & PMinSize) || !floating) {
- if(r->width > orig.width)
- r->width = orig.width;
- if(r->height > orig.height)
- r->height = orig.height;
- }
-
- if((sticky & (EAST|WEST)) == EAST)
- r->x = r_east(&orig) - r->width;
- if((sticky & (NORTH|SOUTH)) == SOUTH)
- r->y = r_south(&orig) - r->height;
-}
-
-void
-focus(Client *c, Bool restack) {
- View *v;
- Frame *f;
-
- f = c->sel;
- if(!f)
- return;
-
- v = f->area->view;
- if(v != screen->sel)
- focus_view(screen, v);
- focus_frame(c->sel, restack);
-}
-
-void
-focus_client(Client *c) {
- flushevents(FocusChangeMask, True);
-
- if(verbose)
- fprintf(stderr, "focus_client(%p) => %s\n", c, (c ? c->name : nil));
- if(screen->focus != c) {
- if(c && verbose)
- fprintf(stderr, "\t%s => %s\n", (screen->focus ? screen->focus->name : "<nil>"),
- (c ? c->name : "<nil>"));
- if(c) {
- XSetInputFocus(blz.dpy, c->win, RevertToParent, CurrentTime);
- update_client_grab(c);
- }else
- XSetInputFocus(blz.dpy, screen->barwin, RevertToParent, CurrentTime);
- }
-
- flushevents(FocusChangeMask, True);
-}
-
-void
-resize_client(Client *c, XRectangle *r) {
- Frame *f;
-
- f = c->sel;
- resize_frame(f, r);
-
- if(f->area->view != screen->sel) {
- unmap_client(c, IconicState);
- unmap_frame(c);
- return;
- }
-
- c->rect = f->crect;
- c->rect.x += f->rect.x;
- c->rect.y += f->rect.y;
- if((f->area->mode == Colmax)
- && (f->area->sel != f)) {
- unmap_frame(c);
- unmap_client(c, IconicState);
- }else if(f->collapsed) {
- XMoveResizeWindow(blz.dpy, c->framewin,
- f->rect.x, f->rect.y,
- f->rect.width, f->rect.height);
- map_frame(c);
- unmap_client(c, IconicState);
- }else {
- XMoveResizeWindow(blz.dpy, c->win,
- f->crect.x, f->crect.y,
- f->crect.width, f->crect.height);
- map_client(c);
- XMoveResizeWindow(blz.dpy, c->framewin,
- f->rect.x, f->rect.y,
- f->rect.width, f->rect.height);
- map_frame(c);
- configure_client(c);
- }
-
- flushevents(FocusChangeMask|ExposureMask, True);
-}
-
-void
-newcol_client(Client *c, char *arg) {
- Frame *f = c->sel;
- Area *to, *a = f->area;
- View *v = a->view;
-
- if(a->floating)
- return;
- if(!f->anext && f == a->frame)
- return;
- if(!strncmp(arg, "prev", 5)) {
- for(to=v->area; to; to=to->next)
- if(to->next == a) break;
- to = new_column(v, to, 0);
- send_to_area(to, f);
- }
- else if(!strncmp(arg, "next", 5)) {
- to = new_column(v, a, 0);
- send_to_area(to, f);
- }
- else
- return;
- flushevents(EnterWindowMask, False);
-}
-
-void
-move_client(Client *c, char *arg) {
- Frame *f = c->sel;
- XRectangle new = f->rect;
- int x, y;
-
- if(sscanf(arg, "%d %d", &x, &y) != 2)
- return;
- new.x += x;
- new.y += y;
- if(!f->area->floating)
- resize_column(f->client, &new);
- else
- resize_client(f->client, &new);
-}
-
-void
-size_client(Client *c, char *arg) {
- Frame *f = c->sel;
- XRectangle new = f->rect;
- int w, h;
-
- if(sscanf(arg, "%d %d", &w, &h) != 2)
- return;
- new.width += w;
- new.height += h;
- if(!f->area->floating)
- resize_column(f->client, &new);
- else
- resize_client(f->client, &new);
-}
-
-char *
-send_client(Frame *f, char *arg, Bool swap) {
- Area *to, *a;
- Client *c;
- Frame *tf;
- View *v;
- Bool before;
- int j;
-
- a = f->area;
- v = a->view;
- c = f->client;
- if(!strncmp(arg, "toggle", 7)) {
- if(!a->floating)
- to = v->area;
- else if(c->revert && !c->revert->floating)
- to = c->revert;
- else
- to = v->area->next;
- goto send_area;
- }else if(!a->floating) {
- if(!strncmp(arg, "left", 5)) {
- if(a->floating)
- return Ebadvalue;
- for(to=v->area->next; to; to=to->next)
- if(a == to->next) break;
- if(!to && !swap && (f->anext || f != a->frame))
- to=new_column(v, v->area, 0);
- goto send_area;
- }
- else if(!strncmp(arg, "right", 5)) {
- if(a->floating)
- return Ebadvalue;
- to = a->next;
- if(!to && !swap && (f->anext || f != a->frame))
- to = new_column(v, a, 0);
- goto send_area;
- }
- else if(!strncmp(arg, "up", 3)) {
- for(tf=a->frame; tf; tf=tf->anext)
- if(tf->anext == f) break;
- before = True;
- goto send_frame;
- }
- else if(!strncmp(arg, "down", 5)) {
- tf = f->anext;
- before = False;
- goto send_frame;
- }
- else {
- if(sscanf(arg, "%d", &j) != 1)
- return Ebadvalue;
- for(to=v->area; to; to=to->next)
- if(!--j) break;
- goto send_area;
- }
- }
- return Ebadvalue;
-
-send_frame:
- if(!tf)
- return Ebadvalue;
- if(!swap) {
- remove_frame(f);
- insert_frame(tf, f, before);
- }else
- swap_frames(f, tf);
- arrange_column(a, False);
-
- flushevents(EnterWindowMask, False);
- focus_frame(f, True);
- update_views();
- return nil;
-
-send_area:
- if(!to)
- return Ebadvalue;
- if(!swap)
- send_to_area(to, f);
- else if(to->sel)
- swap_frames(f, to->sel);
-
- flushevents(EnterWindowMask, False);
- focus_frame(f, True);
- update_views();
- return nil;
-}
-
-void
-update_client_views(Client *c, char **tags) {
- Frame **fp, *f;
- int cmp;
-
- fp = &c->frame;
- while(*fp || *tags) {
- while(*fp) {
- if(*tags) {
- cmp = strcmp((*fp)->view->name, *tags);
- if(cmp >= 0)
- break;
- }
-
- f = *fp;
- detach_from_area(f);
- *fp = f->cnext;
- if(c->sel == f)
- c->sel = *fp;
- free(f);
- }
- if(*tags) {
- if(!*fp || cmp > 0) {
- f = create_frame(c, get_view(*tags));
- if(f->view == screen->sel || !c->sel)
- c->sel = f;
- attach_to_view(f->view, f);
- f->cnext = *fp;
- *fp = f;
- }
- if(*fp) fp=&(*fp)->cnext;
- tags++;
- }
- }
- update_views();
-}
-
-static int
-compare_tags(const void *a, const void *b) {
- return strcmp(*(char **)a, *(char **)b);
-}
-
-void
-apply_tags(Client *c, const char *tags) {
- uint i, j, k, n;
- Bool add;
- char buf[512], last;
- char *toks[32], *cur;
-
- buf[0] = 0;
- for(n = 0; tags[n]; n++)
- if(tags[n] != ' ' && tags[n] != '\t') break;
- if(tags[n] == '+' || tags[n] == '-')
- strncpy(buf, c->tags, sizeof(c->tags));
- strlcat(buf, &tags[n], sizeof(buf));
- trim(buf, " \t/");
-
- n = 0;
- j = 0;
- add = True;
- if(buf[0] == '+')
- n++;
- else if(buf[0] == '-') {
- n++;
- add = False;
- }
- while(buf[n] && n < sizeof(buf) && j < 32) {
- for(i = n; i < sizeof(buf) - 1; i++)
- if(buf[i] == '+'
- || buf[i] == '-'
- || buf[i] == '\0')
- break;
- last = buf[i];
- buf[i] = '\0';
-
- cur = nil;
- if(!strncmp(&buf[n], "~", 2))
- c->floating = add;
- else if(!strncmp(&buf[n], "!", 2))
- cur = view ? screen->sel->name : "nil";
- else if(strncmp(&buf[n], "sel", 4)
- && strncmp(&buf[n], ".", 2)
- && strncmp(&buf[n], "..", 3))
- cur = &buf[n];
-
- n = i + 1;
- if(cur) {
- if(add)
- toks[j++] = cur;
- else {
- for(i = 0, k = 0; i < j; i++)
- if(strcmp(toks[i], cur))
- toks[k++] = toks[i];
- j = k;
- }
- }
-
- switch(last) {
- case '+':
- add = True;
- break;
- case '-':
- add = False;
- break;
- case '\0':
- buf[n] = '\0';
- break;
- }
- }
-
- c->tags[0] = '\0';
- if(!j)
- return;
- qsort(toks, j, sizeof(char *), compare_tags);
-
- for(i=0, n=0; i < j; i++)
- if(!n || strcmp(toks[i], toks[n-1])) {
- if(i)
- strlcat(c->tags, "+", sizeof(c->tags));
- strlcat(c->tags, toks[i], sizeof(c->tags));
- toks[n++] = toks[i];
- }
- toks[n] = nil;
-
- update_client_views(c, toks);
- XChangeProperty(blz.dpy, c->win, atom[TagsAtom], XA_STRING, 8,
- PropModeReplace, (uchar *)c->tags, strlen(c->tags));
-}
-
-void
-apply_rules(Client *c) {
- Rule *r;
- regmatch_t rm;
-
- if(strlen(c->tags))
- return;
- if(def.tagrules.string)
- for(r=def.tagrules.rule; r; r=r->next)
- if(!regexec(&r->regex, c->props, 1, &rm, 0)) {
- apply_tags(c, r->value);
- if(strlen(c->tags) && strcmp(c->tags, "nil"))
- break;
- }
- if(!strlen(c->tags))
- apply_tags(c, "nil");
-}
-
-char *
-message_client(Client *c, char *message) {
- if(!strncmp(message, "kill", 5))
- kill_client(c);
- else if(!strncmp(message, "Urgent", 7))
- set_urgent(c, True, True);
- else if(!strncmp(message, "NotUrgent", 10))
- set_urgent(c, False, True);
- else
- return Ebadcmd;
- return nil;
-}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/Makefile Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,26 @@
+ROOT=..
+include ${ROOT}/mk/hdr.mk
+
+DIRS = wmii
+TARG = wmii9menu \
+ wmii9rc \
+ wmiiloop \
+ wmiir \
+ wmiistartrc
+
+OFILES = util.o
+FILTER = sed "s|CONFPREFIX|${CONFPREFIX}|g; \
+ s|CONFVERSION|${CONFVERSION}|g; \
+ s|P9PATHS|${P9PATHS}|g; \
+ s|AWKPATH|${AWKPATH}|g"
+
+include ${ROOT}/mk/many.mk
+include ${ROOT}/mk/dir.mk
+
+OWMIIR=${OFILES} ${LIBIXP}
+wmiir.O: ${OWMIIR}
+ ${LINK} $@ $*.o ${OWMIIR}
+
+EXCFLAGS=${INCX11}
+wmii9menu.O:
+ ${LINK} $@ $*.o ${LIBX11}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/util.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/util.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,148 @@
+/* Written by Kris Maglione <fbsdaemon at gmail dot com> */
+/* Public domain */
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+void
+fatal(const char *fmt, ...) {
+ va_list ap;
+ int err;
+
+ err = errno;
+ fprintf(stderr, "%s: fatal: ", argv0);
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ if(fmt[strlen(fmt)-1] == ':')
+ fprintf(stderr, " %s\n", strerror(err));
+ else
+ fprintf(stderr, "\n");
+
+ exit(1);
+}
+
+/* Can't malloc */
+void
+mfatal(char *name, uint size) {
+ const char
+ couldnot[] = ": fatal: Could not ",
+ paren[] = "() ",
+ bytes[] = " bytes\n";
+ char sizestr[8];
+ int i;
+
+ i = sizeof(sizestr);
+ do {
+ sizestr[--i] = '0' + (size%10);
+ size /= 10;
+ } while(size > 0);
+
+ write(1, argv0, strlen(argv0)-1);
+ write(1, couldnot, sizeof(couldnot)-1);
+ write(1, name, strlen(name));
+ write(1, paren, sizeof(paren)-1);
+ write(1, sizestr+i, sizeof(sizestr)-i);
+ write(1, bytes, sizeof(bytes)-1);
+
+ exit(1);
+}
+
+void *
+emalloc(uint size) {
+ void *ret = malloc(size);
+ if(!ret)
+ mfatal("malloc", size);
+ return ret;
+}
+
+void *
+emallocz(uint size) {
+ void *ret = emalloc(size);
+ memset(ret, 0, size);
+ return ret;
+}
+
+void *
+erealloc(void *ptr, uint size) {
+ void *ret = realloc(ptr, size);
+ if(!ret)
+ mfatal("realloc", size);
+ return ret;
+}
+
+char *
+estrdup(const char *str) {
+ void *ret = strdup(str);
+ if(!ret)
+ mfatal("strdup", strlen(str));
+ return ret;
+}
+
+uint
+tokenize(char *res[], uint reslen, char *str, char delim) {
+ char *s;
+ uint i;
+
+ i = 0;
+ s = str;
+ while(i < reslen && *s) {
+ while(*s == delim)
+ *(s++) = '\0';
+ if(*s)
+ res[i++] = s;
+ while(*s && *s != delim)
+ s++;
+ }
+ return i;
+}
+
+int
+max(int a, int b) {
+ if(a > b)
+ return a;
+ return b;
+}
+
+int
+min(int a, int b) {
+ if(a < b)
+ return a;
+ return b;
+}
+
+char *
+str_nil(char *s) {
+ if(s)
+ return s;
+ return "<nil>";
+}
+
+uint
+strlcat(char *dst, const char *src, uint size) {
+ const char *s;
+ char *d;
+ int n, len;
+
+ d = dst;
+ s = src;
+ n = size;
+ while(n-- > 0 && *d != '\0')
+ d++;
+ len = n;
+
+ while(*s != '\0') {
+ if(n-- > 0)
+ *d++ = *s;
+ s++;
+ }
+ if(len > 0)
+ *d = '\0';
+ return size - n - 1;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/Makefile Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,26 @@
+ROOT= ../..
+include ${ROOT}/mk/hdr.mk
+
+TARG = wmii
+
+LIB = ${LIBIXP}
+EXLDFLAGS = -lm ${LIBX11}
+EXCFLAGS = ${INCX11}
+OBJ = area \
+ bar \
+ client \
+ column \
+ draw \
+ event \
+ frame \
+ fs \
+ geom \
+ key \
+ main \
+ mouse \
+ rule \
+ printevent\
+ view \
+ ../util
+
+include ${ROOT}/mk/one.mk
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/area.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/area.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,438 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "wmii.h"
+
+static void place_frame(Frame *f);
+
+Client *
+sel_client_of_area(Area *a) {
+ if(a && a->sel)
+ return a->sel->client;
+ return nil;
+}
+
+Area *
+create_area(View *v, Area *pos, uint w) {
+ static ushort id = 1;
+ uint area_num, col_num, i;
+ uint min_width;
+ Area *a, **p;
+
+ min_width = screen->rect.width/NCOL;
+ p = pos ? &pos->next : &v->area;
+
+ area_num = 0;
+ i = 0;
+ for(a = v->area; a != *p; a = a->next)
+ area_num++, i++;
+ for(; a; a = a->next) area_num++;
+
+ col_num = max((area_num - 1), 0);
+ if(w == 0) {
+ if(col_num) {
+ w = newcolw_of_view(v);
+ if (w == 0)
+ w = screen->rect.width / (col_num + 1);
+ }
+ else w = screen->rect.width;
+ }
+ if(w < min_width)
+ w = min_width;
+ if(col_num && (col_num * min_width + w) > screen->rect.width)
+ return nil;
+ if(pos)
+ scale_view(v, screen->rect.width - w);
+
+ a = emallocz(sizeof(Area));
+ a->view = v;
+ a->id = id++;
+ a->rect = screen->rect;
+ a->rect.height = screen->rect.height - screen->brect.height;
+ a->mode = def.colmode;
+ a->rect.width = w;
+ a->frame = nil;
+ a->sel = nil;
+ a->next = *p;
+ *p = a;
+
+ if(a == v->area)
+ a->floating = True;
+ if((!v->sel) ||
+ (v->sel->floating && v->area->next == a && a->next == nil))
+ focus_area(a);
+
+ if(i)
+ write_event("CreateColumn %d\n", i);
+ return a;
+}
+
+void
+destroy_area(Area *a) {
+ Client *c;
+ Area *ta;
+ View *v;
+ uint i;
+
+ v = a->view;
+
+ if(a->frame)
+ fatal("destroying non-empty area");
+ if(v->revert == a)
+ v->revert = nil;
+ for(c=client; c; c=c->next)
+ if(c->revert == a)
+ c->revert = nil;
+
+ i = 1;
+ for(ta=v->area; ta; ta=ta->next)
+ if(ta->next == a) break;
+ else i++;
+ if(ta) {
+ ta->next = a->next;
+ if(ta->floating && ta->next)
+ ta = ta->next;
+ if(v->sel == a)
+ focus_area(ta);
+ }
+ if(i) write_event("DestroyColumn %d\n", i);
+ free(a);
+}
+
+void
+send_to_area(Area *to, Frame *f) {
+ Area *from;
+ assert(to->view == f->view);
+ from = f->area;
+ if(to->floating != from->floating) {
+ XRectangle temp = f->revert;
+ f->revert = f->rect;
+ f->rect = temp;
+ }
+ f->client->revert = from;
+ detach_from_area(f);
+ attach_to_area(to, f, True);
+}
+
+void
+attach_to_area(Area *a, Frame *f, Bool send) {
+ uint h, n_frame;
+ Frame *ft;
+ Client *c;
+ View *v;
+
+ v = a->view;
+ c = f->client;
+ h = 0;
+
+ f->area = a;
+
+ n_frame = 0;
+ for(ft=a->frame; ft; ft=ft->anext)
+ n_frame++;
+ if(n_frame == 0)
+ n_frame = 1;
+
+ c->floating = a->floating;
+ if(!a->floating)
+ f->rect.height = a->rect.height / n_frame;
+
+ insert_frame(a->sel, f, False);
+
+ if(a->floating)
+ place_frame(f);
+
+ focus_frame(f, False);
+ resize_frame(f, &f->rect);
+ restack_view(a->view);
+ if(!a->floating)
+ arrange_column(a, False);
+ else
+ resize_frame(f, &f->rect);
+
+ update_client_grab(f->client);
+ if(a->frame)
+ assert(a->sel);
+}
+
+void
+detach_from_area(Frame *f) {
+ Frame *pr;
+ Client *c;
+ Area *a;
+ View *v;
+ Area *ta;
+ uint i;
+
+ a = f->area;
+ v = a->view;
+ c = f->client;
+
+ for(pr = a->frame; pr; pr = pr->anext)
+ if(pr->anext == f) break;
+ remove_frame(f);
+
+ if(a->sel == f) {
+ if(!pr)
+ pr = a->frame;
+ if((a->view->sel == a) && (pr))
+ focus_frame(pr, False);
+ else
+ a->sel = pr;
+ }
+
+ if(!a->floating) {
+ if(a->frame)
+ arrange_column(a, False);
+ else {
+ i = 0;
+ for(ta=v->area; ta && ta != a; ta=ta->next)
+ i++;
+ if(v->area->next->next)
+ destroy_area(a);
+ else if(!a->frame && v->area->frame)
+ /* focus floating area if it contains something */
+ focus_area(v->area);
+ arrange_view(v);
+ }
+ }
+ else if(!a->frame) {
+ if(c->trans) {
+ /* focus area of transient, if possible */
+ Client *cl = client_of_win(c->trans);
+ if(cl && cl->frame) {
+ a = cl->sel->area;
+ if(a->view == v)
+ focus_area(a);
+ }
+ }
+ else if(v->area->next->frame)
+ focus_area(v->area->next);
+ }else
+ assert(a->sel);
+}
+
+static void
+bit_twiddle(uint *field, uint width, uint x, uint y, Bool set) {
+ enum { devisor = sizeof(uint) * 8 };
+ uint bx, mask;
+
+ bx = x / devisor;
+ mask = 1 << x % devisor;
+ if(set)
+ field[y*width + bx] |= mask;
+ else
+ field[y*width + bx] &= ~mask;
+}
+
+static Bool
+bit_get(uint *field, uint width, uint x, uint y) {
+ enum { devisor = sizeof(uint) * 8 };
+ uint bx, mask;
+
+ bx = x / devisor;
+ mask = 1 << x % devisor;
+
+ return (field[y*width + bx] & mask) != 0;
+}
+
+static void
+place_frame(Frame *f) {
+ enum { devisor = sizeof(uint) * 8 };
+ enum { dx = 8, dy = 8 };
+ static uint mwidth, mx, my;
+ static uint *field = nil;
+ BlitzAlign align;
+ XPoint p1 = {0, 0};
+ XPoint p2 = {0, 0};
+ XRectangle *rects;
+ Frame *fr;
+ Client *c;
+ Area *a;
+ Bool fit;
+ uint i, j, x, y, cx, cy, maxx, maxy, diff, num;
+ int snap;
+
+ snap = screen->rect.height / 66;
+ num = 0;
+ fit = False;
+ align = CENTER;
+
+ a = f->area;
+ c = f->client;
+
+ if(c->trans)
+ return;
+ if(c->rect.width >= a->rect.width
+ || c->rect.height >= a->rect.height
+ || c->size.flags & USPosition
+ || c->size.flags & PPosition)
+ return;
+ if(!field) {
+ mx = screen->rect.width / dx;
+ my = screen->rect.height / dy;
+ mwidth = ceil((float)mx / devisor);
+ field = emallocz(sizeof(uint) * mwidth * my);
+ }
+ memset(field, ~0, (sizeof(uint) * mwidth * my));
+ for(fr=a->frame; fr; fr=fr->anext) {
+ if(fr == f) {
+ cx = f->rect.width / dx;
+ cy = f->rect.height / dy;
+ continue;
+ }
+ if(fr->rect.x < 0)
+ x = 0;
+ else
+ x = fr->rect.x / dx;
+ if(fr->rect.y < 0)
+ y = 0;
+ else
+ y = fr->rect.y / dy;
+ maxx = r_east(&fr->rect) / dx;
+ maxy = r_south(&fr->rect) / dy;
+ for(j = y; j < my && j < maxy; j++)
+ for(i = x; i < mx && i < maxx; i++)
+ bit_twiddle(field, mwidth, i, j, False);
+ }
+ for(y = 0; y < my; y++)
+ for(x = 0; x < mx; x++) {
+ if(bit_get(field, mwidth, x, y)) {
+ for(i = x; (i < mx) && bit_get(field, mwidth, i, y); i++);
+ for(j = y; (j < my) && bit_get(field, mwidth, x, j); j++);
+ if(((i - x) * (j - y) > (p2.x - p1.x) * (p2.y - p1.y))
+ && (i - x > cx) && (j - y > cy))
+ {
+ fit = True;
+ p1.x = x;
+ p1.y = y;
+ p2.x = i;
+ p2.y = j;
+ }
+ }
+ }
+ if(fit) {
+ p1.x *= dx;
+ p1.y *= dy;
+ }
+ if(fit && (p1.x + f->rect.width < r_south(&a->rect)))
+ f->rect.x = p1.x;
+ else {
+ diff = a->rect.width - f->rect.width;
+ f->rect.x = a->rect.x + (random() % (diff ? diff : 1));
+ }
+ if(fit && (p1.y + f->rect.height < (r_south(&a->rect))))
+ f->rect.y = p1.y;
+ else {
+ diff = a->rect.height - f->rect.height;
+ f->rect.y = a->rect.y + (random() % (diff ? diff : 1));
+ }
+
+ rects = rects_of_view(a->view, &num, nil);
+ snap_rect(rects, num, &f->rect, &align, snap);
+ if(rects)
+ free(rects);
+}
+
+void
+focus_area(Area *a) {
+ Frame *f;
+ View *v;
+ Area *old_a;
+ int i;
+
+ v = a->view;
+ f = a->sel;
+ old_a = v->sel;
+
+ v->sel = a;
+
+ if((old_a)
+ && (a->floating != old_a->floating))
+ v->revert = old_a;
+
+ if(v != screen->sel)
+ return;
+
+ if(f)
+ focus_client(f->client);
+ else
+ focus_client(nil);
+
+ if(a != old_a) {
+ i = 0;
+ for(a = v->area; a != v->sel; a = a->next)
+ i++;
+ if(i)
+ write_event("ColumnFocus %d\n", i);
+ else
+ write_event("FocusFloating\n");
+ if(a->frame)
+ write_event("ClientFocus 0x%x\n", a->sel->client->win);
+ }
+}
+
+char *
+select_area(Area *a, char *arg) {
+ Area *new;
+ uint i;
+ Frame *p, *f;
+ View *v;
+ static char Ebadvalue[] = "bad value";
+
+ v = a->view;
+ f = a->sel;
+ if(!strncmp(arg, "toggle", 7)) {
+ if(!a->floating)
+ new = v->area;
+ else if(v->revert)
+ new = v->revert;
+ else
+ new = v->area->next;
+ } else if(!strncmp(arg, "left", 5)) {
+ if(a->floating)
+ return Ebadvalue;
+ for(new=v->area->next; new->next; new=new->next)
+ if(new->next == a) break;
+ } else if(!strncmp(arg, "right", 5)) {
+ if(a->floating)
+ return Ebadvalue;
+ new = a->next ? a->next : v->area->next;
+ }
+ else if(!strncmp(arg, "up", 3)) {
+ if(!f)
+ return Ebadvalue;
+ for(p=a->frame; p->anext; p=p->anext)
+ if(p->anext == f) break;
+ goto focus_frame;
+ }
+ else if(!strncmp(arg, "down", 5)) {
+ if(!f)
+ return Ebadvalue;
+ p = f->anext ? f->anext : a->frame;
+ goto focus_frame;
+ }
+ else if(!strncmp(arg, "~", 2)) {
+ new = v->area;
+ }
+ else {
+ if(sscanf(arg, "%u", &i) != 1 || i == 0)
+ return Ebadvalue;
+ for(new=v->area->next; new->next; new=new->next)
+ if(!--i) break;
+ }
+ focus_area(new);
+ return nil;
+
+focus_frame:
+ focus_frame(p, False);
+ frame_to_top(p);
+ if(v == screen->sel)
+ restack_view(v);
+ return nil;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/bar.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/bar.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,134 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <string.h>
+#include "wmii.h"
+
+Bar *free_bars = nil;
+
+Bar *
+create_bar(Bar **b_link, char *name) {
+ static uint id = 1;
+ Bar **i, *b = bar_of_name(*b_link, name);;
+
+ if(b)
+ return b;
+ if(free_bars) {
+ b = free_bars;
+ free_bars = b->next;
+ memset(b, 0, sizeof(*b));
+ }
+ else
+ b = emallocz(sizeof(Bar));
+ b->id = id++;
+ strncpy(b->name, name, sizeof(b->name));
+ b->brush = screen->bbrush;
+ b->brush.color = def.normcolor;
+ for(i = b_link; *i; i = &(*i)->next)
+ if(strcmp((*i)->name, name) >= 0)
+ break;
+ b->next = *i;
+ *i = b;
+
+ return b;
+}
+
+void
+destroy_bar(Bar **b_link, Bar *b) {
+ Bar **p;
+
+ for(p = b_link; *p; p = &(*p)->next)
+ if(*p == b) break;
+ *p = b->next;
+ b->next = free_bars;
+ free_bars = b;
+}
+
+void
+resize_bar(WMScreen *s) {
+ View *v;
+
+ s->brect = s->rect;
+ s->brect.height = labelh(&def.font);
+ s->brect.y = s->rect.height - s->brect.height;
+ XMoveResizeWindow(blz.dpy, s->barwin, s->brect.x, s->brect.y, s->brect.width, s->brect.height);
+ XSync(blz.dpy, False);
+ draw_bar(s);
+ for(v = view; v; v = v->next)
+ arrange_view(v);
+}
+
+void
+draw_bar(WMScreen *s) {
+ uint width, tw, nb, size;
+ float shrink;
+ Bar *b, *tb, *largest, **pb;
+
+ draw_tile(&s->bbrush);
+ if(!s->bar[BarLeft] && !s->bar[BarRight])
+ goto MapBar;
+
+ largest = b = tb = nil;
+ tw = width = nb = size = 0;
+ for(nb = 0; nb < nelem(s->bar); nb++)
+ for(b = s->bar[nb]; b; b=b->next) {
+ b->brush.rect.x = b->brush.rect.y = 0;
+ b->brush.rect.width = def.font.height & ~1;
+ if(b->text && strlen(b->text))
+ b->brush.rect.width += textwidth(b->brush.font, b->text);
+ b->brush.rect.height = s->brect.height;
+ width += b->brush.rect.width;
+ }
+ /* Not enough room. Shrink bars until they all fit */
+ if(width > s->brect.width) {
+ for(nb = 0; nb < nelem(s->bar); nb++)
+ for(b = s->bar[nb]; b; b=b->next) {
+ for(pb = &largest; *pb; pb = &(*pb)->smaller)
+ if((*pb)->brush.rect.width < b->brush.rect.width)
+ break;
+ b->smaller = *pb;
+ *pb = b;
+ }
+ for(tb = largest; tb; tb = tb->smaller) {
+ width -= tb->brush.rect.width;
+ tw += tb->brush.rect.width;
+ shrink = (s->brect.width - width) / (float)tw;
+ if(tb->smaller)
+ if(tb->brush.rect.width * shrink >= tb->smaller->brush.rect.width)
+ break;
+ }
+ if(tb)
+ for(b = largest; b != tb->smaller; b = b->smaller)
+ b->brush.rect.width = (int)(b->brush.rect.width * shrink);
+ width += tw * shrink;
+ tb = nil;
+ }
+ for(nb = 0; nb < nelem(s->bar); nb++)
+ for(b = s->bar[nb]; b; tb=b, b=b->next) {
+ if(b == s->bar[BarRight]) {
+ b->brush.align = EAST;
+ b->brush.rect.width += (s->brect.width - width);
+ }else
+ b->brush.align = CENTER;
+ if(tb)
+ b->brush.rect.x = tb->brush.rect.x + tb->brush.rect.width;
+ draw_label(&b->brush, b->text);
+ draw_border(&b->brush);
+ }
+MapBar:
+ XCopyArea(blz.dpy, s->bbrush.drawable, s->barwin, s->bbrush.gc, 0, 0,
+ s->brect.width, s->brect.height, 0, 0);
+ XSync(blz.dpy, False);
+}
+
+Bar *
+bar_of_name(Bar *b_link, const char *name) {
+ static char buf[256];
+ Bar *b;
+
+ strncpy(buf, name, sizeof(buf));
+ for(b = b_link; b; b = b->next)
+ if(!strncmp(b->name, name, sizeof(b->name))) break;
+ return b;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/client.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/client.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,958 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xatom.h>
+#include "wmii.h"
+
+static void update_client_name(Client *c);
+
+static char Ebadcmd[] = "bad command",
+ Ebadvalue[] = "bad value";
+
+enum {
+ ClientMask =
+ StructureNotifyMask
+ | PropertyChangeMask
+ | EnterWindowMask
+ | FocusChangeMask,
+ ButtonMask =
+ ButtonPressMask | ButtonReleaseMask
+};
+
+Client *
+create_client(Window w, XWindowAttributes *wa) {
+ Client **t, *c;
+ XSetWindowAttributes fwa;
+
+ c = emallocz(sizeof(Client));
+ c->win = w;
+ c->rect.x = wa->x;
+ c->rect.y = wa->y;
+ c->border = wa->border_width;
+ c->rect.width = wa->width;
+ c->rect.height = wa->height;
+
+ c->proto = win_proto(c->win);
+ prop_client(c, XA_WM_TRANSIENT_FOR);
+ prop_client(c, XA_WM_NORMAL_HINTS);
+ prop_client(c, XA_WM_HINTS);
+ prop_client(c, XA_WM_NAME);
+
+ XSetWindowBorderWidth(blz.dpy, c->win, 0);
+ XAddToSaveSet(blz.dpy, c->win);
+
+ fwa.override_redirect = True;
+ fwa.background_pixmap = ParentRelative;
+ fwa.backing_store = Always;
+ fwa.event_mask =
+ SubstructureRedirectMask
+ | SubstructureNotifyMask
+ | ExposureMask
+ | EnterWindowMask
+ | PointerMotionMask
+ | KeyPressMask
+ | ButtonPressMask
+ | ButtonReleaseMask;
+ c->framewin = XCreateWindow(
+ /* display */ blz.dpy,
+ /* parent */ blz.root,
+ /* x */ c->rect.x,
+ /* y */ c->rect.y,
+ /* width */ c->rect.width + 2 * def.border,
+ /* height */ c->rect.height + def.border + labelh(&def.font),
+ /* border */ 0,
+ /* depth */ DefaultDepth(blz.dpy, blz.screen),
+ /* class */ CopyFromParent,
+ /* visual */ DefaultVisual(blz.dpy, blz.screen),
+ /* valuemask */ CWOverrideRedirect | CWEventMask | CWBackPixmap | CWBackingStore,
+ /* attributes */&fwa
+ );
+
+ c->gc = XCreateGC(blz.dpy, c->framewin, 0, 0);
+ XSync(blz.dpy, False);
+
+ for(t=&client ;; t=&(*t)->next)
+ if(!*t) {
+ c->next = *t;
+ *t = c;
+ break;
+ }
+
+ write_event("CreateClient 0x%x\n", c->win);
+ return c;
+}
+
+static int
+dummy_error_handler(Display *dpy, XErrorEvent *error) {
+ return 0;
+}
+
+void
+destroy_client(Client *c) {
+ char *dummy;
+ Client **tc;
+ XEvent ev;
+
+ XGrabServer(blz.dpy);
+ /* In case the client is already unmapped */
+ XSetErrorHandler(dummy_error_handler);
+
+ for(tc=&client; *tc; tc=&(*tc)->next)
+ if(*tc == c) {
+ *tc = c->next;
+ break;
+ }
+
+ dummy = nil;
+ update_client_views(c, &dummy);
+
+ unmap_client(c, WithdrawnState);
+ gravitate_client(c, True);
+ reparent_client(c, blz.root, c->rect.x, c->rect.y);
+
+ XFreeGC(blz.dpy, c->gc);
+ XDestroyWindow(blz.dpy, c->framewin);
+ XSync(blz.dpy, False);
+
+ XSetErrorHandler(wmii_error_handler);
+ XUngrabServer(blz.dpy);
+ flushevents(EnterWindowMask, False);
+
+ while(XCheckMaskEvent(blz.dpy, StructureNotifyMask, &ev))
+ if(ev.type != UnmapNotify || ev.xunmap.window != c->win)
+ dispatch_event(&ev);
+
+ write_event("DestroyClient 0x%x\n", c->win);
+ free(c);
+}
+
+void
+manage_client(Client *c) {
+ XTextProperty tags = { 0 };
+ Client *trans;
+
+ XGetTextProperty(blz.dpy, c->win, &tags, atom[TagsAtom]);
+
+ if((trans = client_of_win(c->trans)))
+ strncpy(c->tags, trans->tags, sizeof(c->tags));
+ else if(tags.nitems)
+ strncpy(c->tags, (char *)tags.value, sizeof(c->tags));
+ XFree(tags.value);
+
+ gravitate_client(c, False);
+ reparent_client(c, c->framewin, def.border, labelh(&def.font));
+
+ if(!strlen(c->tags))
+ apply_rules(c);
+ else
+ apply_tags(c, c->tags);
+
+ if(!starting)
+ update_views();
+ XSync(blz.dpy, False);
+
+ if(c->sel->view == screen->sel)
+ focus(c, True);
+ flushevents(EnterWindowMask, False);
+}
+
+Client *
+sel_client() {
+ if(screen->sel && screen->sel->sel->sel)
+ return screen->sel->sel->sel->client;
+ return nil;
+}
+
+Client *
+client_of_win(Window w) {
+ Client *c;
+ for(c=client; c; c=c->next)
+ if(c->win == w) break;
+ return c;
+}
+
+Frame *
+frame_of_win(Window w) {
+ Client *c;
+ for(c=client; c; c=c->next)
+ if(c->framewin == w) break;
+ if(c)
+ return c->sel;
+ return nil;
+}
+
+static void
+update_client_name(Client *c) {
+ XTextProperty name;
+ XClassHint ch;
+ int n;
+ char **list = nil;
+
+ name.nitems = 0;
+ c->name[0] = 0;
+ XGetTextProperty(blz.dpy, c->win, &name, atom[NetWMName]);
+ if(!name.nitems)
+ XGetWMName(blz.dpy, c->win, &name);
+ if(!name.nitems)
+ return;
+ if(name.encoding == XA_STRING)
+ strncpy(c->name, (char *)name.value, sizeof(c->name));
+ else {
+ if(XmbTextPropertyToTextList(blz.dpy, &name, &list, &n) >= Success
+ && n > 0 && *list)
+ {
+ strncpy(c->name, *list, sizeof(c->name));
+ XFreeStringList(list);
+ }
+ }
+ XFree(name.value);
+ if(XGetClassHint(blz.dpy, c->win, &ch)) {
+ snprintf(c->props, sizeof(c->props),
+ "%s:%s:%s",
+ str_nil(ch.res_class),
+ str_nil(ch.res_name),
+ c->name);
+ if(ch.res_class)
+ XFree(ch.res_class);
+ if(ch.res_name)
+ XFree(ch.res_name);
+ }
+}
+
+void
+update_client_grab(Client *c) {
+ Frame *f;
+ f = c->sel;
+ if((f->client != sel_client())
+ || (f->area->floating && f != f->area->stack)) {
+ if(verbose)
+ fprintf(stderr, "update_client_grab(%p) AnyButton => %s\n", c, str_nil(c->name));
+ grab_button(c->framewin, AnyButton, AnyModifier);
+ }else {
+ if(verbose)
+ fprintf(stderr, "update_client_grab(%p) def.mod => %s\n", c, str_nil(c->name));
+ XUngrabButton(blz.dpy, AnyButton, AnyModifier, c->framewin);
+ grab_button(c->framewin, Button1, def.mod);
+ grab_button(c->framewin, Button3, def.mod);
+ }
+}
+
+void
+set_client_state(Client * c, int state) {
+ long data[] = { state, None };
+ XChangeProperty(
+ /* display */ blz.dpy,
+ /* parent */ c->win,
+ /* property */ atom[WMState],
+ /* type */ atom[WMState],
+ /* format */ 32,
+ /* mode */ PropModeReplace,
+ /* data */ (uchar *) data,
+ /* npositions */2
+ );
+}
+
+void
+map_client(Client *c) {
+ if(!c->mapped) {
+ XSelectInput(blz.dpy, c->win, ClientMask & ~StructureNotifyMask);
+ XMapWindow(blz.dpy, c->win);
+ XSelectInput(blz.dpy, c->win, ClientMask);
+ set_client_state(c, NormalState);
+ c->mapped = 1;
+ }
+}
+
+void
+unmap_client(Client *c, int state) {
+ if(c->mapped) {
+ c->unmapped++;
+ XSelectInput(blz.dpy, c->win, ClientMask & ~StructureNotifyMask);
+ XUnmapWindow(blz.dpy, c->win);
+ XSelectInput(blz.dpy, c->win, ClientMask);
+ set_client_state(c, state);
+ c->mapped = 0;
+ }
+}
+
+void
+map_frame(Client *c) {
+ if(!c->frame_mapped) {
+ XMapWindow(blz.dpy, c->framewin);
+ c->frame_mapped = True;
+ }
+}
+
+void
+unmap_frame(Client *c) {
+ if(c->frame_mapped) {
+ XUnmapWindow(blz.dpy, c->framewin);
+ c->frame_mapped = False;
+ }
+}
+
+void
+reparent_client(Client *c, Window w, int x, int y) {
+ XSelectInput(blz.dpy, c->win, ClientMask & ~StructureNotifyMask);
+ XReparentWindow(blz.dpy, c->win, w, x, y);
+ XSelectInput(blz.dpy, c->win, ClientMask);
+}
+
+void
+set_cursor(Client *c, Cursor cur) {
+ XSetWindowAttributes wa;
+
+ if(c->cursor != cur) {
+ c->cursor = cur;
+ wa.cursor = cur;
+ XChangeWindowAttributes(blz.dpy, c->framewin, CWCursor, &wa);
+ }
+}
+
+void
+configure_client(Client *c) {
+ XConfigureEvent e;
+ Frame *f;
+
+ f = c->sel;
+ if(!f)
+ return;
+
+ e.type = ConfigureNotify;
+ e.event = c->win;
+ e.window = c->win;
+ e.x = f->crect.x + f->rect.x - c->border;
+ e.y = f->crect.y + f->rect.y - c->border;
+ e.width = f->crect.width;
+ e.height = f->crect.height;
+ e.border_width = c->border;
+ e.above = None;
+ e.override_redirect = False;
+ XSendEvent(blz.dpy, c->win, False,
+ StructureNotifyMask, (XEvent *) & e);
+ XSync(blz.dpy, False);
+}
+
+static void
+send_client_message(Window w, Atom a, long value) {
+ XEvent e;
+
+ e.type = ClientMessage;
+ e.xclient.window = w;
+ e.xclient.message_type = a;
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = value;
+ e.xclient.data.l[1] = CurrentTime;
+ XSendEvent(blz.dpy, w, False, NoEventMask, &e);
+ XSync(blz.dpy, False);
+}
+
+void
+kill_client(Client * c) {
+ if(c->proto & WM_PROTOCOL_DELWIN)
+ send_client_message(c->win, atom[WMProtocols], atom[WMDelete]);
+ else
+ XKillClient(blz.dpy, c->win);
+}
+
+static void
+set_urgent(Client *c, Bool urgent, Bool write) {
+ XWMHints *wmh;
+ char *cwrite, *cnot;
+ Frame *f, *ff;
+ Area *a;
+
+ cwrite = "Client";
+ if(write)
+ cwrite = "Manager";
+ cnot = "Not";
+ if(urgent)
+ cnot = "";
+
+ if(urgent != c->urgent) {
+ write_event("%sUrgent 0x%x %s\n", cnot, c->win, cwrite);
+ c->urgent = urgent;
+ if(c->sel) {
+ if(c->sel->view == screen->sel)
+ draw_frame(c->sel);
+ if(!urgent || c->sel->view != screen->sel)
+ for(f=c->frame; f; f=f->cnext) {
+ for(a=f->view->area; a; a=a->next)
+ for(ff=a->frame; ff; ff=ff->anext)
+ if(ff->client->urgent) break;
+ if(!ff)
+ write_event("%sUrgentTag %s %s\n", cnot, cwrite, f->view->name);
+ }
+ }
+ }
+
+ if(write) {
+ wmh = XGetWMHints(blz.dpy, c->win);
+ if(wmh) {
+ if(urgent)
+ wmh->flags |= XUrgencyHint;
+ else
+ wmh->flags &= ~XUrgencyHint;
+ XSetWMHints(blz.dpy, c->win, wmh);
+ XFree(wmh);
+ }
+ }
+}
+
+void
+prop_client(Client *c, Atom a) {
+ XWMHints *wmh;
+ long msize;
+
+ if(a == atom[WMProtocols])
+ c->proto = win_proto(c->win);
+ else if(a== atom[NetWMName]) {
+wmname:
+ update_client_name(c);
+ if(c->frame)
+ draw_frame(c->sel);
+ }else switch (a) {
+ case XA_WM_TRANSIENT_FOR:
+ XGetTransientForHint(blz.dpy, c->win, &c->trans);
+ break;
+ case XA_WM_NORMAL_HINTS:
+ if(!XGetWMNormalHints(blz.dpy, c->win, &c->size, &msize) || !c->size.flags)
+ c->size.flags = PSize;
+ c->fixedsize = False;
+ if((c->size.flags & PMinSize) && (c->size.flags & PMaxSize)
+ &&(c->size.min_width == c->size.max_width)
+ &&(c->size.min_height == c->size.max_height))
+ c->fixedsize = True;
+ break;
+ case XA_WM_HINTS:
+ wmh = XGetWMHints(blz.dpy, c->win);
+ if(wmh) {
+ set_urgent(c, (wmh->flags & XUrgencyHint) != 0, False);
+ XFree(wmh);
+ }
+ break;
+ case XA_WM_NAME:
+ goto wmname;
+ }
+}
+
+void
+gravitate_client(Client *c, Bool invert) {
+ int dx, dy;
+ int gravity;
+
+ gravity = NorthWestGravity;
+ if(c->size.flags & PWinGravity) {
+ gravity = c->size.win_gravity;
+ }
+
+ dy = 0;
+ switch (gravity) {
+ case StaticGravity:
+ case NorthWestGravity:
+ case NorthGravity:
+ case NorthEastGravity:
+ dy = labelh(&def.font);
+ break;
+ case EastGravity:
+ case CenterGravity:
+ case WestGravity:
+ dy = -(c->rect.height / 2) + labelh(&def.font);
+ break;
+ case SouthEastGravity:
+ case SouthGravity:
+ case SouthWestGravity:
+ dy = -c->rect.height;
+ break;
+ default:
+ break;
+ }
+
+ dx = 0;
+ switch (gravity) {
+ case StaticGravity:
+ case NorthWestGravity:
+ case WestGravity:
+ case SouthWestGravity:
+ dx = def.border;
+ break;
+ case NorthGravity:
+ case CenterGravity:
+ case SouthGravity:
+ dx = -(c->rect.width / 2) + def.border;
+ break;
+ case NorthEastGravity:
+ case EastGravity:
+ case SouthEastGravity:
+ dx = -(c->rect.width + def.border);
+ break;
+ default:
+ break;
+ }
+
+ if(invert) {
+ dx = -dx;
+ dy = -dy;
+ }
+ c->rect.x += dx;
+ c->rect.y += dy;
+}
+
+void
+apply_sizehints(Client *c, XRectangle *r, Bool floating, Bool frame, BlitzAlign sticky) {
+ XSizeHints *s;
+ XRectangle orig;
+ uint bw, bh;
+
+ s = &c->size;
+ orig = *r;
+ if(frame)
+ frame2client(r);
+ bw = 0;
+ bh = 0;
+
+ if(s->flags & PMinSize) {
+ bw = s->min_width;
+ bh = s->min_height;
+ if(floating) {
+ if(r->width < s->min_width)
+ r->width = s->min_width;
+ if(r->height < s->min_height)
+ r->height = s->min_height;
+ }
+ }
+ if(s->flags & PMaxSize) {
+ if(r->width > s->max_width)
+ r->width = s->max_width;
+ if(r->height > s->max_height)
+ r->height = s->max_height;
+ }
+
+ if(s->flags & PBaseSize) {
+ bw = s->base_width;
+ bh = s->base_height;
+ }
+
+ if(s->flags & PResizeInc) {
+ if(s->width_inc > 0)
+ r->width -= (r->width - bw) % s->width_inc;
+ if(s->height_inc > 0)
+ r->height -= (r->height - bh) % s->height_inc;
+ }
+
+ if((s->flags & (PBaseSize|PMinSize)) == PMinSize) {
+ bw = 0;
+ bh = 0;
+ }
+
+ if(s->flags & PAspect) {
+ double min, max, initial;
+
+ min = (double)s->min_aspect.x / s->min_aspect.y;
+ max = (double)s->max_aspect.x / s->max_aspect.y;
+ initial = (double)(r->width - bw) / (r->height - bh);
+ if(initial < min)
+ r->height = bh + (r->width - bw) / min;
+ if(initial > max)
+ r->width = bw + (r->height - bh) * max;
+ }
+
+ if(frame)
+ client2frame(r);
+
+ if(!(s->flags & PMinSize) || !floating) {
+ if(r->width > orig.width)
+ r->width = orig.width;
+ if(r->height > orig.height)
+ r->height = orig.height;
+ }
+
+ if((sticky & (EAST|WEST)) == EAST)
+ r->x = r_east(&orig) - r->width;
+ if((sticky & (NORTH|SOUTH)) == SOUTH)
+ r->y = r_south(&orig) - r->height;
+}
+
+void
+focus(Client *c, Bool restack) {
+ View *v;
+ Frame *f;
+
+ f = c->sel;
+ if(!f)
+ return;
+
+ v = f->area->view;
+ if(v != screen->sel)
+ focus_view(screen, v);
+ focus_frame(c->sel, restack);
+}
+
+void
+focus_client(Client *c) {
+ flushevents(FocusChangeMask, True);
+
+ if(verbose)
+ fprintf(stderr, "focus_client(%p) => %s\n", c, (c ? c->name : nil));
+ if(screen->focus != c) {
+ if(c && verbose)
+ fprintf(stderr, "\t%s => %s\n", (screen->focus ? screen->focus->name : "<nil>"),
+ (c ? c->name : "<nil>"));
+ if(c) {
+ XSetInputFocus(blz.dpy, c->win, RevertToParent, CurrentTime);
+ update_client_grab(c);
+ }else
+ XSetInputFocus(blz.dpy, screen->barwin, RevertToParent, CurrentTime);
+ }
+
+ flushevents(FocusChangeMask, True);
+}
+
+void
+resize_client(Client *c, XRectangle *r) {
+ Frame *f;
+
+ f = c->sel;
+ resize_frame(f, r);
+
+ if(f->area->view != screen->sel) {
+ unmap_client(c, IconicState);
+ unmap_frame(c);
+ return;
+ }
+
+ c->rect = f->crect;
+ c->rect.x += f->rect.x;
+ c->rect.y += f->rect.y;
+ if((f->area->mode == Colmax)
+ && (f->area->sel != f)) {
+ unmap_frame(c);
+ unmap_client(c, IconicState);
+ }else if(f->collapsed) {
+ XMoveResizeWindow(blz.dpy, c->framewin,
+ f->rect.x, f->rect.y,
+ f->rect.width, f->rect.height);
+ map_frame(c);
+ unmap_client(c, IconicState);
+ }else {
+ XMoveResizeWindow(blz.dpy, c->win,
+ f->crect.x, f->crect.y,
+ f->crect.width, f->crect.height);
+ map_client(c);
+ XMoveResizeWindow(blz.dpy, c->framewin,
+ f->rect.x, f->rect.y,
+ f->rect.width, f->rect.height);
+ map_frame(c);
+ configure_client(c);
+ }
+
+ flushevents(FocusChangeMask|ExposureMask, True);
+}
+
+void
+newcol_client(Client *c, char *arg) {
+ Frame *f = c->sel;
+ Area *to, *a = f->area;
+ View *v = a->view;
+
+ if(a->floating)
+ return;
+ if(!f->anext && f == a->frame)
+ return;
+ if(!strncmp(arg, "prev", 5)) {
+ for(to=v->area; to; to=to->next)
+ if(to->next == a) break;
+ to = new_column(v, to, 0);
+ send_to_area(to, f);
+ }
+ else if(!strncmp(arg, "next", 5)) {
+ to = new_column(v, a, 0);
+ send_to_area(to, f);
+ }
+ else
+ return;
+ flushevents(EnterWindowMask, False);
+}
+
+void
+move_client(Client *c, char *arg) {
+ Frame *f = c->sel;
+ XRectangle new = f->rect;
+ int x, y;
+
+ if(sscanf(arg, "%d %d", &x, &y) != 2)
+ return;
+ new.x += x;
+ new.y += y;
+ if(!f->area->floating)
+ resize_column(f->client, &new);
+ else
+ resize_client(f->client, &new);
+}
+
+void
+size_client(Client *c, char *arg) {
+ Frame *f = c->sel;
+ XRectangle new = f->rect;
+ int w, h;
+
+ if(sscanf(arg, "%d %d", &w, &h) != 2)
+ return;
+ new.width += w;
+ new.height += h;
+ if(!f->area->floating)
+ resize_column(f->client, &new);
+ else
+ resize_client(f->client, &new);
+}
+
+char *
+send_client(Frame *f, char *arg, Bool swap) {
+ Area *to, *a;
+ Client *c;
+ Frame *tf;
+ View *v;
+ Bool before;
+ int j;
+
+ a = f->area;
+ v = a->view;
+ c = f->client;
+ if(!strncmp(arg, "toggle", 7)) {
+ if(!a->floating)
+ to = v->area;
+ else if(c->revert && !c->revert->floating)
+ to = c->revert;
+ else
+ to = v->area->next;
+ goto send_area;
+ }else if(!a->floating) {
+ if(!strncmp(arg, "left", 5)) {
+ if(a->floating)
+ return Ebadvalue;
+ for(to=v->area->next; to; to=to->next)
+ if(a == to->next) break;
+ if(!to && !swap && (f->anext || f != a->frame))
+ to=new_column(v, v->area, 0);
+ goto send_area;
+ }
+ else if(!strncmp(arg, "right", 5)) {
+ if(a->floating)
+ return Ebadvalue;
+ to = a->next;
+ if(!to && !swap && (f->anext || f != a->frame))
+ to = new_column(v, a, 0);
+ goto send_area;
+ }
+ else if(!strncmp(arg, "up", 3)) {
+ for(tf=a->frame; tf; tf=tf->anext)
+ if(tf->anext == f) break;
+ before = True;
+ goto send_frame;
+ }
+ else if(!strncmp(arg, "down", 5)) {
+ tf = f->anext;
+ before = False;
+ goto send_frame;
+ }
+ else {
+ if(sscanf(arg, "%d", &j) != 1)
+ return Ebadvalue;
+ for(to=v->area; to; to=to->next)
+ if(!--j) break;
+ goto send_area;
+ }
+ }
+ return Ebadvalue;
+
+send_frame:
+ if(!tf)
+ return Ebadvalue;
+ if(!swap) {
+ remove_frame(f);
+ insert_frame(tf, f, before);
+ }else
+ swap_frames(f, tf);
+ arrange_column(a, False);
+
+ flushevents(EnterWindowMask, False);
+ focus_frame(f, True);
+ update_views();
+ return nil;
+
+send_area:
+ if(!to)
+ return Ebadvalue;
+ if(!swap)
+ send_to_area(to, f);
+ else if(to->sel)
+ swap_frames(f, to->sel);
+
+ flushevents(EnterWindowMask, False);
+ focus_frame(f, True);
+ update_views();
+ return nil;
+}
+
+void
+update_client_views(Client *c, char **tags) {
+ Frame **fp, *f;
+ int cmp;
+
+ fp = &c->frame;
+ while(*fp || *tags) {
+ while(*fp) {
+ if(*tags) {
+ cmp = strcmp((*fp)->view->name, *tags);
+ if(cmp >= 0)
+ break;
+ }
+
+ f = *fp;
+ detach_from_area(f);
+ *fp = f->cnext;
+ if(c->sel == f)
+ c->sel = *fp;
+ free(f);
+ }
+ if(*tags) {
+ if(!*fp || cmp > 0) {
+ f = create_frame(c, get_view(*tags));
+ if(f->view == screen->sel || !c->sel)
+ c->sel = f;
+ attach_to_view(f->view, f);
+ f->cnext = *fp;
+ *fp = f;
+ }
+ if(*fp) fp=&(*fp)->cnext;
+ tags++;
+ }
+ }
+ update_views();
+}
+
+static int
+compare_tags(const void *a, const void *b) {
+ return strcmp(*(char **)a, *(char **)b);
+}
+
+void
+apply_tags(Client *c, const char *tags) {
+ uint i, j, k, n;
+ Bool add;
+ char buf[512], last;
+ char *toks[32], *cur;
+
+ buf[0] = 0;
+ for(n = 0; tags[n]; n++)
+ if(tags[n] != ' ' && tags[n] != '\t') break;
+ if(tags[n] == '+' || tags[n] == '-')
+ strncpy(buf, c->tags, sizeof(c->tags));
+ strlcat(buf, &tags[n], sizeof(buf));
+ trim(buf, " \t/");
+
+ n = 0;
+ j = 0;
+ add = True;
+ if(buf[0] == '+')
+ n++;
+ else if(buf[0] == '-') {
+ n++;
+ add = False;
+ }
+ while(buf[n] && n < sizeof(buf) && j < 32) {
+ for(i = n; i < sizeof(buf) - 1; i++)
+ if(buf[i] == '+'
+ || buf[i] == '-'
+ || buf[i] == '\0')
+ break;
+ last = buf[i];
+ buf[i] = '\0';
+
+ cur = nil;
+ if(!strncmp(&buf[n], "~", 2))
+ c->floating = add;
+ else if(!strncmp(&buf[n], "!", 2))
+ cur = view ? screen->sel->name : "nil";
+ else if(strncmp(&buf[n], "sel", 4)
+ && strncmp(&buf[n], ".", 2)
+ && strncmp(&buf[n], "..", 3))
+ cur = &buf[n];
+
+ n = i + 1;
+ if(cur) {
+ if(add)
+ toks[j++] = cur;
+ else {
+ for(i = 0, k = 0; i < j; i++)
+ if(strcmp(toks[i], cur))
+ toks[k++] = toks[i];
+ j = k;
+ }
+ }
+
+ switch(last) {
+ case '+':
+ add = True;
+ break;
+ case '-':
+ add = False;
+ break;
+ case '\0':
+ buf[n] = '\0';
+ break;
+ }
+ }
+
+ c->tags[0] = '\0';
+ if(!j)
+ return;
+ qsort(toks, j, sizeof(char *), compare_tags);
+
+ for(i=0, n=0; i < j; i++)
+ if(!n || strcmp(toks[i], toks[n-1])) {
+ if(i)
+ strlcat(c->tags, "+", sizeof(c->tags));
+ strlcat(c->tags, toks[i], sizeof(c->tags));
+ toks[n++] = toks[i];
+ }
+ toks[n] = nil;
+
+ update_client_views(c, toks);
+ XChangeProperty(blz.dpy, c->win, atom[TagsAtom], XA_STRING, 8,
+ PropModeReplace, (uchar *)c->tags, strlen(c->tags));
+}
+
+void
+apply_rules(Client *c) {
+ Rule *r;
+ regmatch_t rm;
+
+ if(strlen(c->tags))
+ return;
+ if(def.tagrules.string)
+ for(r=def.tagrules.rule; r; r=r->next)
+ if(!regexec(&r->regex, c->props, 1, &rm, 0)) {
+ apply_tags(c, r->value);
+ if(strlen(c->tags) && strcmp(c->tags, "nil"))
+ break;
+ }
+ if(!strlen(c->tags))
+ apply_tags(c, "nil");
+}
+
+char *
+message_client(Client *c, char *message) {
+ if(!strncmp(message, "kill", 5))
+ kill_client(c);
+ else if(!strncmp(message, "Urgent", 7))
+ set_urgent(c, True, True);
+ else if(!strncmp(message, "NotUrgent", 10))
+ set_urgent(c, False, True);
+ else
+ return Ebadcmd;
+ return nil;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/column.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/column.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,317 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <math.h>
+#include <string.h>
+#include "wmii.h"
+
+char *
+str_of_column_mode(int mode) {
+ switch(mode) {
+ case Coldefault: return "default"; break;
+ case Colstack: return "stack"; break;
+ case Colmax: return "max"; break;
+ default: break;
+ }
+ return nil;
+}
+
+int
+column_mode_of_str(char *arg) {
+ if(!strncmp("default", arg, 8))
+ return Coldefault;
+ if(!strncmp("stack", arg, 6))
+ return Colstack;
+ if(!strncmp("max", arg, 4))
+ return Colmax;
+ return -1;
+}
+
+static void
+scale_column(Area *a) {
+ Frame *f, **fp;
+ uint min_height, yoff, dy;
+ uint num_col, num_uncol;
+ uint col_h, uncol_h;
+ int surplus, i, j;
+
+ if(!a->frame)
+ return;
+
+ /* This works by comparing heights based on a surplus of their
+ * minimum size. We start by subtracting the minimum size, then
+ * scale the surplus, and add back the minimum size later. This
+ * is based on the size of the client, rather than the frame, so
+ * increment gaps can be equalized later */
+ /* Frames that can't be accomodated are pushed to the floating layer */
+
+ min_height = labelh(&def.font);
+ col_h = labelh(&def.font);
+ uncol_h = min_height + frame_delta_h();
+
+ num_col = 0;
+ num_uncol = 0;
+ dy = 0;
+ for(f=a->frame; f; f=f->anext)
+ if(f->collapsed)
+ num_col++;
+ else
+ num_uncol++;
+
+ surplus = a->rect.height;
+ surplus -= num_col * col_h;
+ surplus -= num_uncol * uncol_h;
+ if(surplus < 0) {
+ i = ceil((float)(-surplus)/(uncol_h - col_h));
+ if(i >= num_uncol)
+ i = num_uncol - 1;
+ num_uncol -= i;
+ num_col += i;
+ surplus += i * (uncol_h - col_h);
+ }
+ if(surplus < 0) {
+ i = ceil((float)(-surplus)/col_h);
+ if(i > num_col)
+ i = num_col;
+ num_col -= i;
+ surplus += i * col_h;
+ }
+
+ i = num_col - 1;
+ j = num_uncol - 1;
+ for(f=a->frame; f; f=f->anext) {
+ if(f == a->sel)
+ j++;
+ if(!f->collapsed) {
+ if(j < 0 && f != a->sel)
+ f->collapsed = True;
+ else {
+ if(f->crect.height <= min_height)
+ f->crect.height = 1;
+ else
+ f->crect.height -= min_height;
+ dy += f->crect.height;
+ }
+ j--;
+ }
+ }
+ for(fp=&a->frame; *fp;) {
+ f = *fp;
+ if(f == a->sel)
+ i++;
+ if(f->collapsed) {
+ if(i < 0 && f != a->sel) {
+ f->collapsed = False;
+ send_to_area(f->view->area, f);
+ continue;
+ }
+ i--;
+ }
+ fp=&f->anext;
+ }
+
+ i = num_uncol;
+ for(f=a->frame; f; f=f->anext) {
+ f->rect.x = a->rect.x;
+ f->rect.width = a->rect.width;
+ if(!f->collapsed) {
+ i--;
+ f->rect.height = (float)f->crect.height / dy * surplus;
+ if(!i)
+ f->rect.height = surplus;
+ f->rect.height += min_height + frame_delta_h();
+ apply_sizehints(f->client, &f->rect, False, True, NWEST);
+
+ dy -= f->crect.height;
+ surplus -= f->rect.height - frame_delta_h() - min_height;
+ }else
+ f->rect.height = labelh(&def.font);
+ }
+
+ yoff = a->rect.y;
+ i = num_uncol;
+ for(f=a->frame; f; f=f->anext) {
+ f->rect.y = yoff;
+ f->rect.x = a->rect.x;
+ f->rect.width = a->rect.width;
+ if(f->collapsed)
+ yoff += f->rect.height;
+ else{
+ i--;
+ f->rect.height += surplus / num_uncol;
+ if(!i)
+ f->rect.height += surplus % num_uncol;
+ yoff += f->rect.height;
+ }
+ }
+}
+
+void
+arrange_column(Area *a, Bool dirty) {
+ Frame *f;
+
+ if(a->floating || !a->frame)
+ return;
+
+ switch(a->mode) {
+ case Coldefault:
+ for(f=a->frame; f; f=f->anext) {
+ f->collapsed = False;
+ if(dirty)
+ f->crect.height = 100;
+ }
+ break;
+ case Colstack:
+ for(f=a->frame; f; f=f->anext)
+ f->collapsed = (f != a->sel);
+ break;
+ case Colmax:
+ for(f=a->frame; f; f=f->anext) {
+ f->collapsed = False;
+ f->rect = a->rect;
+ }
+ goto resize;
+ default:
+ break;
+ }
+ scale_column(a);
+resize:
+ if(a->view == screen->sel) {
+ restack_view(a->view);
+ resize_client(a->sel->client, &a->sel->rect);
+ for(f=a->frame; f; f=f->anext)
+ if(!f->collapsed && f != a->sel)
+ resize_client(f->client, &f->rect);
+ for(f=a->frame; f; f=f->anext)
+ if(f->collapsed && f != a->sel)
+ resize_client(f->client, &f->rect);
+ }
+}
+
+static void
+match_horiz(Area *a, XRectangle *r) {
+ Frame *f;
+
+ for(f=a->frame; f; f=f->anext) {
+ f->rect.x = r->x;
+ f->rect.width = r->width;
+ resize_frame(f, &f->rect);
+ }
+}
+
+void
+resize_column(Client *c, XRectangle *new) {
+ Area *west, *east, *a;
+ Frame *north, *south, *f;
+ View *v;
+ BlitzAlign sticky;
+ uint min_height;
+ uint min_width;
+
+ f = c->sel;
+ a = f->area;
+ v = a->view;
+ min_height = 2 * labelh(&def.font);
+ min_width = screen->rect.width/NCOL;
+
+ for(west=v->area->next; west; west=west->next)
+ if(west->next == a) break;
+ east = a->next;
+ for(north=a->frame; north; north=north->anext)
+ if(north->anext == f) break;
+ south = f->anext;
+ /* validate (and trim if necessary) horizontal resize */
+ sticky = get_sticky(&f->rect, new);
+ if(new->width < min_width) {
+ if(sticky & EAST)
+ new->x = r_east(&a->rect) - min_width;
+ new->width = min_width;
+ }
+ if(west && !(sticky & WEST)) {
+ if(new->x < 0 || new->x < (west->rect.x + min_width)) {
+ new->width -= (west->rect.x + min_width) - new->x;
+ new->x = west->rect.x + min_width;
+ }
+ } else {
+ new->width += new->x - a->rect.x;
+ new->x = a->rect.x;
+ }
+ if(east && !(sticky & EAST)) {
+ if(r_east(new) > r_east(&east->rect) - min_width)
+ new->width = r_east(&east->rect) - min_width - new->x;
+ } else
+ new->width = r_east(&a->rect) - new->x;
+ if(new->width < min_width)
+ goto AfterHorizontal;
+ /* horizontal resize */
+ sticky = get_sticky(&a->rect, new);
+ if(west && !(sticky & WEST)) {
+ west->rect.width = new->x - west->rect.x;
+ a->rect.width += a->rect.x - new->x;
+ a->rect.x = new->x;
+ match_horiz(a, &a->rect);
+ match_horiz(west, &west->rect);
+ //relax_column(west);
+ }
+ if(east && !(sticky & EAST)) {
+ east->rect.width -= r_east(new) - east->rect.x;
+ east->rect.x = r_east(new);
+ a->rect.width = r_east(new) - a->rect.x;
+ match_horiz(a, &a->rect);
+ match_horiz(east, &east->rect);
+ //relax_column(east);
+ }
+AfterHorizontal:
+ /* skip vertical resize unless the column is in equal mode */
+ if(a->mode != Coldefault)
+ goto AfterVertical;
+ /* validate (and trim if necessary) vertical resize */
+ sticky = get_sticky(&f->rect, new);
+ if(new->height < min_height) {
+ if((f->rect.height < min_height) && sticky & (NORTH|SOUTH))
+ goto AfterVertical;
+ if(sticky & SOUTH)
+ new->y = r_south(&f->rect) - min_height;
+ new->height = min_height;
+ }
+ if(north && !(sticky & NORTH))
+ if(new->y < 0 || new->y < (north->rect.y + min_height)) {
+ new->height -= (north->rect.y + min_height) - new->y;
+ new->y = north->rect.y + min_height;
+ }
+ if(south && !(sticky & SOUTH)) {
+ if(r_south(new) > r_south(&south->rect) - min_height)
+ new->height = r_south(&south->rect) - min_height - new->y;
+ }
+ if(new->height < min_height)
+ goto AfterVertical;
+ /* vertical resize */
+ if(north && !(sticky & NORTH)) {
+ north->rect.height = new->y - north->rect.y;
+ f->rect.height += f->rect.y - new->y;
+ f->rect.y = new->y;
+ resize_frame(north, &north->rect);
+ resize_frame(f, &f->rect);
+ }
+ if(south && !(sticky & SOUTH)) {
+ south->rect.height -= r_south(new) - south->rect.y;
+ south->rect.y = r_south(new);
+ f->rect.y = new->y;
+ f->rect.height = new->height;
+ resize_frame(f, &f->rect);
+ resize_frame(south, &south->rect);
+ }
+AfterVertical:
+ arrange_column(a, False);
+ focus_view(screen, v);
+}
+
+Area *
+new_column(View *v, Area *pos, uint w) {
+ Area *a = create_area(v, pos, w);
+ if(!a)
+ return nil;
+ arrange_view(v);
+ return a;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/draw.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/draw.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,227 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "wmii.h"
+
+uint
+textwidth_l(BlitzFont *font, char *text, uint len) {
+ if(font->set) {
+ XRectangle r;
+ XmbTextExtents(font->set, text, len, &r, nil);
+ return r.width;
+ }
+ return XTextWidth(font->xfont, text, len);
+}
+
+uint
+textwidth(BlitzFont *font, char *text) {
+ return textwidth_l(font, text, strlen(text));
+}
+
+void
+loadfont(Blitz *blitz, BlitzFont *font) {
+ char *fontname = font->fontstr;
+ char **missing = nil, *def = "?";
+ int n;
+
+ if(font->set)
+ XFreeFontSet(blitz->dpy, font->set);
+ font->set = XCreateFontSet(blitz->dpy, fontname, &missing, &n, &def);
+ if(missing) {
+ while(n--)
+ fprintf(stderr, "wmii: missing fontset for '%s': %s\n",
+ fontname, missing[n]);
+ XFreeStringList(missing);
+ }
+ if(font->set) {
+ XFontSetExtents *font_extents;
+ XFontStruct **xfonts;
+ char **font_names;
+
+ font->ascent = font->descent = 0;
+ font_extents = XExtentsOfFontSet(font->set);
+ XFontsOfFontSet(font->set, &xfonts, &font_names);
+ font->ascent = xfonts[0]->ascent;
+ font->descent = xfonts[0]->descent;
+ }
+ else {
+ if(font->xfont)
+ XFreeFont(blitz->dpy, font->xfont);
+ font->xfont = nil;
+ font->xfont = XLoadQueryFont(blitz->dpy, fontname);
+ if (!font->xfont) {
+ if(!strncmp(fontname, BLITZ_FONT, sizeof(BLITZ_FONT)))
+ fatal("cannot load font: %s",
+ BLITZ_FONT);
+ free(font->fontstr);
+ font->fontstr = estrdup(BLITZ_FONT);
+ loadfont(blitz, font);
+ return;
+ }
+ font->ascent = font->xfont->ascent;
+ font->descent = font->xfont->descent;
+ }
+ font->height = font->ascent + font->descent;
+}
+
+uint
+labelh(BlitzFont *font) {
+ return font->height + 2;
+}
+
+void
+draw_tile(BlitzBrush *b) {
+ drawbg(b->blitz->dpy, b->drawable, b->gc, &b->rect,
+ b->color, True, b->border);
+}
+
+void
+draw_border(BlitzBrush *b) {
+ drawbg(b->blitz->dpy, b->drawable, b->gc, &b->rect,
+ b->color, False, b->border);
+}
+
+void
+draw_label(BlitzBrush *b, char *text) {
+ uint x, y, w, h, len;
+ Bool shortened = False;
+ static char buf[2048];
+ XRectangle r = {0};
+ XGCValues gcv;
+
+ draw_tile(b);
+ if(!text)
+ return;
+ shortened = 0;
+ strncpy(buf, text, sizeof(buf));
+ len = strlen(buf);
+ gcv.foreground = b->color.fg;
+ gcv.background = b->color.bg;
+ h = b->font->ascent + b->font->descent;
+ y = b->rect.y + b->rect.height / 2 - h / 2 + b->font->ascent;
+ /* shorten text if necessary */
+ while(len
+ && (w = textwidth(b->font, buf)) > b->rect.width - (b->font->height & ~1)) {
+ buf[--len] = 0;
+ shortened = True;
+ }
+ if(!len)
+ return;
+ if(w > b->rect.width)
+ return;
+ /* mark shortened info in the string */
+ if(shortened) {
+ if (len > 3)
+ buf[len - 3] = '.';
+ if (len > 2)
+ buf[len - 2] = '.';
+ if (len > 1)
+ buf[len - 1] = '.';
+ }
+
+ if(b->font->set) {
+ XmbTextExtents(b->font->set, text, len, &r, nil);
+ }
+
+ switch (b->align) {
+ case EAST:
+ x = b->rect.x + b->rect.width - (w + (b->font->height / 2));
+ break;
+ default:
+ x = b->rect.x + (b->font->height / 2) - r.x;
+ break;
+ }
+ if(b->font->set) {
+ XChangeGC(b->blitz->dpy, b->gc, GCForeground | GCBackground, &gcv);
+ XmbDrawImageString(b->blitz->dpy, b->drawable, b->font->set, b->gc,
+ x, y, buf, len);
+ }
+ else {
+ gcv.font = b->font->xfont->fid;
+ XChangeGC(b->blitz->dpy, b->gc, GCForeground | GCBackground | GCFont, &gcv);
+ XDrawImageString(b->blitz->dpy, b->drawable, b->gc, x, y, buf, len);
+ }
+}
+
+void
+drawbg(Display *dpy, Drawable drawable, GC gc, XRectangle *rect,
+ BlitzColor c, Bool fill, int border)
+{
+ if(fill) {
+ XSetForeground(dpy, gc, c.bg);
+ XFillRectangles(dpy, drawable, gc, rect, 1);
+ }
+ if(border) {
+ XSetLineAttributes(dpy, gc, border, LineSolid, CapButt, JoinMiter);
+ XSetForeground(dpy, gc, c.border);
+ XDrawRectangle(dpy, drawable, gc, rect->x + border / 2, rect->y + border / 2,
+ rect->width - border, rect->height - border);
+ }
+}
+
+void
+drawcursor(Display *dpy, Drawable drawable, GC gc,
+ int x, int y, uint h, BlitzColor c)
+{
+ XSegment s[5];
+
+ XSetForeground(dpy, gc, c.fg);
+ XSetLineAttributes(dpy, gc, 1, LineSolid, CapButt, JoinMiter);
+ s[0].x1 = x - 1;
+ s[0].y1 = s[0].y2 = y;
+ s[0].x2 = x + 2;
+ s[1].x1 = x - 1;
+ s[1].y1 = s[1].y2 = y + 1;
+ s[1].x2 = x + 2;
+ s[2].x1 = s[2].x2 = x;
+ s[2].y1 = y;
+ s[2].y2 = y + h;
+ s[3].x1 = x - 1;
+ s[3].y1 = s[3].y2 = y + h;
+ s[3].x2 = x + 2;
+ s[4].x1 = x - 1;
+ s[4].y1 = s[4].y2 = y + h - 1;
+ s[4].x2 = x + 2;
+ XDrawSegments(dpy, drawable, gc, s, 5);
+}
+
+static ulong
+xloadcolor(Blitz *blitz, char *colstr) {
+ XColor color;
+ char col[8];
+
+ strncpy(col, colstr, sizeof(col));
+ col[7] = 0;
+ XAllocNamedColor(blitz->dpy,
+ DefaultColormap(blitz->dpy, blitz->screen), col, &color, &color);
+ return color.pixel;
+}
+
+int
+loadcolor(Blitz *blitz, BlitzColor *c) {
+ if(!c->colstr || strlen(c->colstr) != 23)
+ return -1;
+ c->fg = xloadcolor(blitz, &c->colstr[0]);
+ c->bg = xloadcolor(blitz, &c->colstr[8]);
+ c->border = xloadcolor(blitz, &c->colstr[16]);
+ return 0;
+}
+
+char *
+parse_colors(char **buf, int *buflen, BlitzColor *col) {
+ uint i;
+ if(*buflen < 23 || 3 != sscanf(*buf, "#%06x #%06x #%06x", &i,&i,&i))
+ return "bad value";
+ (*buflen) -= 23;
+ bcopy(*buf, col->colstr, 23);
+ loadcolor(&blz, col);
+
+ (*buf) += 23;
+ if(**buf == '\n' || **buf == ' ') {
+ (*buf)++;
+ (*buflen)--;
+ }
+ return nil;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/event.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/event.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,448 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <X11/keysym.h>
+#include "wmii.h"
+#include "printevent.h"
+
+void
+dispatch_event(XEvent *e) {
+ if(handler[e->type])
+ handler[e->type](e);
+}
+
+uint
+flushevents(long event_mask, Bool dispatch) {
+ XEvent ev;
+ uint n = 0;
+
+ while(XCheckMaskEvent(blz.dpy, event_mask, &ev)) {
+ if(dispatch)
+ dispatch_event(&ev);
+ n++;
+ }
+ return n;
+}
+
+static void
+buttonrelease(XEvent *e) {
+ XButtonPressedEvent *ev;
+ Frame *f;
+ Bar *b;
+
+ ev = &e->xbutton;
+ if(ev->window == screen->barwin) {
+ for(b=screen->bar[BarLeft]; b; b=b->next)
+ if(ptinrect(ev->x, ev->y, &b->brush.rect)) {
+ write_event("LeftBarClick %d %s\n", ev->button, b->name);
+ return;
+ }
+ for(b=screen->bar[BarRight]; b; b=b->next)
+ if(ptinrect(ev->x, ev->y, &b->brush.rect)) {
+ write_event("RightBarClick %d %s\n", ev->button, b->name);
+ return;
+ }
+ }
+ else if((f = frame_of_win(ev->window)))
+ write_event("ClientClick 0x%x %d\n", f->client->win, ev->button);
+}
+
+static void
+buttonpress(XEvent *e) {
+ XButtonPressedEvent *ev;
+ Frame *f;
+
+ ev = &e->xbutton;
+ if((f = frame_of_win(ev->window))) {
+ if((ev->state & def.mod) == def.mod) {
+ switch(ev->button) {
+ case Button1:
+ do_mouse_resize(f->client, False, CENTER);
+ focus(f->client, True);
+ frame_to_top(f);
+ focus(f->client, True);
+ break;
+ case Button3:
+ do_mouse_resize(f->client, False,
+ quadrant(&f->rect, ev->x_root, ev->y_root));
+ frame_to_top(f);
+ focus(f->client, True);
+ break;
+ default: break;
+ XAllowEvents(blz.dpy, ReplayPointer, ev->time);
+ }
+ }else{
+ if(ev->button == Button1) {
+ if(frame_to_top(f))
+ restack_view(f->view);
+
+ if(ptinrect(ev->x, ev->y, &f->grabbox))
+ do_mouse_resize(f->client, True, CENTER);
+ else if(!ev->subwindow && !ptinrect(ev->x, ev->y, &f->titlebar))
+ do_mouse_resize(f->client, False, quadrant(&f->rect, ev->x_root, ev->y_root));
+
+ if(f->client != sel_client())
+ focus(f->client, True);
+ }
+ if(ev->subwindow)
+ XAllowEvents(blz.dpy, ReplayPointer, ev->time);
+ else {
+ /* Ungrab so a menu can receive events before the button is released */
+ XUngrabPointer(blz.dpy, ev->time);
+ XSync(blz.dpy, False);
+
+ write_event("ClientMouseDown 0x%x %d\n", f->client->win, ev->button);
+ }
+ }
+ }else
+ XAllowEvents(blz.dpy, ReplayPointer, ev->time);
+}
+
+static void
+configurerequest(XEvent *e) {
+ XConfigureRequestEvent *ev;
+ XWindowChanges wc;
+ XRectangle *frect;
+ Client *c;
+ Frame *f;
+
+ ev = &e->xconfigurerequest;
+ c = client_of_win(ev->window);
+ if(c) {
+ f = c->sel;
+ gravitate_client(c, True);
+ if(ev->value_mask & CWX)
+ c->rect.x = ev->x;
+ if(ev->value_mask & CWY)
+ c->rect.y = ev->y;
+ if(ev->value_mask & CWWidth)
+ c->rect.width = ev->width;
+ if(ev->value_mask & CWHeight)
+ c->rect.height = ev->height;
+ if(ev->value_mask & CWBorderWidth)
+ c->border = ev->border_width;
+ gravitate_client(c, False);
+
+ if((c->rect.height == screen->rect.height)
+ && (c->rect.width == screen->rect.width)) {
+ c->fullscreen = True;
+ if(c->sel) {
+ if(!c->sel->area->floating)
+ send_to_area(c->sel->view->area, c->sel);
+ focus_client(c);
+ restack_view(c->sel->view);
+ }
+ }
+
+ if(c->sel->area->floating)
+ frect=&c->sel->rect;
+ else
+ frect=&c->sel->revert;
+
+ *frect = c->rect;
+ frect->y -= labelh(&def.font);
+ frect->x -= def.border;
+ frect->width += 2 * def.border;
+ frect->height += frame_delta_h();
+
+ if(c->sel->area->floating || c->fullscreen)
+ resize_client(c, frect);
+ else
+ configure_client(c);
+ }else{
+ wc.x = ev->x;
+ wc.y = ev->y;
+ wc.width = ev->width;
+ wc.height = ev->height;
+ wc.border_width = ev->border_width;
+ wc.sibling = ev->above;
+ wc.stack_mode = ev->detail;
+ ev->value_mask &= ~(CWStackMode|CWSibling);
+ XConfigureWindow(blz.dpy, ev->window, ev->value_mask, &wc);
+ XSync(blz.dpy, False);
+ }
+}
+
+static void
+destroynotify(XEvent *e) {
+ XDestroyWindowEvent *ev;
+ Client *c;
+
+ ev = &e->xdestroywindow;
+ if((c = client_of_win(ev->window)))
+ destroy_client(c);
+}
+
+static void
+enternotify(XEvent *e) {
+ XCrossingEvent *ev;
+ Client *c;
+ Frame *f;
+
+ ev = &e->xcrossing;
+ if(ev->mode != NotifyNormal)
+ return;
+
+ if((c = client_of_win(ev->window))) {
+ if(ev->detail != NotifyInferior) {
+ if(screen->focus != c) {
+ if(verbose) fprintf(stderr, "enter_notify(c) => %s\n", c->name);
+ focus(c, False);
+ }
+ set_cursor(c, cursor[CurNormal]);
+ }else if(verbose) fprintf(stderr, "enter_notify(c[NotifyInferior]) => %s\n", c->name);
+ }
+ else if((f = frame_of_win(ev->window))) {
+ if(screen->focus != c) {
+ if(verbose) fprintf(stderr, "enter_notify(f) => %s\n", f->client->name);
+ if(f->area->floating || !f->collapsed)
+ focus(f->client, False);
+ }
+ set_frame_cursor(f, ev->x, ev->y);
+ }
+ else if(ev->window == blz.root) {
+ sel_screen = True;
+ draw_frames();
+ }
+}
+
+static void
+leavenotify(XEvent *e) {
+ XCrossingEvent *ev;
+
+ ev = &e->xcrossing;
+ if((ev->window == blz.root) && !ev->same_screen) {
+ sel_screen = True;
+ draw_frames();
+ }
+}
+
+void
+print_focus(Client *c, char *to) {
+ if(verbose) {
+ fprintf(stderr, "screen->focus: %p => %p\n",
+ screen->focus, c);
+ fprintf(stderr, "\t%s => %s\n",
+ screen->focus ? screen->focus->name : "<nil>",
+ to);
+ }
+}
+
+static void
+focusin(XEvent *e) {
+ XFocusChangeEvent *ev;
+ Client *c, *old;
+ XEvent me;
+
+ ev = &e->xfocus;
+ /* Yes, we're focusing in on nothing, here. */
+ if(ev->detail == NotifyDetailNone) {
+ XSetInputFocus(blz.dpy, screen->barwin, RevertToParent, CurrentTime);
+ return;
+ }
+
+ if(!((ev->detail == NotifyNonlinear)
+ ||(ev->detail == NotifyNonlinearVirtual)
+ ||(ev->detail == NotifyVirtual)
+ ||(ev->detail == NotifyInferior)
+ ||(ev->detail == NotifyAncestor)))
+ return;
+ if((ev->mode == NotifyWhileGrabbed)
+ && (screen->hasgrab != &c_root))
+ return;
+
+ old = screen->focus;
+ c = client_of_win(ev->window);
+ if(c) {
+ print_focus(c, c->name);
+ if(ev->mode == NotifyGrab)
+ screen->hasgrab = c;
+ screen->focus = c;
+ if(c != old) {
+ update_client_grab(c);
+ if(c->sel)
+ draw_frame(c->sel);
+ if(old && old->sel)
+ draw_frame(old->sel);
+ }
+ }else if(ev->window == screen->barwin) {
+ print_focus(nil, "<nil>");
+ screen->focus = nil;
+ }else if(ev->mode == NotifyGrab) {
+ if(ev->window == blz.root)
+ if(XCheckMaskEvent(blz.dpy, KeyPressMask, &me)) {
+ /* wmii has grabbed focus */
+ screen->hasgrab = &c_root;
+ dispatch_event(&me);
+ return;
+ }
+ /* Some unmanaged window has grabbed focus */
+ if((c = screen->focus)) {
+ print_focus(&c_magic, "<magic>");
+ screen->focus = &c_magic;
+ if(c->sel)
+ draw_frame(c->sel);
+ }
+ }
+}
+
+static void
+focusout(XEvent *e) {
+ XFocusChangeEvent *ev;
+ Client *c;
+
+ ev = &e->xfocus;
+ if(!((ev->detail == NotifyNonlinear)
+ ||(ev->detail == NotifyNonlinearVirtual)))
+ return;
+ if(ev->mode == NotifyUngrab)
+ screen->hasgrab = nil;
+
+ c = client_of_win(ev->window);
+ if(c) {
+ if((ev->mode == NotifyWhileGrabbed)
+ && (screen->hasgrab != &c_root)) {
+ if((screen->focus)
+ && (screen->hasgrab != screen->focus))
+ screen->hasgrab = screen->focus;
+ if(screen->hasgrab == c)
+ return;
+ }else if(ev->mode != NotifyGrab) {
+ if(screen->focus == c) {
+ print_focus(&c_magic, "<magic>");
+ screen->focus = &c_magic;
+ }
+ update_client_grab(c);
+ if(c->sel)
+ draw_frame(c->sel);
+ }
+ }
+}
+
+static void
+expose(XEvent *e) {
+ XExposeEvent *ev;
+ static Frame *f;
+
+ ev = &e->xexpose;
+ if(ev->count == 0) {
+ if(ev->window == screen->barwin)
+ draw_bar(screen);
+ else if((f = frame_of_win(ev->window)))
+ draw_frame(f);
+ }
+}
+
+static void
+keypress(XEvent *e) {
+ XKeyEvent *ev;
+
+ ev = &e->xkey;
+ ev->state &= valid_mask;
+ if(ev->window == blz.root)
+ kpress(blz.root, ev->state, (KeyCode) ev->keycode);
+}
+
+static void
+mappingnotify(XEvent *e) {
+ XMappingEvent *ev;
+
+ ev = &e->xmapping;
+ XRefreshKeyboardMapping(ev);
+ if(ev->request == MappingKeyboard)
+ update_keys();
+}
+
+static void
+maprequest(XEvent *e) {
+ XMapRequestEvent *ev;
+ static XWindowAttributes wa;
+
+ ev = &e->xmaprequest;
+ if(!XGetWindowAttributes(blz.dpy, ev->window, &wa))
+ return;
+ if(wa.override_redirect) {
+ XSelectInput(blz.dpy, ev->window,
+ (StructureNotifyMask | PropertyChangeMask));
+ return;
+ }
+ if(!client_of_win(ev->window))
+ manage_client(create_client(ev->window, &wa));
+}
+
+static void
+motionnotify(XEvent *e) {
+ XMotionEvent *ev;
+ Frame *f;
+
+ ev = &e->xmotion;
+ if((f = frame_of_win(ev->window)))
+ set_frame_cursor(f, ev->x, ev->y);
+}
+
+static void
+propertynotify(XEvent *e) {
+ XPropertyEvent *ev;
+ Client *c;
+
+ ev = &e->xproperty;
+ if(ev->state == PropertyDelete)
+ return; /* ignore */
+ if((c = client_of_win(ev->window)))
+ prop_client(c, ev->atom);
+}
+
+static void
+mapnotify(XEvent *e) {
+ XMapEvent *ev;
+ Client *c;
+
+ ev = &e->xmap;
+ if((c = client_of_win(ev->window)))
+ if(c == sel_client())
+ focus_client(c);
+}
+
+static void
+unmapnotify(XEvent *e) {
+ XUnmapEvent *ev;
+ Client *c;
+
+ ev = &e->xunmap;
+ if((c = client_of_win(ev->window)))
+ if(ev->send_event || (c->unmapped-- == 0))
+ destroy_client(c);
+}
+
+void (*handler[LASTEvent]) (XEvent *) = {
+ [ButtonPress] = buttonpress,
+ [ButtonRelease] = buttonrelease,
+ [ConfigureRequest]=configurerequest,
+ [DestroyNotify] = destroynotify,
+ [EnterNotify] = enternotify,
+ [Expose] = expose,
+ [FocusIn] = focusin,
+ [FocusOut] = focusout,
+ [KeyPress] = keypress,
+ [LeaveNotify] = leavenotify,
+ [MapNotify] = mapnotify,
+ [MapRequest] = maprequest,
+ [MappingNotify] = mappingnotify,
+ [MotionNotify] = motionnotify,
+ [PropertyNotify]= propertynotify,
+ [UnmapNotify] = unmapnotify,
+
+};
+
+void
+check_x_event(IxpConn *c) {
+ XEvent ev;
+ while(XPending(blz.dpy)) {
+ XNextEvent(blz.dpy, &ev);
+ if(verbose)
+ printevent(&ev);
+ dispatch_event(&ev);
+ XPending(blz.dpy);
+ }
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/frame.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/frame.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,341 @@
+/* Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "wmii.h"
+
+Frame *
+create_frame(Client *c, View *v) {
+ static ushort id = 1;
+ Frame *f = emallocz(sizeof(Frame));
+
+ f->id = id++;
+ f->client = c;
+ f->view = v;
+ if(c->sel) {
+ f->revert = c->sel->revert;
+ f->rect = c->sel->rect;
+ }
+ else{
+ c->sel = f;
+ f->revert = f->rect = c->rect;
+ f->revert.width = f->rect.width += 2 * def.border;
+ f->revert.height = f->rect.height += frame_delta_h();
+ }
+ f->collapsed = False;
+
+ return f;
+}
+
+void
+remove_frame(Frame *f) {
+ Area *a;
+ Frame **ft;
+
+ a = f->area;
+ for(ft = &a->frame; *ft; ft=&(*ft)->anext)
+ if(*ft == f) break;
+ *ft = f->anext;
+
+ if(a->floating) {
+ for(ft = &a->stack; *ft; ft=&(*ft)->snext)
+ if(*ft == f) break;
+ *ft = f->snext;
+ }
+}
+
+void
+insert_frame(Frame *pos, Frame *f, Bool before) {
+ Frame *ft, **p;
+ Area *a = f->area;
+
+ if(before) {
+ for(ft=a->frame; ft; ft=ft->anext)
+ if(ft->anext == pos) break;
+ pos=ft;
+ }
+ p = &a->frame;
+ if(pos)
+ p = &pos->anext;
+ f->anext = *p;
+ *p = f;
+
+ if(a->floating) {
+ f->snext = a->stack;
+ a->stack = f;
+ }
+}
+
+void
+frame2client(XRectangle *r) {
+ r->width = max(r->width - def.border * 2, 1);
+ r->height = max(r->height - frame_delta_h(), 1);
+}
+
+void
+client2frame(XRectangle *r) {
+ r->width += def.border * 2;
+ r->height += frame_delta_h();
+}
+
+void
+resize_frame(Frame *f, XRectangle *r) {
+ BlitzAlign stickycorner;
+ Client *c;
+
+ c = f->client;
+ stickycorner = get_sticky(&f->rect, r);
+
+ f->rect = *r;
+ f->crect = *r;
+ apply_sizehints(c, &f->crect, f->area->floating, True, stickycorner);
+
+ if(f->area->floating)
+ f->rect = f->crect;
+
+ frame2client(&f->crect);
+
+ if(f->crect.height < labelh(&def.font))
+ f->collapsed = True;
+ else
+ f->collapsed = False;
+
+ if(f->crect.width < labelh(&def.font)) {
+ f->rect.width = frame_delta_h();
+ f->collapsed = True;
+ }
+
+ if(f->collapsed) {
+ f->rect.height = labelh(&def.font);
+ f->crect = f->rect;
+ }
+ f->crect.y = labelh(&def.font);
+ f->crect.x = (f->rect.width - f->crect.width) / 2;
+
+
+ if(f->area->floating) {
+ if(c->fullscreen) {
+ f->crect.width = screen->rect.width;
+ f->crect.height = screen->rect.height;
+ f->rect = f->crect;
+ client2frame(&f->rect);
+ f->rect.x = -def.border;
+ f->rect.y = -labelh(&def.font);
+ }else
+ check_frame_constraints(&f->rect);
+ }
+}
+
+void
+set_frame_cursor(Frame *f, int x, int y) {
+ XRectangle r;
+ Cursor cur;
+
+ if(!ptinrect(x, y, &f->titlebar)
+ &&!ptinrect(x, y, &f->crect)) {
+ r = f->rect;
+ r.x = 0;
+ r.y = 0;
+ cur = cursor_of_quad(quadrant(&r, x, y));
+ set_cursor(f->client, cur);
+ }else
+ set_cursor(f->client, cursor[CurNormal]);
+}
+
+Bool
+frame_to_top(Frame *f) {
+ Frame **tf;
+ Area *a;
+
+ a = f->area;
+ if(!a->floating || f == a->stack)
+ return False;
+ for(tf=&a->stack; *tf; tf=&(*tf)->snext)
+ if(*tf == f) break;
+ *tf = f->snext;
+ f->snext = a->stack;
+ a->stack = f;
+ update_client_grab(f->client);
+ return True;
+}
+
+void
+swap_frames(Frame *fa, Frame *fb) {
+ XRectangle trect;
+ Area *a;
+ Frame **fp_a, **fp_b, *ft;
+
+ if(fa == fb) return;
+
+ a = fa->area;
+ for(fp_a = &a->frame; *fp_a; fp_a = &(*fp_a)->anext)
+ if(*fp_a == fa) break;
+ a = fb->area;
+ for(fp_b = &a->frame; *fp_b; fp_b = &(*fp_b)->anext)
+ if(*fp_b == fb) break;
+
+ if(fa->anext == fb) {
+ *fp_a = fb;
+ fa->anext = fb->anext;
+ fb->anext = fa;
+ } else if(fb->anext == fa) {
+ *fp_b = fa;
+ fb->anext = fa->anext;
+ fa->anext = fb;
+ } else {
+ *fp_a = fb;
+ *fp_b = fa;
+ ft = fb->anext;
+ fb->anext = fa->anext;
+ fa->anext = ft;
+ }
+
+ if(fb->area->sel == fb)
+ fb->area->sel = fa;
+ if(fa->area->sel == fa)
+ fa->area->sel = fb;
+
+ fb->area = fa->area;
+ fa->area = a;
+
+ trect = fa->rect;
+ fa->rect = fb->rect;
+ fb->rect = trect;
+}
+
+void
+focus_frame(Frame *f, Bool restack) {
+ Frame *old, *old_in_a;
+ View *v;
+ Area *a, *old_a;
+
+ a = f->area;
+ v = f->view;
+ old = v->sel->sel;
+ old_a = v->sel;
+ old_in_a = a->sel;
+
+ a->sel = f;
+
+ if(a != old_a)
+ focus_area(f->area);
+
+ if(v != screen->sel)
+ return;
+
+ focus_client(f->client);
+
+ if(!a->floating
+ && ((a->mode == Colstack) || (a->mode == Colmax)))
+ arrange_column(a, False);
+
+ if((f != old)
+ && (f->area == old_a))
+ write_event("ClientFocus 0x%x\n", f->client->win);
+
+ if(restack)
+ restack_view(v);
+}
+
+int
+frame_delta_h() {
+ return def.border + labelh(&def.font);
+}
+
+void
+draw_frame(Frame *f) {
+ BlitzBrush br = { 0 };
+ Frame *tf;
+
+ if(f->view != screen->sel)
+ return;
+
+ br.blitz = &blz;
+ br.font = &def.font;
+ br.drawable = pmap;
+ br.gc = f->client->gc;
+ if(f->client == screen->focus)
+ br.color = def.focuscolor;
+ else
+ br.color = def.normcolor;
+ if(!f->area->floating && f->area->mode == Colmax)
+ for(tf = f->area->frame; tf; tf=tf->anext)
+ if(tf->client == screen->focus) {
+ br.color = def.focuscolor;
+ break;
+ }
+
+ br.rect = f->rect;
+ br.rect.x = 0;
+ br.rect.y = 0;
+ draw_tile(&br);
+
+ br.rect.x += def.font.height - 3;
+ br.rect.width -= br.rect.x;
+ br.rect.height = labelh(&def.font);
+ draw_label(&br, f->client->name);
+
+ br.border = 1;
+ br.rect.width += br.rect.x;
+ br.rect.x = 0;
+ f->titlebar.x = br.rect.x + 3;
+ f->titlebar.height = br.rect.height - 3;
+ f->titlebar.y = br.rect.y + 3;
+ f->titlebar.width = br.rect.width - 6;
+ draw_border(&br);
+ br.rect.height = f->rect.height;
+ if(def.border)
+ draw_border(&br);
+
+ if(f->client->urgent)
+ br.color.bg = br.color.fg;
+ br.rect.x = 2;
+ br.rect.y = 2;
+ br.rect.height = labelh(&def.font) - 4;
+ br.rect.width = def.font.height - 3;
+ f->grabbox = br.rect;
+ draw_tile(&br);
+
+ XCopyArea(
+ /* display */ blz.dpy,
+ /* src */ pmap,
+ /* dest */ f->client->framewin,
+ /* gc */ f->client->gc,
+ /* x, y */ 0, 0,
+ /* width */ f->rect.width,
+ /* height */ f->rect.height,
+ /* dest_x */ 0,
+ /* dest_y */ 0
+ );
+ XSync(blz.dpy, False);
+}
+
+void
+draw_frames() {
+ Client *c;
+
+ for(c=client; c; c=c->next)
+ if(c->sel && c->sel->view == screen->sel)
+ draw_frame(c->sel);
+}
+
+void
+check_frame_constraints(XRectangle *rect) {
+ int max_height;
+ int barheight;
+
+ barheight = screen->brect.height;
+ max_height = screen->rect.height - barheight;
+
+ if(rect->height > max_height)
+ rect->height = max_height;
+ if(rect->width > screen->rect.width)
+ rect->width = screen->rect.width;
+ if(rect->x + barheight > screen->rect.width)
+ rect->x = screen->rect.width - barheight;
+ if(rect->y + barheight > max_height)
+ rect->y = max_height - barheight;
+ if(r_east(rect) < barheight)
+ rect->x = barheight - rect->width;
+ if(r_south(rect) < barheight)
+ rect->y = barheight - rect->height;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/fs.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/fs.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,974 @@
+/* Copyright ©2006 Kris Maglione <fbsdaemon at gmail dot com>
+ * See LICENSE file for license details.
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "wmii.h"
+
+
+/* Datatypes: */
+/**************/
+typedef struct Dirtab Dirtab;
+struct Dirtab {
+ char *name;
+ uchar qtype;
+ uint type;
+ uint perm;
+};
+
+typedef struct FidLink FidLink;
+struct FidLink {
+ FidLink *next;
+ Fid *fid;
+};
+
+typedef struct FileId FileId;
+struct FileId {
+ FileId *next;
+ union {
+ void *ref;
+ char *buf;
+ Bar *bar;
+ Bar **bar_p;
+ View *view;
+ Client *client;
+ Ruleset *rule;
+ BlitzColor *col;
+ } content;
+ uint id;
+ uint index;
+ Dirtab tab;
+ ushort nref;
+};
+
+/* Constants */
+/*************/
+enum { /* Dirs */
+ FsRoot, FsDClient, FsDClients, FsDBars,
+ FsDTag, FsDTags,
+ /* Files */
+ FsFBar, FsFCctl, FsFColRules,
+ FsFCtags, FsFEvent, FsFKeys, FsFRctl,
+ FsFTagRules, FsFTctl, FsFTindex,
+ FsFprops
+};
+
+/* Error messages */
+static char
+ Enoperm[] = "permission denied",
+ Enofile[] = "file not found",
+ Ebadvalue[] = "bad value",
+ Einterrupted[] = "interrupted",
+ Ebadcmd[] = "bad command";
+
+/* Macros */
+#define QID(t, i) (((vlong)((t)&0xFF)<<32)|((i)&0xFFFFFFFF))
+
+/* Global Vars */
+/***************/
+FileId *free_fileid;
+Ixp9Req *pending_event_reads;
+Ixp9Req *outgoing_event_reads;
+FidLink *pending_event_fids;
+Ixp9Srv p9srv = {
+ .open= fs_open,
+ .walk= fs_walk,
+ .read= fs_read,
+ .stat= fs_stat,
+ .write= fs_write,
+ .clunk= fs_clunk,
+ .flush= fs_flush,
+ .attach=fs_attach,
+ .create=fs_create,
+ .remove=fs_remove,
+ .freefid=fs_freefid
+};
+
+/* ad-hoc file tree. Empty names ("") indicate dynamic entries to be filled
+ * in by lookup_file */
+static Dirtab
+dirtab_root[]= {{".", QTDIR, FsRoot, 0500|P9_DMDIR },
+ {"rbar", QTDIR, FsDBars, 0700|P9_DMDIR },
+ {"lbar", QTDIR, FsDBars, 0700|P9_DMDIR },
+ {"client", QTDIR, FsDClients, 0500|P9_DMDIR },
+ {"tag", QTDIR, FsDTags, 0500|P9_DMDIR },
+ {"ctl", QTAPPEND, FsFRctl, 0600|P9_DMAPPEND },
+ {"colrules", QTFILE, FsFColRules, 0600 },
+ {"event", QTFILE, FsFEvent, 0600 },
+ {"keys", QTFILE, FsFKeys, 0600 },
+ {"tagrules", QTFILE, FsFTagRules, 0600 },
+ {nil}},
+dirtab_clients[]={{".", QTDIR, FsDClients, 0500|P9_DMDIR },
+ {"", QTDIR, FsDClient, 0500|P9_DMDIR },
+ {nil}},
+dirtab_client[]= {{".", QTDIR, FsDClient, 0500|P9_DMDIR },
+ {"ctl", QTAPPEND, FsFCctl, 0600|P9_DMAPPEND },
+ {"tags", QTFILE, FsFCtags, 0600 },
+ {"props", QTFILE, FsFprops, 0400 },
+ {nil}},
+dirtab_bars[]= {{".", QTDIR, FsDBars, 0700|P9_DMDIR },
+ {"", QTFILE, FsFBar, 0600 },
+ {nil}},
+dirtab_tags[]= {{".", QTDIR, FsDTags, 0500|P9_DMDIR },
+ {"", QTDIR, FsDTag, 0500|P9_DMDIR },
+ {nil}},
+dirtab_tag[]= {{".", QTDIR, FsDTag, 0500|P9_DMDIR },
+ {"ctl", QTAPPEND, FsFTctl, 0600|P9_DMAPPEND },
+ {"index", QTFILE, FsFTindex, 0400 },
+ {nil}};
+/* Writing the lists separately and using an array of their references
+ * removes the need for casting and allows for C90 conformance,
+ * since otherwise we would need to use compound literals */
+static Dirtab *dirtab[] = {
+ [FsRoot] = dirtab_root,
+ [FsDBars] = dirtab_bars,
+ [FsDClients] = dirtab_clients,
+ [FsDClient] = dirtab_client,
+ [FsDTags] = dirtab_tags,
+ [FsDTag] = dirtab_tag,
+};
+
+/* Utility Functions */
+/*********************/
+
+/* get_file/free_file save and reuse old FileId structs
+ * since so many of them are needed for so many
+ * purposes */
+static FileId *
+get_file() {
+ FileId *temp;
+ if(!free_fileid) {
+ uint i = 15;
+ temp = emallocz(sizeof(FileId) * i);
+ for(; i; i--) {
+ temp->next = free_fileid;
+ free_fileid = temp++;
+ }
+ }
+ temp = free_fileid;
+ free_fileid = temp->next;
+ temp->nref = 1;
+ temp->next = nil;
+ return temp;
+}
+
+static void
+free_file(FileId *f) {
+ if(--f->nref)
+ return;
+ free(f->tab.name);
+ f->next = free_fileid;
+ free_fileid = f;
+}
+
+/* This function's name belies it's true purpose. It increases
+ * the reference counts of the FileId list */
+static void
+clone_files(FileId *f) {
+ for(; f; f=f->next)
+ assert(f->nref++);
+}
+
+/* This should be moved to libixp */
+static void
+write_buf(Ixp9Req *r, char *buf, uint len) {
+ if(r->ifcall.offset >= len)
+ return;
+
+ len -= r->ifcall.offset;
+ if(len > r->ifcall.count)
+ len = r->ifcall.count;
+ r->ofcall.data = emalloc(len);
+ memcpy(r->ofcall.data, buf + r->ifcall.offset, len);
+ r->ofcall.count = len;
+}
+
+/* This should be moved to libixp */
+void
+write_to_buf(Ixp9Req *r, void *buf, uint *len, uint max) {
+ uint offset, count;
+
+ offset = (r->fid->omode&P9_OAPPEND) ? *len : r->ifcall.offset;
+ if(offset > *len || r->ifcall.count == 0) {
+ r->ofcall.count = 0;
+ return;
+ }
+
+ count = r->ifcall.count;
+ if(max && (count > max - offset))
+ count = max - offset;
+
+ *len = offset + count;
+
+ if(max == 0) {
+ *(void **)buf = erealloc(*(void **)buf, *len + 1);
+ buf = *(void **)buf;
+ }
+
+ memcpy((uchar*)buf + offset, r->ifcall.data, count);
+ r->ofcall.count = count;
+ ((char *)buf)[offset+count] = '\0';
+}
+
+/* This should be moved to libixp */
+void
+data_to_cstring(Ixp9Req *r) {
+ uint i;
+ i = r->ifcall.count;
+ if(!i || r->ifcall.data[i - 1] != '\n')
+ r->ifcall.data = erealloc(r->ifcall.data, ++i);
+ assert(r->ifcall.data);
+ r->ifcall.data[i - 1] = '\0';
+}
+
+char *
+message_root(char *message)
+{
+ uint n;
+
+ if(!strchr(message, ' ')) {
+ snprintf(buffer, BUFFER_SIZE, "%s ", message);
+ message = buffer;
+ }
+ if(!strcmp(message, "quit "))
+ srv.running = 0;
+ else if(!strncmp(message, "exec ", 5)) {
+ srv.running = 0;
+ execstr = estrdup(&message[5]);
+ message += strlen(message);
+ }
+ else if(!strncmp(message, "view ", 5))
+ select_view(&message[5]);
+ else if(!strncmp(message, "selcolors ", 10)) {
+ fprintf(stderr, "wmii: warning: selcolors have been removed\n");
+ return Ebadcmd;
+ }
+ else if(!strncmp(message, "focuscolors ", 12)) {
+ message += 12;
+ n = strlen(message);
+ return parse_colors(&message, (int *)&n, &def.focuscolor);
+ }
+ else if(!strncmp(message, "normcolors ", 11)) {
+ message += 11;
+ n = strlen(message);
+ return parse_colors(&message, (int *)&n, &def.normcolor);
+ }
+ else if(!strncmp(message, "font ", 5)) {
+ message += 5;
+ free(def.font.fontstr);
+ def.font.fontstr = estrdup(message);
+ loadfont(&blz, &def.font);
+ resize_bar(screen);
+ }
+ else if(!strncmp(message, "border ", 7)) {
+ message += 7;
+ n = (uint)strtol(message, &message, 10);
+ if(*message)
+ return Ebadvalue;
+ def.border = n;
+ }
+ else if(!strncmp(message, "grabmod ", 8)) {
+ message += 8;
+ ulong mod;
+ mod = mod_key_of_str(message);
+ if(!(mod & (Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)))
+ return Ebadvalue;
+ strncpy(def.grabmod, message, sizeof(def.grabmod));
+ def.mod = mod;
+ if(view)
+ restack_view(screen->sel);
+ }
+ else
+ return Ebadcmd;
+ return nil;
+}
+
+char *
+read_root_ctl() {
+ uint i = 0;
+ if(screen->sel)
+ i += snprintf(&buffer[i], (BUFFER_SIZE - i), "view %s\n", screen->sel->name);
+ i += snprintf(&buffer[i], (BUFFER_SIZE - i), "focuscolors %s\n", def.focuscolor.colstr);
+ i += snprintf(&buffer[i], (BUFFER_SIZE - i), "normcolors %s\n", def.normcolor.colstr);
+ i += snprintf(&buffer[i], (BUFFER_SIZE - i), "font %s\n", def.font.fontstr);
+ i += snprintf(&buffer[i], (BUFFER_SIZE - i), "grabmod %s\n", def.grabmod);
+ i += snprintf(&buffer[i], (BUFFER_SIZE - i), "border %d\n", def.border);
+ return buffer;
+}
+
+
+void
+respond_event(Ixp9Req *r) {
+ FileId *f = r->fid->aux;
+ if(f->content.buf) {
+ r->ofcall.data = (void *)f->content.buf;
+ r->ofcall.count = strlen(f->content.buf);
+ respond(r, nil);
+ f->content.buf = nil;
+ }else{
+ r->aux = pending_event_reads;
+ pending_event_reads = r;
+ }
+}
+
+void
+write_event(char *format, ...) {
+ uint len, slen;
+ va_list ap;
+ FidLink *f;
+ FileId *fi;
+ Ixp9Req *req;
+
+ va_start(ap, format);
+ vsnprintf(buffer, BUFFER_SIZE, format, ap);
+ va_end(ap);
+ if(!(len = strlen(buffer)))
+ return;
+ for(f=pending_event_fids; f; f=f->next) {
+ fi = f->fid->aux;
+ slen = fi->content.buf ? strlen(fi->content.buf) : 0;
+ fi->content.buf = (char *) erealloc(fi->content.buf, slen + len + 1);
+ (fi->content.buf)[slen] = '\0';
+ strcat(fi->content.buf, buffer);
+ }
+ outgoing_event_reads = pending_event_reads;
+ pending_event_reads = nil;
+ while((req = outgoing_event_reads)) {
+ outgoing_event_reads = outgoing_event_reads->aux;
+ respond_event(req);
+ }
+}
+
+static void
+dostat(Stat *s, uint len, FileId *f) {
+ s->type = 0;
+ s->dev = 0;
+ s->qid.path = QID(f->tab.type, f->id);
+ s->qid.version = 0;
+ s->qid.type = f->tab.qtype;
+ s->mode = f->tab.perm;
+ s->atime = time(nil);
+ s->mtime = time(nil);
+ s->length = len;
+ s->name = f->tab.name;
+ s->uid = user;
+ s->gid = user;
+ s->muid = user;
+}
+
+/* lookup_file */
+/***************/
+/* All lookups and directory organization should be performed through
+ * lookup_file, mostly through the dirtabs[] tree. */
+static FileId *
+lookup_file(FileId *parent, char *name)
+{
+ FileId *ret, *file, **last;
+ Dirtab *dir;
+ Client *c;
+ View *v;
+ Bar *b;
+ uint id;
+
+ if(!(parent->tab.perm & P9_DMDIR))
+ return nil;
+ dir = dirtab[parent->tab.type];
+ last = &ret;
+ ret = nil;
+ for(; dir->name; dir++) {
+ /* Dynamic dirs */
+ if(!*dir->name) { /* strlen(dir->name) == 0 */
+ switch(parent->tab.type) {
+ case FsDClients:
+ if(!name || !strcmp(name, "sel")) {
+ if((c = sel_client())) {
+ file = get_file();
+ *last = file;
+ last = &file->next;
+ file->content.client = c;
+ file->id = c->win;
+ file->index = c->win;
+ file->tab = *dir;
+ file->tab.name = estrdup("sel");
+ }if(name) goto LastItem;
+ }
+ if(name) {
+ id = (uint)strtol(name, &name, 16);
+ if(*name) goto NextItem;
+ }
+ for(c=client; c; c=c->next) {
+ if(!name || c->win == id) {
+ file = get_file();
+ *last = file;
+ last = &file->next;
+ file->content.client = c;
+ file->id = c->win;
+ file->index = c->win;
+ file->tab = *dir;
+ file->tab.name = emallocz(16);
+ snprintf(file->tab.name, 16, "0x%x", (uint)c->win);
+ if(name) goto LastItem;
+ }
+ }
+ break;
+ case FsDTags:
+ if(!name || !strcmp(name, "sel")) {
+ if(screen->sel) {
+ file = get_file();
+ *last = file;
+ last = &file->next;
+ file->content.view = screen->sel;
+ file->id = screen->sel->id;
+ file->tab = *dir;
+ file->tab.name = estrdup("sel");
+ }if(name) goto LastItem;
+ }
+ for(v=view; v; v=v->next) {
+ if(!name || !strcmp(name, v->name)) {
+ file = get_file();
+ *last = file;
+ last = &file->next;
+ file->content.view = v;
+ file->id = v->id;
+ file->tab = *dir;
+ file->tab.name = estrdup(v->name);
+ if(name) goto LastItem;
+ }
+ }
+ break;
+ case FsDBars:
+ for(b=*parent->content.bar_p; b; b=b->next) {
+ if(!name || !strcmp(name, b->name)) {
+ file = get_file();
+ *last = file;
+ last = &file->next;
+ file->content.bar = b;
+ file->id = b->id;
+ file->tab = *dir;
+ file->tab.name = estrdup(b->name);
+ if(name) goto LastItem;
+ }
+ }
+ break;
+ }
+ }else /* Static dirs */
+ if(!name || !strcmp(name, dir->name)) {
+ file = get_file();
+ *last = file;
+ last = &file->next;
+ file->id = 0;
+ file->content.ref = parent->content.ref;
+ file->index = parent->index;
+ file->tab = *dir;
+ file->tab.name = estrdup(file->tab.name);
+ /* Special considerations: */
+ switch(file->tab.type) {
+ case FsDBars:
+ if(!strcmp(file->tab.name, "lbar"))
+ file->content.bar_p = &screen[0].bar[BarLeft];
+ else
+ file->content.bar_p = &screen[0].bar[BarRight];
+ break;
+ case FsFColRules:
+ file->content.rule = &def.colrules;
+ break;
+ case FsFTagRules:
+ file->content.rule = &def.tagrules;
+ break;
+ }
+ if(name) goto LastItem;
+ }
+ NextItem:
+ continue;
+ }
+LastItem:
+ *last = nil;
+ return ret;
+}
+
+Bool
+verify_file(FileId *f) {
+ FileId *nf;
+
+ if(!f->next)
+ return True;
+ if(verify_file(f->next)) {
+ nf = lookup_file(f->next, f->tab.name);
+ if(nf) {
+ free_file(nf);
+ return True;
+ }
+ }
+ return False;
+}
+
+/* Service Functions */
+/*********************/
+void
+fs_attach(Ixp9Req *r) {
+ FileId *f = get_file();
+ f->tab = dirtab[FsRoot][0];
+ f->tab.name = estrdup("/");
+ f->content.ref = nil; /* shut up valgrind */
+ r->fid->aux = f;
+ r->fid->qid.type = f->tab.qtype;
+ r->fid->qid.path = QID(f->tab.type, 0);
+ r->ofcall.qid = r->fid->qid;
+ respond(r, nil);
+}
+
+void
+fs_walk(Ixp9Req *r) {
+ FileId *f, *nf;
+ int i;
+
+ f = r->fid->aux;
+ clone_files(f);
+ for(i=0; i < r->ifcall.nwname; i++) {
+ if(!strcmp(r->ifcall.wname[i], "..")) {
+ if(f->next) {
+ nf=f;
+ f=f->next;
+ free_file(nf);
+ }
+ }else{
+ nf = lookup_file(f, r->ifcall.wname[i]);
+ if(!nf)
+ break;
+ assert(!nf->next);
+ if(strcmp(r->ifcall.wname[i], ".")) {
+ nf->next = f;
+ f = nf;
+ }
+ }
+ r->ofcall.wqid[i].type = f->tab.qtype;
+ r->ofcall.wqid[i].path = QID(f->tab.type, f->id);
+ }
+ /* There should be a way to do this on freefid() */
+ if(i < r->ifcall.nwname) {
+ while((nf = f)) {
+ f=f->next;
+ free_file(nf);
+ }
+ respond(r, Enofile);
+ return;
+ }
+ /* Remove refs for r->fid if no new fid */
+ if(r->ifcall.fid == r->ifcall.newfid) {
+ nf = r->fid->aux;
+ r->fid->aux = f;
+ while((f = nf)) {
+ nf = nf->next;
+ free_file(f);
+ }
+ }else
+ r->newfid->aux = f;
+ r->ofcall.nwqid = i;
+ respond(r, nil);
+}
+
+uint
+fs_size(FileId *f) {
+ switch(f->tab.type) {
+ default:
+ return 0;
+ case FsFColRules:
+ case FsFTagRules:
+ return f->content.rule->size;
+ case FsFKeys:
+ return def.keyssz;
+ case FsFCtags:
+ return strlen(f->content.client->tags);
+ case FsFprops:
+ return strlen(f->content.client->props);
+ }
+}
+
+void
+fs_stat(Ixp9Req *r) {
+ Message m;
+ Stat s;
+ int size;
+ uchar *buf;
+ FileId *f = r->fid->aux;
+
+ if(!verify_file(f)) {
+ respond(r, Enofile);
+ return;
+ }
+
+ dostat(&s, fs_size(f), f);
+ r->ofcall.nstat = size = ixp_sizeof_stat(&s);
+ buf = emallocz(size);
+
+ m = ixp_message(buf, size, MsgPack);
+ ixp_pstat(&m, &s);
+
+ r->ofcall.stat = m.data;
+ respond(r, nil);
+}
+
+void
+fs_read(Ixp9Req *r) {
+ char *buf;
+ FileId *f, *tf;
+ int n, offset;
+ int size;
+
+ offset = 0;
+ f = r->fid->aux;
+
+ if(!verify_file(f)) {
+ respond(r, Enofile);
+ return;
+ }
+
+ if(f->tab.perm & P9_DMDIR && f->tab.perm & 0400) {
+ Stat s;
+ Message m;
+
+ offset = 0;
+ size = r->ifcall.count;
+ buf = emallocz(size);
+ m = ixp_message(buf, size, MsgPack);
+
+ tf = f = lookup_file(f, nil);
+ /* Note: f->tab.name == "." so we skip it */
+ for(f=f->next; f; f=f->next) {
+ dostat(&s, fs_size(f), f);
+ n = ixp_sizeof_stat(&s);
+ if(offset >= r->ifcall.offset) {
+ if(size < n)
+ break;
+ ixp_pstat(&m, &s);
+ }
+ offset += n;
+ }
+ while((f = tf)) {
+ tf=tf->next;
+ free_file(f);
+ }
+ r->ofcall.count = r->ifcall.count - size;
+ r->ofcall.data = m.data;
+ respond(r, nil);
+ return;
+ }
+ else{
+ switch(f->tab.type) {
+ case FsFprops:
+ write_buf(r, f->content.client->props, strlen(f->content.client->props));
+ respond(r, nil);
+ return;
+ case FsFColRules:
+ case FsFTagRules:
+ write_buf(r, f->content.rule->string, f->content.rule->size);
+ respond(r, nil);
+ return;
+ case FsFKeys:
+ write_buf(r, def.keys, def.keyssz);
+ respond(r, nil);
+ return;
+ case FsFCtags:
+ write_buf(r, f->content.client->tags, strlen(f->content.client->tags));
+ respond(r, nil);
+ return;
+ case FsFTctl:
+ write_buf(r, f->content.view->name, strlen(f->content.view->name));
+ respond(r, nil);
+ return;
+ case FsFBar:
+ write_buf(r, f->content.bar->buf, strlen(f->content.bar->buf));
+ respond(r, nil);
+ return;
+ case FsFRctl:
+ buf = read_root_ctl();
+ write_buf(r, buf, strlen(buf));
+ respond(r, nil);
+ return;
+ case FsFCctl:
+ if(r->ifcall.offset) {
+ respond(r, nil);
+ return;
+ }
+ r->ofcall.data = emallocz(16);
+ n = snprintf(r->ofcall.data, 16, "0x%x", (uint)f->index);
+ assert(n >= 0);
+ r->ofcall.count = n;
+ respond(r, nil);
+ return;
+ case FsFTindex:
+ buf = (char *)view_index(f->content.view);
+ n = strlen(buf);
+ write_buf(r, buf, n);
+ respond(r, nil);
+ return;
+ case FsFEvent:
+ respond_event(r);
+ return;
+ }
+ }
+ /* This is an assert because it should this should not be called if
+ * the file is not open for reading. */
+ assert(!"Read called on an unreadable file");
+}
+
+/* This function needs to be seriously cleaned up */
+void
+fs_write(Ixp9Req *r) {
+ FileId *f;
+ char *errstr = nil;
+ uint i;
+
+ if(r->ifcall.count == 0) {
+ respond(r, nil);
+ return;
+ }
+ f = r->fid->aux;
+
+ if(!verify_file(f)) {
+ respond(r, Enofile);
+ return;
+ }
+
+ switch(f->tab.type) {
+ case FsFColRules:
+ case FsFTagRules:
+ write_to_buf(r, &f->content.rule->string, &f->content.rule->size, 0);
+ respond(r, nil);
+ return;
+ case FsFKeys:
+ write_to_buf(r, &def.keys, &def.keyssz, 0);
+ respond(r, nil);
+ return;
+ case FsFCtags:
+ data_to_cstring(r);
+ apply_tags(f->content.client, r->ifcall.data);
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ return;
+ case FsFBar:
+ /* XXX: This should validate after each write */
+ i = strlen(f->content.bar->buf);
+ write_to_buf(r, &f->content.bar->buf, &i, 279);
+ r->ofcall.count = i - r->ifcall.offset;
+ respond(r, nil);
+ return;
+ case FsFCctl:
+ data_to_cstring(r);
+ if((errstr = message_client(f->content.client, r->ifcall.data))) {
+ respond(r, errstr);
+ return;
+ }
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ return;
+ case FsFTctl:
+ data_to_cstring(r);
+ if((errstr = message_view(f->content.view, r->ifcall.data))) {
+ respond(r, errstr);
+ return;
+ }
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ return;
+ case FsFRctl:
+ data_to_cstring(r);
+ { uint n;
+ char *toks[32];
+ n = tokenize(toks, 32, r->ifcall.data, '\n');
+ for(i = 0; i < n; i++) {
+ if(errstr)
+ message_root(toks[i]);
+ else
+ errstr = message_root(toks[i]);
+ }
+ }
+ if(screen->sel)
+ focus_view(screen, screen->sel);
+ if(errstr) {
+ respond(r, errstr);
+ return;
+ }
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ return;
+ case FsFEvent:
+ if(r->ifcall.data[r->ifcall.count-1] == '\n')
+ write_event("%.*s", r->ifcall.count, r->ifcall.data);
+ else
+ write_event("%.*s\n", r->ifcall.count, r->ifcall.data);
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ return;
+ }
+ /* This is an assert because this function should not be called if
+ * the file is not open for writing. */
+ assert(!"Write called on an unwritable file");
+}
+
+void
+fs_open(Ixp9Req *r) {
+ FidLink *fl;
+ FileId *f = r->fid->aux;
+
+ if(!verify_file(f)) {
+ respond(r, Enofile);
+ return;
+ }
+
+ switch(f->tab.type) {
+ case FsFEvent:
+ fl = emallocz(sizeof(FidLink));
+ fl->fid = r->fid;
+ fl->next = pending_event_fids;
+ pending_event_fids = fl;
+ break;
+ }
+ if((r->ifcall.mode&3) == P9_OEXEC) {
+ respond(r, Enoperm);
+ return;
+ }
+ if((r->ifcall.mode&3) != P9_OREAD && !(f->tab.perm & 0200)) {
+ respond(r, Enoperm);
+ return;
+ }
+ if((r->ifcall.mode&3) != P9_OWRITE && !(f->tab.perm & 0400)) {
+ respond(r, Enoperm);
+ return;
+ }
+ if((r->ifcall.mode&~(3|P9_OAPPEND|P9_OTRUNC))) {
+ respond(r, Enoperm);
+ return;
+ }
+ respond(r, nil);
+}
+
+void
+fs_create(Ixp9Req *r) {
+ FileId *f = r->fid->aux;
+
+ switch(f->tab.type) {
+ default:
+ /* XXX: This should be taken care of by the library */
+ respond(r, Enoperm);
+ return;
+ case FsDBars:
+ if(!strlen(r->ifcall.name)) {
+ respond(r, Ebadvalue);
+ return;
+ }
+ create_bar(f->content.bar_p, r->ifcall.name);
+ f = lookup_file(f, r->ifcall.name);
+ if(!f) {
+ respond(r, Enofile);
+ return;
+ }
+ r->ofcall.qid.type = f->tab.qtype;
+ r->ofcall.qid.path = QID(f->tab.type, f->id);
+ f->next = r->fid->aux;
+ r->fid->aux = f;
+ respond(r, nil);
+ break;
+ }
+}
+
+void
+fs_remove(Ixp9Req *r) {
+ FileId *f = r->fid->aux;
+
+ if(!verify_file(f)) {
+ respond(r, Enofile);
+ return;
+ }
+
+
+ switch(f->tab.type) {
+ default:
+ /* XXX: This should be taken care of by the library */
+ respond(r, Enoperm);
+ return;
+ case FsFBar:
+ destroy_bar(f->next->content.bar_p, f->content.bar);
+ draw_bar(screen);
+ respond(r, nil);
+ break;
+ }
+}
+
+void
+fs_clunk(Ixp9Req *r) {
+ Client *c;
+ FidLink **fl, *ft;
+ char *buf;
+ int i;
+ FileId *f = r->fid->aux;
+
+ if(!verify_file(f)) {
+ respond(r, nil);
+ return;
+ }
+
+ switch(f->tab.type) {
+ case FsFColRules:
+ update_rules(&f->content.rule->rule, f->content.rule->string);
+ break;
+ case FsFTagRules:
+ update_rules(&f->content.rule->rule, f->content.rule->string);
+ for(c=client; c; c=c->next)
+ apply_rules(c);
+ update_views();
+ break;
+ case FsFKeys:
+ update_keys();
+ break;
+ case FsFBar:
+ buf = f->content.bar->buf;
+ i = strlen(f->content.bar->buf);
+ parse_colors(&buf, &i, &f->content.bar->brush.color);
+ while(i > 0 && buf[i - 1] == '\n')
+ buf[--i] = '\0';
+ strncpy(f->content.bar->text, buf, sizeof(f->content.bar->text));
+ draw_bar(screen);
+ break;
+ case FsFEvent:
+ for(fl=&pending_event_fids; *fl; fl=&(*fl)->next)
+ if((*fl)->fid == r->fid) {
+ ft = *fl;
+ *fl = (*fl)->next;
+ f = ft->fid->aux;
+ free(f->content.buf);
+ free(ft);
+ break;
+ }
+ break;
+ }
+ respond(r, nil);
+}
+
+void
+fs_flush(Ixp9Req *r) {
+ Ixp9Req **i, **j;
+
+ for(i=&pending_event_reads; i != &outgoing_event_reads; i=&outgoing_event_reads)
+ for(j=i; *j; j=(Ixp9Req **)&(*j)->aux)
+ if(*j == r->oldreq) {
+ *j = (*j)->aux;
+ respond(r->oldreq, Einterrupted);
+ goto done;
+ }
+done:
+ respond(r, nil);
+}
+
+void
+fs_freefid(Fid *f) {
+ FileId *id, *tid;
+
+ for(id=f->aux; id; id = tid) {
+ tid = id->next;
+ free_file(id);
+ }
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/geom.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/geom.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,84 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+#include "wmii.h"
+
+Bool
+ptinrect(int x, int y, XRectangle * r) {
+ return (x >= r->x) && (x < r_east(r))
+ && (y >= r->y) && (y < r_south(r));
+}
+
+BlitzAlign
+quadrant(XRectangle *rect, int x, int y) {
+ BlitzAlign ret = 0;
+ x -= rect->x;
+ y -= rect->y;
+
+ if(x >= rect->width * .5)
+ ret |= EAST;
+ if(x <= rect->width * .5)
+ ret |= WEST;
+ if(y <= rect->height * .5)
+ ret |= NORTH;
+ if(y >= rect->height * .5)
+ ret |= SOUTH;
+
+ return ret;
+}
+
+Cursor
+cursor_of_quad(BlitzAlign align) {
+ switch(align) {
+ case NEAST:
+ return cursor[CurNECorner];
+ case NWEST:
+ return cursor[CurNWCorner];
+ case SEAST:
+ return cursor[CurSECorner];
+ case SWEST:
+ return cursor[CurSWCorner];
+ default:
+ return cursor[CurMove];
+ }
+}
+
+/* Syntax: <x> <y> <width> <height> */
+int
+strtorect(XRectangle *r, const char *val) {
+ XRectangle new;
+ if (!val)
+ return -1;
+
+ if(sscanf(val, "%hd %hd %hu %hu", &new.x, &new.y, &new.width, &new.height) != 4)
+ return -1;
+
+ *r = new;
+ return 0;
+}
+
+int
+r_east(XRectangle *r) {
+ return r->x + r->width;
+}
+
+int
+r_south(XRectangle *r) {
+ return r->y + r->height;
+}
+
+BlitzAlign
+get_sticky(XRectangle *src, XRectangle *dst) {
+ BlitzAlign stickycorner = 0;
+
+ if(src->x != dst->x && r_east(src) == r_east(dst))
+ stickycorner |= EAST;
+ else
+ stickycorner |= WEST;
+ if(src->y != dst->y && r_south(src) == r_south(dst))
+ stickycorner |= SOUTH;
+ else
+ stickycorner |= NORTH;
+
+ return stickycorner;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/key.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/key.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,243 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+#include "wmii.h"
+
+void
+init_lock_keys() {
+ XModifierKeymap *modmap;
+ KeyCode num_lock;
+ static int masks[] = {
+ ShiftMask, LockMask, ControlMask, Mod1Mask,
+ Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
+ };
+ int i;
+
+ num_lock_mask = 0;
+ modmap = XGetModifierMapping(blz.dpy);
+ num_lock = XKeysymToKeycode(blz.dpy, XStringToKeysym("Num_Lock"));
+ if(modmap && modmap->max_keypermod > 0) {
+ int max = (sizeof(masks) / sizeof(int)) * modmap->max_keypermod;
+ for(i = 0; i < max; i++)
+ if(num_lock && (modmap->modifiermap[i] == num_lock))
+ num_lock_mask = masks[i / modmap->max_keypermod];
+ }
+ XFreeModifiermap(modmap);
+ valid_mask = 255 & ~(num_lock_mask | LockMask);
+}
+
+ulong
+mod_key_of_str(char *val) {
+ ulong mod = 0;
+
+ if (strstr(val, "Shift"))
+ mod |= ShiftMask;
+ if (strstr(val, "Control"))
+ mod |= ControlMask;
+ if (strstr(val, "Mod1"))
+ mod |= Mod1Mask;
+ if (strstr(val, "Mod2"))
+ mod |= Mod2Mask;
+ if (strstr(val, "Mod3"))
+ mod |= Mod3Mask;
+ if (strstr(val, "Mod4"))
+ mod |= Mod4Mask;
+ if (strstr(val, "Mod5"))
+ mod |= Mod5Mask;
+ return mod;
+}
+
+static void
+grab_key(Key *k) {
+ XGrabKey(blz.dpy, k->key, k->mod, blz.root,
+ True, GrabModeAsync, GrabModeAsync);
+ if(num_lock_mask) {
+ XGrabKey(blz.dpy, k->key, k->mod | num_lock_mask, blz.root,
+ True, GrabModeAsync, GrabModeAsync);
+ XGrabKey(blz.dpy, k->key, k->mod | num_lock_mask | LockMask, blz.root,
+ True, GrabModeAsync, GrabModeAsync);
+ }
+ XSync(blz.dpy, False);
+}
+
+static void
+ungrab_key(Key *k) {
+ XUngrabKey(blz.dpy, k->key, k->mod, blz.root);
+ if(num_lock_mask) {
+ XUngrabKey(blz.dpy, k->key, k->mod | num_lock_mask, blz.root);
+ XUngrabKey(blz.dpy, k->key, k->mod | num_lock_mask | LockMask, blz.root);
+ }
+ XSync(blz.dpy, False);
+}
+
+static Key *
+name2key(const char *name) {
+ Key *k;
+ for(k=key; k; k=k->lnext)
+ if(!strncmp(k->name, name, sizeof(k->name))) break;
+ return k;
+}
+
+static Key *
+get_key(const char *name) {
+ char buf[128];
+ char *seq[8];
+ char *kstr;
+ uint i, toks;
+ static ushort id = 1;
+ Key *k = 0, *r = 0;
+
+ if((k = name2key(name))) {
+ ungrab_key(k);
+ return k;
+ }
+ strncpy(buf, name, sizeof(buf));
+ toks = tokenize(seq, 8, buf, ',');
+ for(i = 0; i < toks; i++) {
+ if(!k)
+ r = k = emallocz(sizeof(Key));
+ else {
+ k->next = emallocz(sizeof(Key));
+ k = k->next;
+ }
+ strncpy(k->name, name, sizeof(k->name));
+ kstr = strrchr(seq[i], '-');
+ if(kstr)
+ kstr++;
+ else
+ kstr = seq[i];
+ k->key = XKeysymToKeycode(blz.dpy, XStringToKeysym(kstr));
+ k->mod = mod_key_of_str(seq[i]);
+ }
+ if(r) {
+ r->id = id++;
+ r->lnext = key;
+ key = r;
+ }
+
+ return r;
+}
+
+static void
+next_keystroke(ulong *mod, KeyCode *code) {
+ XEvent e;
+ KeySym sym;
+ *mod = 0;
+
+ do {
+ XMaskEvent(blz.dpy, KeyPressMask, &e);
+ *mod |= e.xkey.state & valid_mask;
+ *code = (KeyCode) e.xkey.keycode;
+ sym = XKeycodeToKeysym(blz.dpy, e.xkey.keycode, 0);
+ } while(IsModifierKey(sym));
+}
+
+static void
+emulate_key_press(ulong mod, KeyCode key) {
+ XEvent e;
+ Window client_win;
+ int revert;
+
+ XGetInputFocus(blz.dpy, &client_win, &revert);
+ e.xkey.type = KeyPress;
+ e.xkey.time = CurrentTime;
+ e.xkey.window = client_win;
+ e.xkey.display = blz.dpy;
+ e.xkey.state = mod;
+ e.xkey.keycode = key;
+ XSendEvent(blz.dpy, client_win, True, KeyPressMask, &e);
+ e.xkey.type = KeyRelease;
+ XSendEvent(blz.dpy, client_win, True, KeyReleaseMask, &e);
+ XSync(blz.dpy, False);
+}
+
+static Key *
+match_keys(Key *k, ulong mod, KeyCode keycode, Bool seq) {
+ Key *ret = nil, *next;
+
+ for(next = k->tnext; k; (k=next) && (next=k->tnext)) {
+ if(seq)
+ k = k->next;
+ if(k && (k->mod == mod) && (k->key == keycode)) {
+ k->tnext = ret;
+ ret = k;
+ }
+ }
+ return ret;
+}
+
+static void
+kpress_seq(Window w, Key *done) {
+ ulong mod;
+ KeyCode key;
+ Key *found;
+
+ next_keystroke(&mod, &key);
+ found = match_keys(done, mod, key, True);
+ if((done->mod == mod) && (done->key == key))
+ emulate_key_press(mod, key); /* double key */
+ else {
+ if(!found) {
+ XBell(blz.dpy, 0);
+ } /* grabbed but not found */
+ else if(!found->tnext && !found->next)
+ write_event("Key %s\n", found->name);
+ else
+ kpress_seq(w, found);
+ }
+}
+
+void
+kpress(Window w, ulong mod, KeyCode keycode) {
+ Key *k, *found;
+
+ for(k=key; k; k=k->lnext)
+ k->tnext=k->lnext;
+ found = match_keys(key, mod, keycode, False);
+ if(!found) {
+ XBell(blz.dpy, 0);
+ } /* grabbed but not found */
+ else if(!found->tnext && !found->next)
+ write_event("Key %s\n", found->name);
+ else {
+ XGrabKeyboard(blz.dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ kpress_seq(w, found);
+ XUngrabKeyboard(blz.dpy, CurrentTime);
+ XSync(blz.dpy, False);
+ }
+}
+
+void
+update_keys() {
+ Key *k, *n;
+ char *l, *p;
+
+ init_lock_keys();
+ while((k = key)) {
+ key = key->lnext;
+ ungrab_key(k);
+ while((n = k)) {
+ k = k->next;
+ free(n);
+ }
+ }
+ for(l = p = def.keys; p && *p;) {
+ if(*p == '\n') {
+ *p = 0;
+ if((k = get_key(l)))
+ grab_key(k);
+ *p = '\n';
+ l = ++p;
+ }
+ else
+ p++;
+ }
+ if(l < p && strlen(l)) {
+ if((k = get_key(l)))
+ grab_key(k);
+ }
+ XSync(blz.dpy, False);
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/main.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/main.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,583 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <X11/Xatom.h>
+#include <X11/Xproto.h>
+#include <X11/cursorfont.h>
+#include <errno.h>
+#include <locale.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "wmii.h"
+
+static const char
+ version[] = "wmii - " VERSION ", ©2007 Kris Maglione\n";
+
+static int (*x_error_handler) (Display *, XErrorEvent *);
+static char *address, *ns_path;
+static Bool check_other_wm;
+static struct sigaction sa;
+static struct passwd *passwd;
+static int sleeperfd, sock;
+
+static void
+usage() {
+ fatal("usage: wmii [-a <address>] [-r <wmiirc>] [-v]\n");
+}
+
+static void
+scan_wins() {
+ int i;
+ uint num;
+ Window *wins;
+ XWindowAttributes wa;
+ Window d1, d2;
+
+ if(XQueryTree(blz.dpy, blz.root, &d1, &d2, &wins, &num)) {
+ for(i = 0; i < num; i++) {
+ if(!XGetWindowAttributes(blz.dpy, wins[i], &wa))
+ continue;
+ if(wa.override_redirect || XGetTransientForHint(blz.dpy, wins[i], &d1))
+ continue;
+ if(wa.map_state == IsViewable)
+ manage_client(create_client(wins[i], &wa));
+ }
+ for(i = 0; i < num; i++) {
+ if(!XGetWindowAttributes(blz.dpy, wins[i], &wa))
+ continue;
+ if(XGetTransientForHint(blz.dpy, wins[i], &d1)
+ && wa.map_state == IsViewable)
+ manage_client(create_client(wins[i], &wa));
+ }
+ }
+ if(wins)
+ XFree(wins);
+}
+
+int
+win_proto(Window w) {
+ Atom *protocols;
+ Atom real;
+ ulong nitems, extra;
+ int i, format, status, protos;
+
+ status = XGetWindowProperty(
+ /* display */ blz.dpy,
+ /* window */ w,
+ /* property */ atom[WMProtocols],
+ /* offset */ 0L,
+ /* length */ 20L,
+ /* delete */ False,
+ /* req_type */ XA_ATOM,
+ /* type_ret */ &real,
+ /* format_ret */&format,
+ /* nitems_ret */&nitems,
+ /* extra_bytes */&extra,
+ /* prop_return */(uchar**)&protocols
+ );
+
+ if(status != Success || protocols == 0) {
+ return 0;
+ }
+
+ if(nitems == 0) {
+ free(protocols);
+ return 0;
+ }
+
+ protos = 0;
+ for(i = 0; i < nitems; i++) {
+ if(protocols[i] == atom[WMDelete])
+ protos |= WM_PROTOCOL_DELWIN;
+ }
+
+ free(protocols);
+ return protos;
+}
+
+static void
+ns_display() {
+ char *p, *disp;
+
+ disp = getenv("DISPLAY");
+ if(disp == nil)
+ fatal("DISPLAY is unset");
+
+ disp = estrdup(disp);
+ p = &disp[strlen(disp) - 2];
+ if(strcmp(p, ".0") == 0)
+ *p = '\0';
+
+ ns_path = emalloc(strlen(disp) + strlen(user) + strlen("/tmp/ns..") + 1);
+ sprintf(ns_path, "/tmp/ns.%s.%s", user, disp);
+
+ free(disp);
+}
+
+static void
+rmkdir(char *path, int mode) {
+ char *p, *q;
+ int ret;
+ char c;
+
+ q = path + strlen(ns_path);
+ for(p = &path[1]; p <= q; p++) {
+ c = *p;
+ if((c == '/') || (c == '\0')) {
+ *p = '\0';
+ ret = mkdir(path, mode);
+ if((ret == -1) && (errno != EEXIST))
+ fatal("Can't create ns_path '%s':", path);
+ *p = c;
+ }
+ }
+}
+
+static void
+init_ns() {
+ struct stat st;
+ char *p;
+
+ if(address && strncmp(address, "unix!", 5) == 0) {
+ ns_path = estrdup(&address[5]);
+ p = strrchr(ns_path, '/');
+ if(p != nil)
+ p = '\0';
+ }
+ else if((p = getenv("WMII_NS_PATH")) || (p = getenv("NAMESPACE")))
+ ns_path = p;
+ else
+ ns_display();
+
+ if((ns_path[0] != '/') || (strlen(ns_path) == 0))
+ fatal("Bad ns_path");
+
+ rmkdir(ns_path, 0700);
+
+ if(stat(ns_path, &st))
+ fatal("Can't stat ns_path '%s':", ns_path);
+ if(getuid() != st.st_uid)
+ fatal("ns_path '%s' exists but is not owned by you",
+ ns_path);
+ if(st.st_mode & 077)
+ fatal("ns_path '%s' exists, but has group or world permissions",
+ ns_path);
+}
+
+static void
+init_environment() {
+ if(address == nil)
+ address = getenv("WMII_ADDRESS");
+
+ init_ns();
+
+ if(address == nil) {
+ address = emalloc(strlen(ns_path) + strlen("unix!/wmii") + 1);
+ sprintf(address, "unix!%s/wmii", ns_path);
+ }
+
+ setenv("WMII_NS_DIR", ns_path, True);
+ setenv("WMII_ADDRESS", address, True);
+}
+
+static void
+intern_atom(int ident, char *name) {
+ atom[ident] = XInternAtom(blz.dpy, name, False);
+}
+
+static void
+init_atoms() {
+ intern_atom(WMState, "WM_STATE");
+ intern_atom(WMProtocols, "WM_PROTOCOLS");
+ intern_atom(WMDelete, "WM_DELETE_WINDOW");
+ intern_atom(NetSupported, "_NET_SUPPORTED");
+ intern_atom(NetWMName, "_NET_WM_NAME");
+ intern_atom(TagsAtom, "_WIN_TAGS");
+
+ XChangeProperty(blz.dpy, blz.root, atom[NetSupported], XA_ATOM, 32,
+ PropModeReplace, (uchar *)&atom[NetSupported], 2);
+}
+
+static void
+create_cursor(int ident, uint shape) {
+ cursor[ident] = XCreateFontCursor(blz.dpy, shape);
+}
+
+static void
+init_cursors() {
+ Pixmap pix;
+ XColor black, dummy;
+
+ create_cursor(CurNormal, XC_left_ptr);
+ create_cursor(CurNECorner, XC_top_right_corner);
+ create_cursor(CurNWCorner, XC_top_left_corner);
+ create_cursor(CurSECorner, XC_bottom_right_corner);
+ create_cursor(CurSWCorner, XC_bottom_left_corner);
+ create_cursor(CurMove, XC_fleur);
+ create_cursor(CurInput, XC_xterm);
+
+ XAllocNamedColor(blz.dpy, DefaultColormap(blz.dpy, blz.screen),
+ "black", &black,
+ &dummy);
+ pix = XCreateBitmapFromData(blz.dpy, blz.root,
+ (char[]){0}, 1, 1);
+
+ cursor[CurInvisible] = XCreatePixmapCursor(blz.dpy,
+ pix, pix,
+ &black, &black,
+ 0, 0);
+
+ XFreePixmap(blz.dpy, pix);
+}
+
+static void
+init_screen(WMScreen *screen) {
+ Window w;
+ int ret;
+ unsigned mask;
+ XGCValues gcv;
+
+ gcv.subwindow_mode = IncludeInferiors;
+ gcv.function = GXxor;
+ gcv.foreground = def.normcolor.bg;
+ gcv.plane_mask = AllPlanes;
+ gcv.graphics_exposures = False;
+ xorgc = XCreateGC(blz.dpy, blz.root,
+ GCForeground
+ | GCGraphicsExposures
+ | GCFunction
+ | GCSubwindowMode
+ | GCPlaneMask,
+ &gcv);
+
+ screen->rect.x = screen->rect.y = 0;
+ screen->rect.width = DisplayWidth(blz.dpy, blz.screen);
+ screen->rect.height = DisplayHeight(blz.dpy, blz.screen);
+ def.snap = screen->rect.height / 63;
+
+ sel_screen = XQueryPointer(blz.dpy, blz.root,
+ &w, &w,
+ &ret, &ret, &ret, &ret,
+ &mask);
+}
+
+/*
+ * There's no way to check accesses to destroyed windows, thus
+ * those cases are ignored (especially on UnmapNotify's).
+ * Other types of errors call Xlib's default error handler, which
+ * calls exit().
+ */
+int
+wmii_error_handler(Display *dpy, XErrorEvent *error) {
+ if(check_other_wm)
+ fatal("another window manager is already running");
+
+ if(error->error_code == BadWindow
+ ||(error->request_code == X_SetInputFocus
+ && error->error_code == BadMatch)
+ ||(error->request_code == X_PolyText8
+ && error->error_code == BadDrawable)
+ ||(error->request_code == X_PolyFillRectangle
+ && error->error_code == BadDrawable)
+ ||(error->request_code == X_PolySegment
+ && error->error_code == BadDrawable)
+ ||(error->request_code == X_ConfigureWindow
+ && error->error_code == BadMatch)
+ ||(error->request_code == X_GrabKey
+ && error->error_code == BadAccess))
+ return 0;
+
+ fprintf(stderr, "wmii: fatal error: Xrequest code=%d, Xerror code=%d\n",
+ error->request_code, error->error_code);
+ return x_error_handler(blz.dpy, error); /* calls exit() */
+}
+
+static void
+cleanup() {
+ Client *c;
+
+ for(c=client; c; c=c->next)
+ reparent_client(c, blz.root, c->sel->rect.x, c->sel->rect.y);
+ XSync(blz.dpy, False);
+}
+
+static void
+cleanup_handler(int signal) {
+ sa.sa_handler = SIG_DFL;
+ sigaction(signal, &sa, nil);
+
+ switch(signal) {
+ case SIGINT:
+ srv.running = False;
+ break;
+ default:
+ cleanup();
+ XCloseDisplay(blz.dpy);
+ raise(signal);
+ break;
+ }
+}
+
+static void
+init_traps() {
+ char buf[1];
+ int fd[2];
+
+ if(pipe(fd) != 0)
+ fatal("Can't pipe():");
+
+ switch(fork()) {
+ case -1:
+ fatal("Can't fork():");
+ break; /* not reached */
+ case 0:
+ close(fd[1]);
+ close(ConnectionNumber(blz.dpy));
+ setsid();
+
+ blz.dpy = XOpenDisplay(0);
+ if(!blz.dpy)
+ fatal("Can't open display");
+
+ /* Wait for parent to exit */
+ read(fd[0], buf, 1);
+
+ XSetInputFocus(blz.dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+ XCloseDisplay(blz.dpy);
+ exit(0);
+ default:
+ break;
+ }
+
+ close(fd[0]);
+ sleeperfd = fd[1];
+
+ sa.sa_flags = 0;
+ sa.sa_handler = cleanup_handler;
+ sigaction(SIGINT, &sa, nil);
+ sigaction(SIGTERM, &sa, nil);
+ sigaction(SIGQUIT, &sa, nil);
+ sigaction(SIGHUP, &sa, nil);
+}
+
+static void
+spawn_command(const char *cmd) {
+ char *shell, *p;
+ pid_t pid;
+ int status;
+
+ /* Double fork hack */
+ switch(pid = fork()) {
+ case -1:
+ fatal("Can't fork:");
+ break; /* Not reached */
+ case 0:
+ switch(fork()) {
+ case -1:
+ fatal("Can't fork:");
+ break; /* Not reached */
+ case 0:
+ if(setsid() == -1)
+ fatal("Can't setsid:");
+ close(sock);
+ close(ConnectionNumber(blz.dpy));
+
+ shell = passwd->pw_shell;
+ if(shell[0] != '/')
+ fatal("Shell is not an absolute path: %s", shell);
+
+ /* Run through the user's shell as a login shell */
+ p = malloc((strlen(shell) + 2));
+ sprintf(p, "-%s", strrchr(shell, '/') + 1);
+
+ execl(shell, p, "-c", cmd, nil);
+ fatal("Can't exec '%s':", cmd);
+ break; /* Not reached */
+ default:
+ exit(0);
+ break; /* Not reached */
+ }
+ default:
+ waitpid(pid, &status, 0);
+ if(status != 0)
+ exit(1); /* Error already printed */
+ break;
+ }
+}
+
+void
+check_9pcon(IxpConn *c) {
+ serve_9pcon(c);
+ check_x_event(nil);
+}
+
+int
+main(int argc, char *argv[]) {
+ char *wmiirc, *errstr;
+ WMScreen *s;
+ XSetWindowAttributes wa;
+ int i;
+
+ passwd = getpwuid(getuid());
+ user = estrdup(passwd->pw_name);
+ wmiirc = "wmiistartrc";
+
+ /* command line args */
+ ARGBEGIN{
+ case 'v':
+ printf("%s", version);
+ exit(0);
+ case 'V':
+ verbose = True;
+ break;
+ case 'a':
+ address = EARGF(usage());
+ break;
+ case 'r':
+ wmiirc = EARGF(usage());
+ break;
+ default:
+ usage();
+ break;
+ }ARGEND;
+
+ setlocale(LC_CTYPE, "");
+ starting = True;
+
+ blz.dpy = XOpenDisplay(0);
+ if(!blz.dpy)
+ fatal("Can't open display");
+ blz.screen = DefaultScreen(blz.dpy);
+ blz.root = RootWindow(blz.dpy, blz.screen);
+
+ check_other_wm = True;
+ x_error_handler = XSetErrorHandler(wmii_error_handler);
+ XSelectInput(blz.dpy, blz.root, SubstructureRedirectMask | EnterWindowMask);
+ XSync(blz.dpy, False);
+ check_other_wm = False;
+
+ init_environment();
+ init_traps();
+
+ errstr = nil;
+ sock = ixp_dial(address);
+ if(sock < 0)
+ fatal("Can't create socket '%s': %s", address, errstr);
+
+ if(wmiirc)
+ spawn_command(wmiirc);
+
+ ixp_listen(&srv, sock, &p9srv, check_9pcon, nil);
+ ixp_listen(&srv, ConnectionNumber(blz.dpy), nil, check_x_event, nil);
+
+ view = nil;
+ client = nil;
+ key = nil;
+
+ def.font.fontstr = estrdup(BLITZ_FONT);
+ def.border = 1;
+ def.colmode = Coldefault;
+
+ def.mod = Mod1Mask;
+ strncpy(def.grabmod, "Mod1", sizeof(def.grabmod));
+
+ strncpy(def.focuscolor.colstr, BLITZ_FOCUSCOLORS, sizeof(def.focuscolor.colstr));
+ strncpy(def.normcolor.colstr, BLITZ_NORMCOLORS, sizeof(def.normcolor.colstr));
+ loadcolor(&blz, &def.focuscolor);
+ loadcolor(&blz, &def.normcolor);
+
+ init_atoms();
+ init_cursors();
+ loadfont(&blz, &def.font);
+ init_lock_keys();
+
+ num_screens = 1;
+ screens = emallocz(num_screens * sizeof(*screens));
+ for(i = 0; i < num_screens; i++) {
+ s = &screens[i];
+ init_screen(s);
+ pmap = XCreatePixmap(
+ /* display */ blz.dpy,
+ /* drawable */ blz.root,
+ /* width */ s->rect.width,
+ /* height */ s->rect.height,
+ /* depth */ DefaultDepth(blz.dpy, blz.screen)
+ );
+ wa.event_mask =
+ SubstructureRedirectMask
+ | EnterWindowMask
+ | LeaveWindowMask
+ | FocusChangeMask;
+ wa.cursor = cursor[CurNormal];
+ XChangeWindowAttributes(blz.dpy, blz.root, CWEventMask | CWCursor, &wa);
+ wa.override_redirect = 1;
+ wa.background_pixmap = ParentRelative;
+ wa.event_mask =
+ ExposureMask
+ | ButtonReleaseMask
+ | FocusChangeMask
+ | SubstructureRedirectMask
+ | SubstructureNotifyMask;
+ s->brect = s->rect;
+ s->brect.height = labelh(&def.font);
+ s->brect.y = s->rect.height - s->brect.height;
+ s->barwin = XCreateWindow(
+ /* display */ blz.dpy,
+ /* parent */ RootWindow(blz.dpy, blz.screen),
+ /* x */ s->brect.x,
+ /* y */ s->brect.y,
+ /* width */ s->brect.width,
+ /* height */ s->brect.height,
+ /*border_width*/0,
+ /* depth */ DefaultDepth(blz.dpy, blz.screen),
+ /* class */ CopyFromParent,
+ /* visual */ DefaultVisual(blz.dpy, blz.screen),
+ /* valuemask */ CWOverrideRedirect | CWBackPixmap | CWEventMask,
+ /* attrubutes */&wa
+ );
+ XSync(blz.dpy, False);
+ s->bbrush.blitz = &blz;
+ s->bbrush.gc = XCreateGC(blz.dpy, s->barwin, 0, 0);
+ s->bbrush.drawable = pmap;
+ s->bbrush.rect = s->brect;
+ s->bbrush.rect.x = 0;
+ s->bbrush.rect.y = 0;
+ s->bbrush.color = def.normcolor;
+ s->bbrush.font = &def.font;
+ s->bbrush.border = 1;
+ draw_bar(s);
+ XMapRaised(blz.dpy, s->barwin);
+ }
+
+ screen = &screens[0];
+ screen->focus = nil;
+ XSetInputFocus(blz.dpy, screen->barwin, RevertToParent, CurrentTime);
+
+ scan_wins();
+ starting = False;
+ update_views();
+ if(view)
+ write_event("FocusTag %s\n", screen->sel->name);
+
+ check_x_event(nil);
+ errstr = ixp_serverloop(&srv);
+ if(errstr)
+
+ cleanup();
+ XCloseDisplay(blz.dpy);
+ ixp_server_close(&srv);
+ close(sleeperfd);
+
+ if(execstr)
+ execl("/bin/sh", "sh", "-c", execstr, nil);
+
+ if(errstr)
+ fatal("%s", errstr);
+ return 0;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/mouse.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/mouse.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,490 @@
+/* Copyright ©2006 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "wmii.h"
+
+enum {
+ ButtonMask =
+ ButtonPressMask | ButtonReleaseMask,
+ MouseMask =
+ ButtonMask | PointerMotionMask
+};
+
+static void
+rect_morph_xy(XRectangle *rect, int dx, int dy, BlitzAlign *mask) {
+ BlitzAlign new_mask = 0;
+ if(*mask & NORTH) {
+ if(rect->height - dy >= 0 || *mask & SOUTH) {
+ rect->y += dy;
+ rect->height -= dy;
+ }
+ else {
+ rect->y += rect->height;
+ rect->height = dy - rect->height;
+ new_mask ^= NORTH|SOUTH;
+ }
+ }
+ if(*mask & SOUTH) {
+ if(rect->height + dy >= 0 || *mask & NORTH)
+ rect->height += dy;
+ else {
+ rect->height = -dy - rect->height;
+ rect->y -= rect->height;
+ new_mask ^= NORTH|SOUTH;
+ }
+ }
+ if(*mask & EAST) {
+ if(rect->width + dx >= 0 || *mask & WEST)
+ rect->width += dx;
+ else {
+ rect->width = -dx - rect->width;
+ rect->x -= rect->width;
+ new_mask ^= EAST|WEST;
+ }
+ }
+ if(*mask & WEST) {
+ if(rect->width - dx >= 0 || *mask & EAST) {
+ rect->x += dx;
+ rect->width -= dx;
+ }
+ else {
+ rect->x += rect->width;
+ rect->width = dx - rect->width;
+ new_mask ^= EAST|WEST;
+ }
+ }
+ *mask ^= new_mask;
+}
+
+typedef struct {
+ XRectangle *rects;
+ int num;
+ int x1, y1, x2, y2;
+ BlitzAlign mask;
+ int *delta;
+} SnapArgs;
+
+static void
+snap_line(SnapArgs *a) {
+ int i, t_xy;
+
+ /* horizontal */
+ if(a->y1 == a->y2 && (a->mask & (NORTH|SOUTH))) {
+ for(i=0; i < a->num; i++) {
+ if(!(r_east(&a->rects[i]) < a->x1) ||
+ (a->rects[i].x > a->x2)) {
+
+ if(abs(a->rects[i].y - a->y1) <= abs(*a->delta))
+ *a->delta = a->rects[i].y - a->y1;
+
+ t_xy = r_south(&a->rects[i]);
+ if(abs(t_xy - a->y1) < abs(*a->delta))
+ *a->delta = t_xy - a->y1;
+ }
+ }
+ }
+ else if (a->mask & (EAST|WEST)) {
+ /* This is the same as above, tr/xy/yx/,
+ * s/width/height/, s/height/width/ */
+ for(i=0; i < a->num; i++) {
+ if(!(r_south(&a->rects[i]) < a->y1) ||
+ (a->rects[i].y > a->y2)) {
+
+ if(abs(a->rects[i].x - a->x1) <= abs(*a->delta))
+ *a->delta = a->rects[i].x - a->x1;
+
+ t_xy = r_east(&a->rects[i]);
+ if(abs(t_xy - a->x1) < abs(*a->delta))
+ *a->delta = t_xy - a->x1;
+ }
+ }
+ }
+}
+
+BlitzAlign
+snap_rect(XRectangle *rects, int num, XRectangle *current, BlitzAlign *mask, int snap) {
+ SnapArgs a = { rects, num, 0, 0, 0, 0, *mask, nil };
+ int dx, dy;
+ BlitzAlign ret;
+
+ dx = dy = snap + 1;
+
+ a.x1 = current->x;
+ a.x2 = r_east(current);
+ a.delta = &dy;
+ if(*mask & NORTH) {
+ a.y2 = a.y1 = current->y;
+ snap_line(&a);
+ }
+ if(*mask & SOUTH) {
+ a.y2 = a.y1 = r_south(current);
+ snap_line(&a);
+ }
+
+ a.y1 = current->y;
+ a.y2 = r_south(current);
+ a.delta = &dx;
+ if(*mask & EAST) {
+ a.x1 = a.x2 = r_east(current);
+ snap_line(&a);
+ }
+ if(*mask & WEST) {
+ a.x1 = a.x2 = current->x;
+ snap_line(&a);
+ }
+
+ rect_morph_xy(current,
+ abs(dx) <= snap ? dx : 0,
+ abs(dy) <= snap ? dy : 0,
+ mask);
+
+ ret = *mask;
+ if(abs(dx) <= snap)
+ ret ^= EAST|WEST;
+ if(abs(dy) <= snap)
+ ret ^= NORTH|SOUTH;
+ return ret ^ CENTER;
+}
+
+static void
+draw_xor_border(XRectangle *r) {
+ XRectangle xor;
+
+ xor = *r;
+ xor.x += 2;
+ xor.y += 2;
+ xor.width = xor.width > 4 ? xor.width - 4 : 0;
+ xor.height = xor.height > 4 ? xor.height - 4 : 0;
+
+ XSetLineAttributes(blz.dpy, xorgc, 1, LineSolid, CapNotLast, JoinMiter);
+ XSetForeground(blz.dpy, xorgc, def.focuscolor.bg);
+ if(xor.height > 4 && xor.width > 2)
+ XDrawLine(blz.dpy, blz.root, xorgc,
+ xor.x + 2,
+ xor.y + xor.height / 2,
+ r_east(&xor) - 2,
+ xor.y + xor.height / 2);
+ if(xor.width > 4 && xor.height > 2)
+ XDrawLine(blz.dpy, blz.root, xorgc,
+ xor.x + xor.width / 2,
+ xor.y + 2,
+ xor.x + xor.width / 2,
+ r_south(&xor) - 2);
+ XSetLineAttributes(blz.dpy, xorgc, 4, LineSolid, CapNotLast, JoinMiter);
+ XDrawRectangles(blz.dpy, blz.root, xorgc, &xor, 1);
+}
+
+static void
+find_droppoint(Frame *frame, int x, int y, XRectangle *rect, Bool do_move) {
+ View *v;
+ Area *a, *a_prev;
+ Frame *f, *f_close;
+
+ v = frame->view;
+ rect->y = 0;
+ rect->height = screen->rect.height - screen->brect.height;
+
+ a_prev = v->area;
+ for(a = a_prev->next; a && a->next; a = a->next) {
+ if(x < r_east(&a->rect))
+ break;
+ a_prev = a;
+ }
+ if(x < (a->rect.x + labelh(&def.font))) {
+ rect->x = a->rect.x - 4;
+ rect->width = 8;
+
+ if(do_move) {
+ a = new_column(v, a_prev, 0);
+ send_to_area(a, frame);
+ focus(frame->client, False);
+ }
+ return;
+ }
+ if(x > (r_east(&a->rect) - labelh(&def.font))) {
+ rect->x = r_east(&a->rect) - 4;
+ rect->width = 8;
+
+ if(do_move) {
+ a = new_column(v, a, 0);
+ send_to_area(a, frame);
+ focus(frame->client, False);
+ }
+ return;
+ }
+
+ rect->x = a->rect.x;
+ rect->width = a->rect.width;
+
+ f_close = nil;
+ for(f = a->frame; f; f = f->anext) {
+ if(y < f->rect.y)
+ break;
+ if(y < r_south(&f->rect))
+ break;
+ f_close = f;
+ }
+ if(f == nil)
+ f = f_close;
+ if(y < (f->rect.y + labelh(&def.font))) {
+ rect->y = f->rect.y;
+ rect->height = 2;
+ if(f_close) {
+ rect->y = r_south(&f_close->rect);
+ rect->height = f->rect.y - rect->y;
+ }
+ if(do_move)
+ goto do_move;
+ return;
+ }
+ if(y > r_south(&f->rect) - labelh(&def.font)) {
+ rect->y = r_south(&f->rect);
+ rect->height = (screen->rect.height - labelh(&def.font) - rect->y);
+ if(f->anext)
+ rect->height = (f->anext->rect.y - rect->y);
+ if(do_move)
+ goto do_move;
+ return;
+ }
+
+ *rect = f->rect;
+ if(do_move) {
+ swap_frames(frame, f);
+ focus(frame->client, False);
+ }
+ return;
+
+do_move:
+ if(frame == f)
+ return;
+ if(a != frame->area)
+ send_to_area(a, frame);
+ remove_frame(frame);
+ insert_frame(f, frame, False);
+ arrange_column(f->area, False);
+ focus(frame->client, True);
+}
+
+static void
+do_managed_move(Client *c) {
+ XRectangle frect, ofrect;
+ Window dummy;
+ XEvent ev;
+ Frame *f;
+ uint di;
+ int x, y, i;
+
+ focus(c, False);
+ f = c->sel;
+
+ XSync(blz.dpy, False);
+ if(XGrabPointer(blz.dpy, c->framewin, False, MouseMask, GrabModeAsync, GrabModeAsync,
+ None, cursor[CurMove], CurrentTime) != GrabSuccess)
+ return;
+ XGrabServer(blz.dpy);
+
+ XQueryPointer(blz.dpy, blz.root, &dummy, &dummy, &i, &i, &x, &y, &di);
+
+ find_droppoint(f, x, y, &frect, False);
+ draw_xor_border(&frect);
+ for(;;) {
+ XMaskEvent(blz.dpy, MouseMask | ExposureMask, &ev);
+ switch (ev.type) {
+ case ButtonRelease:
+ draw_xor_border(&frect);
+
+ find_droppoint(f, x, y, &frect, True);
+
+ XUngrabServer(blz.dpy);
+ XUngrabPointer(blz.dpy, CurrentTime);
+ XSync(blz.dpy, False);
+ return;
+ case MotionNotify:
+ ofrect = frect;
+ x = ev.xmotion.x_root;
+ y = ev.xmotion.y_root;
+
+ find_droppoint(f, x, y, &frect, False);
+
+ if(memcmp(&frect, &ofrect, sizeof(frect))) {
+ draw_xor_border(&ofrect);
+ draw_xor_border(&frect);
+ }
+ break;
+ case Expose:
+ (handler[Expose])(&ev);
+ break;
+ default: break;
+ }
+ }
+}
+
+void
+do_mouse_resize(Client *c, Bool grabbox, BlitzAlign align) {
+ BlitzAlign grav;
+ Window dummy;
+ Cursor cur;
+ XEvent ev;
+ XRectangle *rects, ofrect, frect, origin;
+ int snap, dx, dy, pt_x, pt_y, hr_x, hr_y, i;
+ uint num, di;
+ Bool floating;
+ float rx, ry;
+ Frame *f;
+
+ f = c->sel;
+ floating = f->area->floating;
+ origin = frect = f->rect;
+ cur = cursor_of_quad(align);
+ if(floating) {
+ rects = rects_of_view(f->area->view, &num, (grabbox ? c->frame : nil));
+ snap = screen->rect.height / 66;
+ }else{
+ rects = nil;
+ snap = 0;
+ }
+
+ if(align == CENTER) {
+ if(!grabbox)
+ cur = cursor[CurInvisible];
+ if(!floating) {
+ do_managed_move(c);
+ return;
+ }
+ }
+
+ XQueryPointer(blz.dpy, c->framewin, &dummy, &dummy, &i, &i, &pt_x, &pt_y, &di);
+ rx = (float)pt_x / frect.width;
+ ry = (float)pt_y / frect.height;
+
+ if(XGrabPointer(
+ /* display */ blz.dpy,
+ /* window */ c->framewin,
+ /* owner_events */ False,
+ /* event_mask */ MouseMask,
+ /* pointer_mode */ GrabModeAsync,
+ /* keyboard_mode */ GrabModeAsync,
+ /* confine_to */ None,
+ /* cursor */ cur,
+ /* time */ CurrentTime
+ ) != GrabSuccess)
+ return;
+
+ XQueryPointer(blz.dpy, blz.root, &dummy, &dummy, &i, &i, &pt_x, &pt_y, &di);
+
+ if(align != CENTER) {
+ hr_x = dx = frect.width / 2;
+ hr_y = dy = frect.height / 2;
+ if(align&NORTH) dy -= hr_y;
+ if(align&SOUTH) dy += hr_y;
+ if(align&EAST) dx += hr_x;
+ if(align&WEST) dx -= hr_x;
+ XTranslateCoordinates(blz.dpy, c->framewin, blz.root, dx, dy,
+ &pt_x, &pt_y, &dummy);
+ XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, pt_x, pt_y);
+ }
+ else if(!grabbox) {
+ hr_x = screen->rect.width / 2;
+ hr_y = screen->rect.height / 2;
+ XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, hr_x, hr_y);
+ flushevents(PointerMotionMask, False);
+ }
+
+
+ XSync(blz.dpy, False);
+ if(!grabbox) {
+ XGrabServer(blz.dpy);
+ draw_xor_border(&frect);
+ }else
+ unmap_client(c, IconicState);
+
+ for(;;) {
+ XMaskEvent(blz.dpy, MouseMask | ExposureMask, &ev);
+ switch (ev.type) {
+ case ButtonRelease:
+ if(!grabbox)
+ draw_xor_border(&frect);
+
+ if(!floating)
+ resize_column(c, &frect);
+ else
+ resize_client(c, &frect);
+
+ if(!grabbox) {
+ if(align != CENTER)
+ XTranslateCoordinates(blz.dpy, c->framewin, blz.root,
+ (frect.width * rx), (frect.height * ry),
+ &pt_x, &pt_y, &dummy);
+ if(pt_y > screen->brect.y)
+ pt_y = screen->brect.y - 1;
+ XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, pt_x, pt_y);
+ XUngrabServer(blz.dpy);
+ }else
+ map_client(c);
+
+ if(rects)
+ free(rects);
+
+ XUngrabPointer(blz.dpy, CurrentTime);
+ XSync(blz.dpy, False);
+ return;
+ case MotionNotify:
+ ofrect = frect;
+ dx = ev.xmotion.x_root;
+ dy = ev.xmotion.y_root;
+
+ if(align == CENTER && !grabbox) {
+ if(dx == hr_x && dy == hr_y)
+ continue;
+ XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, hr_x, hr_y);
+ dx -= hr_x;
+ dy -= hr_y;
+ }else{
+ dx -= pt_x;
+ dy -= pt_y;
+ }
+ pt_x += dx;
+ pt_y += dy;
+
+ rect_morph_xy(&origin, dx, dy, &align);
+ if(align != CENTER)
+ check_frame_constraints(&origin);
+ frect = origin;
+
+ if(floating)
+ grav = snap_rect(rects, num, &frect, &align, snap);
+ else
+ grav = align ^ CENTER;
+
+ apply_sizehints(c, &frect, floating, True, grav);
+
+ if(grabbox) {
+ XMoveWindow(blz.dpy, c->framewin, frect.x, frect.y);
+ XSync(blz.dpy, False);
+ } else {
+ draw_xor_border(&ofrect);
+ draw_xor_border(&frect);
+ }
+ break;
+ case Expose:
+ (handler[Expose])(&ev);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void
+grab_button(Window w, uint button, ulong mod) {
+ XGrabButton(blz.dpy, button, mod, w, False, ButtonMask,
+ GrabModeSync, GrabModeSync, None, None);
+ if((mod != AnyModifier) && num_lock_mask) {
+ XGrabButton(blz.dpy, button, mod | num_lock_mask, w, False, ButtonMask,
+ GrabModeSync, GrabModeAsync, None, None);
+ XGrabButton(blz.dpy, button, mod | num_lock_mask | LockMask, w, False,
+ ButtonMask, GrabModeSync, GrabModeAsync, None, None);
+ }
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/printevent.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/printevent.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,997 @@
+/*
+ * Original code posted to comp.sources.x
+ * Modifications by Russ Cox <rsc_AT_swtch.com>.
+ */
+
+/*
+Path: uunet!wyse!mikew
+From: mikew_AT_wyse.wyse.com (Mike Wexler)
+Newsgroups: comp.sources.x
+Subject: v02i056: subroutine to print events in human readable form, Part01/01
+Message-ID: <1935_AT_wyse.wyse.com>
+Date: 22 Dec 88 19:28:25 GMT
+Organization: Wyse Technology, San Jose
+Lines: 1093
+Approved: mikew_AT_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_AT_richsun.UUCP
+*/
+
+#include <stdio.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xproto.h>
+#include "wmii.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)
+{
+ ulong msec;
+ ulong sec;
+ ulong min;
+ ulong hr;
+ ulong 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
+{
+ uint value;
+ char *string;
+};
+
+/* Returns the string equivalent of a mask of buttons and/or modifier keys */
+static char*
+ButtonAndOrModifierState(uint 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(uint 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)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
+ fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
+ fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
+ fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
+ fprintf(stderr, "is_hint=%s%s", IsHint(ev->is_hint), sep);
+ fprintf(stderr, "same_screen=%s\n", TorF(ev->same_screen));
+}
+
+static void
+VerbButton(XButtonEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
+ fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
+ fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
+ fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
+ fprintf(stderr, "button=%s%s", ButtonAndOrModifierState(ev->button), sep);
+ fprintf(stderr, "same_screen=%s\n", TorF(ev->same_screen));
+}
+
+static void
+VerbColormap(XColormapEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "colormap=%s%s", MaybeNone(ev->colormap), sep);
+ fprintf(stderr, "new=%s%s", TorF(ev->new), sep);
+ fprintf(stderr, "state=%s\n", ColormapState(ev->state));
+}
+
+static void
+VerbCrossing(XCrossingEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
+ fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
+ fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
+ fprintf(stderr, "mode=%s%s", GrabMode(ev->mode), sep);
+ fprintf(stderr, "detail=%s%s", CrossingDetail(ev->detail), sep);
+ fprintf(stderr, "same_screen=%s%s", TorF(ev->same_screen), sep);
+ fprintf(stderr, "focus=%s%s", TorF(ev->focus), sep);
+ fprintf(stderr, "state=%s\n", ButtonAndOrModifierState(ev->state));
+}
+
+static void
+VerbExpose(XExposeEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
+ fprintf(stderr, "count=%d\n", ev->count);
+}
+
+static void
+VerbGraphicsExpose(XGraphicsExposeEvent *ev)
+{
+ fprintf(stderr, "drawable=0x%x%s", (int)ev->drawable, sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
+ fprintf(stderr, "major_code=%s%s", MajorCode(ev->major_code), sep);
+ fprintf(stderr, "minor_code=%d\n", ev->minor_code);
+}
+
+static void
+VerbNoExpose(XNoExposeEvent *ev)
+{
+ fprintf(stderr, "drawable=0x%x%s", (int)ev->drawable, sep);
+ fprintf(stderr, "major_code=%s%s", MajorCode(ev->major_code), sep);
+ fprintf(stderr, "minor_code=%d\n", ev->minor_code);
+}
+
+static void
+VerbFocus(XFocusChangeEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "mode=%s%s", GrabMode(ev->mode), sep);
+ fprintf(stderr, "detail=%s\n", FocusChangeDetail(ev->detail));
+}
+
+static void
+VerbKeymap(XKeymapEvent *ev)
+{
+ int i;
+
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "key_vector=");
+ for (i = 0; i < 32; i++)
+ fprintf(stderr, "%02x", ev->key_vector[i]);
+ fprintf(stderr, "\n");
+}
+
+static void
+VerbKey(XKeyEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
+ if(ev->subwindow)
+ fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
+ fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
+ fprintf(stderr, "[%d,%d]%s", ev->x, ev->y, sep);
+ fprintf(stderr, "root=[%d,%d]%s", ev->x_root, ev->y_root, sep);
+ if(ev->state)
+ fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
+ fprintf(stderr, "keycode=%s%s", Keycode(ev), sep);
+ if(!ev->same_screen)
+ fprintf(stderr, "!same_screen");
+ fprintf(stderr, "\n");
+ return;
+
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
+ fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
+ fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
+ fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
+ fprintf(stderr, "keycode=%s%s", Keycode(ev), sep);
+ fprintf(stderr, "same_screen=%s\n", TorF(ev->same_screen));
+}
+
+static void
+VerbProperty(XPropertyEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "atom=%s%s", AtomName(ev->display, ev->atom), sep);
+ fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
+ fprintf(stderr, "state=%s\n", PropertyState(ev->state));
+}
+
+static void
+VerbResizeRequest(XResizeRequestEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "width=%d height=%d\n", ev->width, ev->height);
+}
+
+static void
+VerbCirculate(XCirculateEvent *ev)
+{
+ fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "place=%s\n", Place(ev->place));
+}
+
+static void
+VerbConfigure(XConfigureEvent *ev)
+{
+ fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
+ fprintf(stderr, "border_width=%d%s", ev->border_width, sep);
+ fprintf(stderr, "above=%s%s", MaybeNone(ev->above), sep);
+ fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
+}
+
+static void
+VerbCreateWindow(XCreateWindowEvent *ev)
+{
+ fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
+ fprintf(stderr, "border_width=%d%s", ev->border_width, sep);
+ fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
+}
+
+static void
+VerbDestroyWindow(XDestroyWindowEvent *ev)
+{
+ fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
+ fprintf(stderr, "window=0x%x\n", (int)ev->window);
+}
+
+static void
+VerbGravity(XGravityEvent *ev)
+{
+ fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "x=%d y=%d\n", ev->x, ev->y);
+}
+
+static void
+VerbMap(XMapEvent *ev)
+{
+ fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
+}
+
+static void
+VerbReparent(XReparentEvent *ev)
+{
+ fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
+}
+
+static void
+VerbUnmap(XUnmapEvent *ev)
+{
+ fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "from_configure=%s\n", TorF(ev->from_configure));
+}
+
+static void
+VerbCirculateRequest(XCirculateRequestEvent *ev)
+{
+ fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "place=%s\n", Place(ev->place));
+}
+
+static void
+VerbConfigureRequest(XConfigureRequestEvent *ev)
+{
+ fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
+ fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
+ fprintf(stderr, "border_width=%d%s", ev->border_width, sep);
+ fprintf(stderr, "above=%s%s", MaybeNone(ev->above), sep);
+ fprintf(stderr, "detail=%s%s", ConfigureDetail(ev->detail), sep);
+ fprintf(stderr, "value_mask=%s\n", ConfigureValueMask(ev->value_mask));
+}
+
+static void
+VerbMapRequest(XMapRequestEvent *ev)
+{
+ fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
+ fprintf(stderr, "window=0x%x\n", (int)ev->window);
+}
+
+static void
+VerbClient(XClientMessageEvent *ev)
+{
+ int i;
+
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "message_type=%s%s", AtomName(ev->display, ev->message_type), sep);
+ fprintf(stderr, "format=%d\n", ev->format);
+ fprintf(stderr, "data (shown as longs)=");
+ for (i = 0; i < 5; i++)
+ fprintf(stderr, " 0x%08lx", ev->data.l[i]);
+ fprintf(stderr, "\n");
+}
+
+static void
+VerbMapping(XMappingEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "request=%s%s", MappingRequest(ev->request), sep);
+ fprintf(stderr, "first_keycode=0x%x%s", ev->first_keycode, sep);
+ fprintf(stderr, "count=0x%x\n", ev->count);
+}
+
+static void
+VerbSelectionClear(XSelectionClearEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "selection=%s%s", AtomName(ev->display, ev->selection), sep);
+ fprintf(stderr, "time=%s\n", ServerTime(ev->time));
+}
+
+static void
+VerbSelection(XSelectionEvent *ev)
+{
+ fprintf(stderr, "requestor=0x%x%s", (int)ev->requestor, sep);
+ fprintf(stderr, "selection=%s%s", AtomName(ev->display, ev->selection), sep);
+ fprintf(stderr, "target=%s%s", AtomName(ev->display, ev->target), sep);
+ fprintf(stderr, "property=%s%s", AtomName(ev->display, ev->property), sep);
+ fprintf(stderr, "time=%s\n", ServerTime(ev->time));
+}
+
+static void
+VerbSelectionRequest(XSelectionRequestEvent *ev)
+{
+ fprintf(stderr, "owner=0x%x%s", (int)ev->owner, sep);
+ fprintf(stderr, "requestor=0x%x%s", (int)ev->requestor, sep);
+ fprintf(stderr, "selection=%s%s", AtomName(ev->display, ev->selection), sep);
+ fprintf(stderr, "target=%s%s", AtomName(ev->display, ev->target), sep);
+ fprintf(stderr, "property=%s%s", AtomName(ev->display, ev->property), sep);
+ fprintf(stderr, "time=%s\n", ServerTime(ev->time));
+}
+
+static void
+VerbVisibility(XVisibilityEvent *ev)
+{
+ fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
+ fprintf(stderr, "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;
+ char *name;
+
+ if(ev->window) {
+ XFetchName(blz.dpy, ev->window, &name);
+ if(name) {
+ fprintf(stderr, "\ttitle=%s\n", name);
+ XFree(name);
+ }
+ }
+ fprintf(stderr, "%3ld %-20s ", ev->serial, eventtype(e));
+ if(ev->send_event)
+ fprintf(stderr, "(sendevent) ");
+ if(0){
+ fprintf(stderr, "type=%s%s", eventtype(e), sep);
+ fprintf(stderr, "serial=%lu%s", ev->serial, sep);
+ fprintf(stderr, "send_event=%s%s", TorF(ev->send_event), sep);
+ fprintf(stderr, "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;
+ }
+}
+
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/printevent.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/printevent.h Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,2 @@
+char *eventtype(XEvent*);
+void printevent(XEvent*);
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/rule.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/rule.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright ©2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "wmii.h"
+
+/* basic rule matching language /regex/ -> value
+ * regex might contain POSIX regex syntax defined in regex(3) */
+enum {
+ IGNORE,
+ REGEX,
+ VALUE
+};
+
+void
+trim(char *str, const char *chars) {
+ const char *cp;
+ char *sp, *sn;
+
+ for(cp = chars; *cp; cp++) {
+ for(sp = sn = str; *sn; sn++) {
+ if(*sn != *cp)
+ *(sp++) = *sn;
+ }
+ *sp = 0;
+ }
+}
+
+void
+update_rules(Rule **rule, const char *data) {
+ int mode = IGNORE;
+ Rule *rul;
+ char *p, *r = nil, *v = nil, regex[256], value[256];
+
+ if(!data || !strlen(data))
+ return;
+ while((rul = *rule)) {
+ *rule = rul->next;
+ regfree(&rul->regex);
+ free(rul);
+ }
+ for(p = (char *)data; *p; p++)
+ switch(mode) {
+ case IGNORE:
+ if(*p == '/') {
+ mode = REGEX;
+ r = regex;
+ }
+ else if(*p == '>') {
+ mode = VALUE;
+ value[0] = 0;
+ v = value;
+ }
+ break;
+ case REGEX:
+ if(*p == '/') {
+ mode = IGNORE;
+ *r = 0;
+ }
+ else {
+ *r = *p;
+ r++;
+ }
+ break;
+ case VALUE:
+ if(*p == '\n' || *p == 0) {
+ *rule = emallocz(sizeof(Rule));
+ *v = 0;
+ trim(value, " \t/");
+ if(!regcomp(&(*rule)->regex, regex, 0)) {
+ strncpy((*rule)->value, value, sizeof(rul->value));
+ rule = &(*rule)->next;
+ }
+ else free(*rule);
+ mode = IGNORE;
+ }
+ else {
+ *v = *p;
+ v++;
+ }
+ break;
+ }
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/view.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/view.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,446 @@
+/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "wmii.h"
+
+static Bool
+is_empty(View *v) {
+ Area *a;
+ for(a=v->area; a; a=a->next)
+ if(a->frame)
+ return False;
+ return True;
+}
+
+Frame *
+clientframe_of_view(View *v, Client *c) {
+ Frame *f;
+ for(f=c->frame; f; f=f->cnext)
+ if(f->area->view == v)
+ break;
+ return f;
+}
+
+static void
+assign_sel_view(View *v) {
+ if(screen->sel != v) {
+ if(screen->sel)
+ write_event("UnfocusTag %s\n",screen->sel->name);
+ screen->sel = v;
+ write_event("FocusTag %s\n", screen->sel->name);
+ }
+}
+
+Client *
+sel_client_of_view(View *v) {
+ return v->sel && v->sel->sel ? v->sel->sel->client : nil;
+}
+
+View *
+get_view(const char *name) {
+ View *v;
+ int cmp;
+
+ for(v = view; v; v=v->next)
+ if((cmp=strcmp(name, v->name)) >= 0)
+ break;
+ if(!v || cmp != 0)
+ v = create_view(name);
+ return v;
+}
+
+View *
+create_view(const char *name) {
+ static ushort id = 1;
+ View **i, *v = emallocz(sizeof(View));
+
+ v->id = id++;
+ strncpy(v->name, name, sizeof(v->name));
+ create_area(v, nil, 0);
+ create_area(v, v->area, 0);
+ for(i=&view; *i; i=&(*i)->next)
+ if(strcmp((*i)->name, name) < 0) break;
+ v->next = *i;
+ *i = v;
+ write_event("CreateTag %s\n", v->name);
+ if(!screen->sel)
+ assign_sel_view(v);
+ return v;
+}
+
+void
+destroy_view(View *v) {
+ Area *a;
+ View **i, *tv;
+
+ while((a = v->area)) {
+ v->area = a->next;
+ destroy_area(a);
+ };
+ for(i=&view; *i; i=&(*i)->next)
+ if(*i == v) break;
+ *i = v->next;
+ write_event("DestroyTag %s\n", v->name);
+ if(v == screen->sel) {
+ for(tv=view; tv && tv->next; tv=tv->next)
+ if(tv->next == *i) break;
+ if(tv)
+ focus_view(screen, tv);
+ }
+ free(v);
+}
+
+static void
+update_frame_selectors(View *v) {
+ Area *a;
+ Frame *f;
+
+ for(a=v->area; a; a=a->next)
+ for(f=a->frame; f; f=f->anext)
+ f->client->sel = f;
+}
+
+void
+focus_view(WMScreen *s, View *v) {
+ View *old;
+ Frame *f;
+ Client *c;
+
+ old = screen->sel;
+ XGrabServer(blz.dpy);
+ assign_sel_view(v);
+ update_frame_selectors(v);
+ for(c=client; c; c=c->next)
+ if((f = c->sel)) {
+ if(f->view == v) {
+ resize_client(c, &f->rect);
+ update_client_grab(c);
+ } else {
+ unmap_frame(c);
+ unmap_client(c, IconicState);
+ }
+ }
+ restack_view(v);
+ focus_area(v->sel);
+ draw_frames();
+ XSync(blz.dpy, False);
+ XUngrabServer(blz.dpy);
+ flushevents(EnterWindowMask, False);
+}
+
+void
+select_view(const char *arg) {
+ char buf[256];
+
+ strncpy(buf, arg, sizeof(buf));
+ trim(buf, " \t+/");
+ if(!strlen(buf))
+ return;
+ if(!strncmp(buf, ".", 2) || !strncmp(buf, "..", 3))
+ return;
+ assign_sel_view(get_view(buf));
+ update_views(); /* performs focus_view */
+}
+
+void
+attach_to_view(View *v, Frame *f) {
+ Client *c = f->client;
+
+ c->revert = nil;
+ if(c->trans || c->floating || c->fixedsize || c->fullscreen)
+ v->sel = v->area;
+ else if(starting && v->sel->floating)
+ v->sel = v->area->next;
+ attach_to_area(v->sel, f, False);
+}
+
+void
+restack_view(View *v) {
+ Area *a;
+ Frame *f;
+ Client *c;
+ uint n, i;
+ static Window *wins = nil;
+ static uint winssz = 0;
+
+ if(v != screen->sel)
+ return;
+
+ i = 0;
+ n = 0;
+
+ for(c=client; c; c=c->next)
+ i++;
+ if(i == 0)
+ return;
+ if(i >= winssz) {
+ winssz = 2 * i;
+ wins = erealloc(wins, sizeof(Window) * winssz);
+ }
+
+ for(f=v->area->stack; f; f=f->snext)
+ if(f->client->fullscreen)
+ wins[n++] = f->client->framewin;
+ wins[n++] = screen->barwin;
+ for(f=v->area->stack; f; f=f->snext)
+ if(!f->client->fullscreen)
+ wins[n++] = f->client->framewin;
+ for(a=v->area->next; a; a=a->next) {
+ if(a->frame) {
+ wins[n++] = a->sel->client->framewin;
+ for(f=a->frame; f; f=f->anext)
+ if(f != a->sel)
+ wins[n++] = f->client->framewin;
+ }
+ }
+ if(n)
+ XRestackWindows(blz.dpy, wins, n);
+}
+
+void
+scale_view(View *v, float w) {
+ uint xoff, num_col;
+ uint min_width;
+ Area *a;
+ float scale, dx = 0;
+ int wdiff = 0;
+
+ min_width = screen->rect.width/NCOL;
+
+ if(!v->area->next)
+ return;
+
+ num_col = 0;
+ for(a=v->area->next; a; a=a->next)
+ num_col++, dx += a->rect.width;
+
+ scale = w / dx;
+ xoff = 0;
+ for(a=v->area->next; a; a=a->next) {
+ a->rect.width *= scale;
+ if(!a->next)
+ a->rect.width = w - xoff;
+ xoff += a->rect.width;
+ }
+ /* min_width can only be respected when there is enough space;
+ * the caller should guarantee this */
+ if(num_col * min_width > w)
+ return;
+ xoff = 0;
+ for(a=v->area->next, num_col--; a; a=a->next, num_col--) {
+ if(a->rect.width < min_width)
+ a->rect.width = min_width;
+ else if((wdiff = xoff + a->rect.width - w + num_col * min_width) > 0)
+ a->rect.width -= wdiff;
+ if(!a->next)
+ a->rect.width = w - xoff;
+ xoff += a->rect.width;
+ }
+}
+
+void
+arrange_view(View *v) {
+ uint xoff = 0;
+ Area *a;
+
+ if(!v->area->next)
+ return;
+ scale_view(v, screen->rect.width);
+ for(a=v->area->next; a; a=a->next) {
+ a->rect.x = xoff;
+ a->rect.y = 0;
+ a->rect.height = screen->rect.height - screen->brect.height;
+ xoff += a->rect.width;
+ arrange_column(a, False);
+ }
+}
+
+XRectangle *
+rects_of_view(View *v, uint *num, Frame *ignore) {
+ XRectangle *result;
+ Frame *f;
+ int i;
+
+ i = 2;
+ for(f=v->area->frame; f; f=f->anext)
+ i++;
+ result = emallocz(i * sizeof(XRectangle));
+ i = 0;
+ for(f=v->area->frame; f; f=f->anext)
+ if(f != ignore)
+ result[i++] = f->rect;
+ result[i++] = screen->rect;
+ result[i++] = screen->brect;
+ *num = i;
+ return result;
+}
+
+/* XXX: This will need cleanup */
+uchar *
+view_index(View *v) {
+ uint a_i, buf_i, n;
+ int len;
+ Frame *f;
+ Area *a;
+
+ len = BUFFER_SIZE;
+ buf_i = 0;
+ for((a = v->area), (a_i = 0); a && len > 0; (a=a->next), (a_i++)) {
+ if(a->floating)
+ n = snprintf(&buffer[buf_i], len, "# ~ %d %d\n",
+ a->rect.width, a->rect.height);
+ else
+ n = snprintf(&buffer[buf_i], len, "# %d %d %d\n",
+ a_i, a->rect.x, a->rect.width);
+ buf_i += n;
+ len -= n;
+ for(f=a->frame; f && len > 0; f=f->anext) {
+ XRectangle *r = &f->rect;
+ if(a->floating)
+ n = snprintf(&buffer[buf_i], len, "~ 0x%x %d %d %d %d %s\n",
+ (uint)f->client->win,
+ r->x, r->y, r->width, r->height,
+ f->client->props);
+ else
+ n = snprintf(&buffer[buf_i], len, "%d 0x%x %d %d %s\n",
+ a_i, (uint)f->client->win, r->y,
+ r->height, f->client->props);
+ if(len - n < 0)
+ return (uchar*)buffer;
+ buf_i += n;
+ len -= n;
+ }
+ }
+ return (uchar *)buffer;
+}
+
+Client *
+client_of_message(View *v, char *message, uint *next) {
+ ulong id = 0;
+ Client *c;
+
+ if(!strncmp(message, "sel ", 4)) {
+ *next = 4;
+ return sel_client_of_view(v);
+ }
+ sscanf(message, "0x%lx %n", &id, next);
+ if(!id)
+ sscanf(message, "%lu %n", &id, next);
+ if(!id)
+ return nil;
+ for(c=client; c && c->win!=id; c=c->next);
+ return c;
+}
+
+Area *
+area_of_message(View *v, char *message, uint *next) {
+ uint i;
+ Area *a;
+
+ if(!strncmp(message, "sel ", 4)) {
+ *next = 4;
+ return v->sel;
+ }
+ if(!strncmp(message, "~ ", 2)) {
+ *next = 2;
+ return v->area;
+ }
+ if(1 != sscanf(message, "%u %n", &i, next) || i == 0)
+ return nil;
+ for(a=v->area; i && a; a=a->next)
+ i--;
+ return a;
+}
+
+char *
+message_view(View *v, char *message) {
+ uint n, i;
+ Client *c;
+ Frame *f;
+ Area *a;
+ Bool swap;
+ static char Ebadvalue[] = "bad value";
+
+ if(!strncmp(message, "send ", 5)) {
+ message += 5;
+ swap = False;
+ goto send;
+ }
+ if(!strncmp(message, "swap ", 5)) {
+ message += 5;
+ swap = True;
+ goto send;
+ }
+ if(!strncmp(message, "select ", 7)) {
+ message += 7;
+ return select_area(v->sel, message);
+ }
+ if(!strncmp(message, "colmode ", 8)) {
+ message += 8;
+ if(!(a = area_of_message(v, message, &n)) || a == v->area)
+ return Ebadvalue;
+ if((i = column_mode_of_str(&message[n])) == -1)
+ return Ebadvalue;
+ a->mode = i;
+ arrange_column(a, True);
+ restack_view(v);
+ if(v == screen->sel)
+ focus_view(screen, v);
+ draw_frames();
+ return nil;
+ }
+ return Ebadvalue;
+
+send:
+ if(!(c = client_of_message(v, message, &n)))
+ return Ebadvalue;
+ if(!(f = clientframe_of_view(v, c)))
+ return Ebadvalue;
+ return send_client(f, &message[n], swap);
+}
+
+void
+update_views() {
+ View *n, *v;
+ View *old = screen->sel;
+
+ for(v=view; v; v=v->next)
+ update_frame_selectors(v);
+ if(old && !strncmp(old->name, "nil", 4))
+ old = nil;
+ for((v=view) && (n=v->next); v; (v=n) && (n=v->next))
+ if((v != old) && is_empty(v))
+ destroy_view(v);
+ if(old)
+ focus_view(screen, old);
+ else if(screen->sel)
+ focus_view(screen, screen->sel);
+}
+
+uint
+newcolw_of_view(View *v) {
+ Rule *r;
+ Area *a;
+ uint i, n;
+ regmatch_t tmpregm;
+
+ for(r=def.colrules.rule; r; r=r->next) {
+ if(!regexec(&r->regex, v->name, 1, &tmpregm, 0)) {
+ char buf[256];
+ char *toks[16];
+ strncpy(buf, r->value, sizeof(buf));
+ n = tokenize(toks, 16, buf, '+');
+ for(a=v->area, i=0; a; a=a->next)
+ i++;
+ if(n && n >= i) {
+ if(sscanf(toks[i - 1], "%u", &n) == 1)
+ return (screen->rect.width * n) / 100;
+ }
+ break;
+ }
+ }
+ return 0;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii/wmii.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii/wmii.h Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,439 @@
+/*
+ * © 2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdio.h>
+#include <regex.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <ixp.h>
+#include <util.h>
+
+#define nil ((void*)0)
+#define nelem(ary) (sizeof(ary) / sizeof(*ary))
+
+/* Types */
+#undef uchar
+#undef ushort
+#undef uint
+#undef ulong
+#undef uvlong
+#undef vlong
+#define uchar _wmiiuchar
+#define ushort _wmiiushort
+#define uint _wmiiuint
+#define ulong _wmiiulong
+#define vlong _wmiivlong
+#define uvlong _wmiiuvlong
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+typedef unsigned long long uvlong;
+typedef long long vlong;
+
+#define BLITZ_FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
+#define BLITZ_FOCUSCOLORS "#ffffff #335577 #447799"
+#define BLITZ_NORMCOLORS "#222222 #eeeeee #666666"
+
+typedef struct Blitz Blitz;
+typedef struct BlitzColor BlitzColor;
+typedef struct BlitzFont BlitzFont;
+typedef struct BlitzBrush BlitzBrush;
+
+struct Blitz {
+ Display *dpy;
+ int screen;
+ Window root;
+};
+
+enum BlitzAlign {
+ NORTH = 0x01,
+ EAST = 0x02,
+ SOUTH = 0x04,
+ WEST = 0x08,
+ NEAST = NORTH | EAST,
+ NWEST = NORTH | WEST,
+ SEAST = SOUTH | EAST,
+ SWEST = SOUTH | WEST,
+ CENTER = NEAST | SWEST
+};
+
+typedef enum BlitzAlign BlitzAlign;
+
+struct BlitzColor {
+ vlong bg;
+ vlong fg;
+ vlong border;
+ char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
+};
+
+struct BlitzFont {
+ XFontStruct *xfont;
+ XFontSet set;
+ int ascent;
+ int descent;
+ uint height;
+ char *fontstr;
+};
+
+struct BlitzBrush {
+ Blitz *blitz;
+ Drawable drawable;
+ GC gc;
+ int border;
+ BlitzColor color;
+ BlitzAlign align;
+ BlitzFont *font;
+ XRectangle rect; /* relative rect */
+};
+
+enum {
+/* WM atom */
+ WMState, WMProtocols, WMDelete,
+/* NET atom */
+ NetSupported, NetWMName,
+/* Other */
+ TagsAtom,
+/* Last atom */
+ AtomLast
+};
+
+/* Column modes */
+enum { Coldefault, Colstack, Colmax };
+
+/* Cursor */
+enum { CurNormal, CurNECorner, CurNWCorner, CurSECorner, CurSWCorner,
+ CurMove, CurInput, CurInvisible, CurLast };
+
+enum { NCOL = 16 };
+enum { WM_PROTOCOL_DELWIN = 1 };
+
+/* Data Structures */
+typedef struct View View;
+typedef struct Area Area;
+typedef struct Frame Frame;
+typedef struct Client Client;
+typedef struct Key Key;
+typedef struct Bar Bar;
+typedef struct Rule Rule;
+typedef struct Ruleset Ruleset;
+typedef struct WMScreen WMScreen;
+
+struct View {
+ View *next;
+ char name[256];
+ ushort id;
+ Area *area;
+ Area *sel;
+ Area *revert;
+};
+
+struct Area {
+ Area *next;
+ Frame *frame;
+ Frame *stack;
+ Frame *sel;
+ View *view;
+ Bool floating;
+ ushort id;
+ int mode;
+ XRectangle rect;
+};
+
+struct Frame {
+ Frame *cnext;
+ Frame *anext;
+ Frame *snext;
+ View *view;
+ Area *area;
+ ushort id;
+ XRectangle rect;
+ XRectangle crect;
+ XRectangle revert;
+ Client *client;
+ Bool collapsed;
+ XRectangle grabbox;
+ XRectangle titlebar;
+};
+
+struct Client {
+ Client *next;
+ Area *revert;
+ Frame *frame;
+ Frame *sel;
+ char name[256];
+ char tags[256];
+ char props[512];
+ uint border;
+ int proto;
+ Bool floating;
+ Bool fixedsize;
+ Bool fullscreen;
+ Bool urgent;
+ Bool mapped;
+ Bool frame_mapped;
+ int unmapped;
+ Window win;
+ Window trans;
+ Window framewin;
+ Cursor cursor;
+ XRectangle rect;
+ XSizeHints size;
+ GC gc;
+};
+
+struct Key {
+ Key *next;
+ Key *lnext;
+ Key *tnext;
+ ushort id;
+ char name[128];
+ ulong mod;
+ KeyCode key;
+};
+
+struct Bar {
+ Bar *next;
+ Bar *smaller;
+ char buf[280];
+ char text[256];
+ char name[256];
+ ushort id;
+ BlitzBrush brush;
+};
+
+struct Rule {
+ Rule *next;
+ regex_t regex;
+ char value[256];
+};
+
+struct Ruleset {
+ Rule *rule;
+ char *string;
+ uint size;
+};
+
+/* global variables */
+struct {
+ BlitzColor focuscolor;
+ BlitzColor normcolor;
+ BlitzFont font;
+ uint border;
+ uint snap;
+ char *keys;
+ uint keyssz;
+ Ruleset tagrules;
+ Ruleset colrules;
+ char grabmod[5];
+ ulong mod;
+ int colmode;
+} def;
+
+enum { BarLeft, BarRight };
+
+struct WMScreen {
+ Bar *bar[2];
+ View *sel;
+ Client *focus;
+ Client *hasgrab;
+ Window barwin;
+
+ XRectangle rect;
+ XRectangle brect;
+ BlitzBrush bbrush;
+} *screens, *screen;
+
+Client *client;
+View *view;
+Key *key;
+Client c_magic;
+Client c_root;
+
+enum { BUFFER_SIZE = 8092 };
+char buffer[BUFFER_SIZE];
+
+/* IXP */
+IxpServer srv;
+Ixp9Srv p9srv;
+
+/* X11 */
+uint num_screens;
+Blitz blz;
+GC xorgc;
+char *user;
+Atom atom[AtomLast];
+Cursor cursor[CurLast];
+uint valid_mask;
+uint num_lock_mask;
+Bool sel_screen;
+Pixmap pmap;
+void (*handler[LASTEvent]) (XEvent *);
+
+/* Misc */
+Bool starting;
+Bool verbose;
+char *execstr;
+
+/* wm.c */
+char *message_root(char *message);
+
+/* area.c */
+Area *create_area(View *v, Area *pos, uint w);
+void destroy_area(Area *a);
+Area *area_of_id(View *t, ushort id);
+void focus_area(Area *a);
+char *select_area(Area *a, char *arg);
+void send_to_area(Area *to, Frame *f);
+void attach_to_area(Area *a, Frame *f, Bool send);
+void detach_from_area(Frame *f);
+Client *sel_client_of_area(Area *a);
+
+/* bar.c */
+Bar *create_bar(Bar **b_link, char *name);
+void destroy_bar(Bar **b_link, Bar *b);
+void draw_bar(WMScreen *s);
+void draw_border(BlitzBrush *b);
+void resize_bar();
+Bar *bar_of_name(Bar *b_link, const char *name);
+
+/* client.c */
+Client *create_client(Window w, XWindowAttributes *wa);
+void destroy_client(Client *c);
+void configure_client(Client *c);
+void prop_client(Client *c, Atom a);
+void kill_client(Client *c);
+void gravitate_client(Client *c, Bool invert);
+void map_client(Client *c);
+void unmap_client(Client *c, int state);
+void map_frame(Client *c);
+void unmap_frame(Client *c);
+void set_cursor(Client *c, Cursor cur);
+void focus_frame(Frame *f, Bool restack);
+void reparent_client(Client *c, Window w, int x, int y);
+void manage_client(Client *c);
+void focus(Client *c, Bool restack);
+void focus_client(Client *c);
+void resize_client(Client *c, XRectangle *r);
+void apply_sizehints(Client *c, XRectangle *r, Bool floating, Bool frame, BlitzAlign sticky);
+char *send_client(Frame *f, char *arg, Bool swap);
+char * message_client(Client *c, char *message);
+void move_client(Client *c, char *arg);
+void size_client(Client *c, char *arg);
+Client *sel_client();
+Frame *frame_of_win(Window w);
+Client *client_of_win(Window w);
+void update_client_grab(Client *c);
+void apply_rules(Client *c);
+void apply_tags(Client *c, const char *tags);
+
+/* column.c */
+void arrange_column(Area *a, Bool dirty);
+void resize_column(Client *c, XRectangle *r);
+int column_mode_of_str(char *arg);
+char *str_of_column_mode(int mode);
+Area *new_column(View *v, Area *pos, uint w);
+
+/* draw.c */
+int loadcolor(Blitz *blitz, BlitzColor *c);
+void draw_label(BlitzBrush *b, char *text);
+void draw_tile(BlitzBrush *b);
+void draw_rect(BlitzBrush *b);
+
+void drawbg(Display *dpy, Drawable drawable, GC gc,
+ XRectangle *rect, BlitzColor c, Bool fill, Bool border);
+void drawcursor(Display *dpy, Drawable drawable, GC gc,
+ int x, int y, uint h, BlitzColor c);
+uint textwidth(BlitzFont *font, char *text);
+uint textwidth_l(BlitzFont *font, char *text, uint len);
+void loadfont(Blitz *blitz, BlitzFont *font);
+uint labelh(BlitzFont *font);
+char *parse_colors(char **buf, int *buflen, BlitzColor *col);
+
+/* event.c */
+void dispatch_event(XEvent *e);
+void check_x_event(IxpConn *c);
+uint flushevents(long even_mask, Bool dispatch);
+
+/* frame.c */
+Frame *create_frame(Client *c, View *v);
+void remove_frame(Frame *f);
+void insert_frame(Frame *pos, Frame *f, Bool before);
+void resize_frame(Frame *f, XRectangle *r);
+Bool frame_to_top(Frame *f);
+void set_frame_cursor(Frame *f, int x, int y);
+void swap_frames(Frame *fa, Frame *fb);
+int frame_delta_h();
+void frame2client(XRectangle *r);
+void client2frame(XRectangle *r);
+void draw_frame(Frame *f);
+void draw_frames();
+void update_frame_widget_colors(Frame *f);
+void check_frame_constraints(XRectangle *rect);
+
+/* fs.c */
+void fs_attach(Ixp9Req *r);
+void fs_clunk(Ixp9Req *r);
+void fs_create(Ixp9Req *r);
+void fs_flush(Ixp9Req *r);
+void fs_freefid(Fid *f);
+void fs_open(Ixp9Req *r);
+void fs_read(Ixp9Req *r);
+void fs_remove(Ixp9Req *r);
+void fs_stat(Ixp9Req *r);
+void fs_walk(Ixp9Req *r);
+void fs_write(Ixp9Req *r);
+void write_event(char *format, ...);
+
+/* geom.c */
+Bool ptinrect(int x, int y, XRectangle * r);
+BlitzAlign quadrant(XRectangle *rect, int x, int y);
+Cursor cursor_of_quad(BlitzAlign align);
+int strtorect(XRectangle *r, const char *val);
+BlitzAlign get_sticky(XRectangle *src, XRectangle *dst);
+int r_east(XRectangle *r);
+int r_south(XRectangle *r);
+
+/* key.c */
+void kpress(Window w, ulong mod, KeyCode keycode);
+void update_keys();
+void init_lock_keys();
+ulong mod_key_of_str(char *val);
+
+/* mouse.c */
+void do_mouse_resize(Client *c, Bool grabbox, BlitzAlign align);
+void grab_mouse(Window w, ulong mod, ulong button);
+void ungrab_mouse(Window w, ulong mod, uint button);
+BlitzAlign snap_rect(XRectangle *rects, int num, XRectangle *current,
+ BlitzAlign *mask, int snap);
+void grab_button(Window w, uint button, ulong mod);
+
+/* rule.c */
+void update_rules(Rule **rule, const char *data);
+void trim(char *str, const char *chars);
+
+/* view.c */
+void arrange_view(View *v);
+void scale_view(View *v, float w);
+View *get_view(const char *name);
+View *create_view(const char *name);
+void focus_view(WMScreen *s, View *v);
+void update_client_views(Client *c, char **tags);
+XRectangle *rects_of_view(View *v, uint *num, Frame *ignore);
+View *view_of_id(ushort id);
+void select_view(const char *arg);
+void attach_to_view(View *v, Frame *f);
+Client *sel_client_of_view(View *v);
+char *message_view(View *v, char *message);
+void restack_view(View *v);
+uchar *view_index(View *v);
+void destroy_view(View *v);
+void update_views();
+uint newcolw_of_view(View *v);
+
+/* wm.c */
+int wmii_error_handler(Display *dpy, XErrorEvent *error);
+int win_proto(Window w);
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii9menu.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii9menu.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,527 @@
+/* Licence
+ * =======
+ *
+ * 9menu is free software, and is Copyright (c) 1994 by David Hogan and
+ * Arnold Robbins. 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 9menu
+ * and whose documentation gives credit where it is due
+ * (4) the authors are 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.
+ *
+ * --
+ * Arnold Robbins
+ * arnold_AT_skeeve.com
+ *
+ * 9menu.c
+ *
+ * This program puts up a window that is just a menu, and executes
+ * commands that correspond to the items selected.
+ *
+ * Initial idea: Arnold Robbins
+ * Version using libXg: Matty Farrow (some ideas borrowed)
+ * This code by: David Hogan and Arnold Robbins
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xutil.h>
+
+#define nil ((void*)0)
+
+char version[] = "@(#) wmii9menu version 1.8";
+
+/* lovely X stuff */
+Display *dpy;
+int screen;
+Window root;
+Window menuwin;
+Colormap defcmap;
+XColor color;
+XFontStruct *font;
+GC gc;
+
+unsigned long selbg;
+unsigned long selfg;
+unsigned long normbg;
+unsigned long normfg;
+unsigned long border;
+char *sfgname = nil;
+char *sbgname = nil;
+char *nfgname = nil;
+char *nbgname = nil;
+char *brcname = nil;
+
+/* for XSetWMProperties to use */
+int g_argc;
+char **g_argv;
+
+/* for labels read from files */
+int f_argc;
+char **f_argv;
+
+char *initial = "";
+int cur;
+
+char *fontlist[] = { /* default font list if no -font */
+ "pelm.latin1.9",
+ "lucm.latin1.9",
+ "blit",
+ "9x15bold",
+ "9x15",
+ "lucidasanstypewriter-12",
+ "fixed",
+ nil
+};
+
+char *progname; /* my name */
+char *displayname; /* X display */
+char *fontname; /* font */
+char *filename; /* file to read options or labels from */
+
+char **labels; /* list of labels and commands */
+char **commands;
+int numitems;
+
+void usage(), run_menu();
+void create_window();
+void redraw(), warpmouse();
+void memory();
+int args();
+
+/* memory --- print the out of memory message and die */
+
+void
+memory(s)
+char *s;
+{
+ fprintf(stderr, "%s: couldn't allocate memory for %s\n", progname, s);
+ exit(1);
+}
+
+/* args --- go through the argument list, set options */
+
+int
+args(int argc, char **argv)
+{
+ int i;
+ if (argc == 0 || argv == nil || argv[0] == '\0')
+ return -1;
+ for (i = 0; i < argc && argv[i] != nil; i++) {
+ if (strcmp(argv[i], "-display") == 0)
+ displayname = argv[++i];
+ else if (strcmp(argv[i], "-file") == 0)
+ filename = argv[++i];
+ else if (strcmp(argv[i], "-font") == 0)
+ fontname = argv[++i];
+ else if (strncmp(argv[i], "-initial", 9) == 0)
+ initial = argv[++i];
+ else if (strncmp(argv[i], "-nb", 3) == 0)
+ nbgname = argv[i][3] ? &argv[i][3] : argv[++i];
+ else if (strncmp(argv[i], "-nf", 3) == 0)
+ nfgname = argv[i][3] ? &argv[i][3] : argv[++i];
+ else if (strncmp(argv[i], "-sb", 3) == 0)
+ sbgname = argv[i][3] ? &argv[i][3] : argv[++i];
+ else if (strncmp(argv[i], "-sf", 3) == 0)
+ sfgname = argv[i][3] ? &argv[i][3] : argv[++i];
+ else if (strncmp(argv[i], "-br", 3) == 0)
+ brcname = argv[i][3] ? &argv[i][3] : argv[++i];
+ else if (strcmp(argv[i], "-version") == 0) {
+ printf("%s\n", version);
+ exit(0);
+ } else if (argv[i][0] == '-')
+ usage();
+ else
+ break;
+ }
+ return i;
+}
+
+/* main --- crack arguments, set up X stuff, run the main menu loop */
+
+int
+main(int argc, char **argv)
+{
+ int i, j;
+ char *cp;
+ XGCValues gv;
+ unsigned long mask;
+ int nlabels = 0;
+
+ g_argc = argc;
+ g_argv = argv;
+
+ /* set default label name */
+ if ((cp = strrchr(argv[0], '/')) == nil)
+ progname = argv[0];
+ else
+ progname = ++cp;
+
+ ++argv;
+ --argc;
+
+ i = args(argc, argv);
+
+ numitems = argc - i;
+
+ if (numitems <= 0 && filename == nil)
+ usage();
+
+ if (filename) {
+ /* Read options and labels from file */
+ char fbuf[1024];
+ FILE *fp;
+
+ fp = fopen(filename, "r");
+ if (fp == nil) {
+ fprintf(stderr, "%s: couldn't open '%s'\n", progname,
+ filename);
+ exit(1);
+ }
+ while (fgets(fbuf, sizeof fbuf, fp)) {
+ char *s = fbuf;
+ strtok(s, "\n");
+ if (s[0] == '-') {
+ char *temp[3];
+ temp[0] = s;
+ temp[1] = strchr(s, ' ');
+ if (temp[1]) {
+ *(temp[1]++) = '\0';
+ s = malloc(strlen(temp[1]) + 1);
+ if (s == nil)
+ memory("temporary argument");
+ strcpy(s, temp[1]);
+ temp[1] = s;
+ }
+ temp[2] = 0;
+ args(temp[1] ? 2 : 1, temp);
+ continue;
+ }
+ if (s[0] == '#')
+ continue;
+ /* allow - in menu items to be escaped */
+ if (s[0] == '\\')
+ ++s;
+ /* allocate space */
+ if (f_argc < nlabels + 1) {
+ int k;
+ char **temp = malloc(sizeof(char *) * (f_argc + 5));
+ if (temp == 0)
+ memory("temporary item");
+
+ for (k = 0; k < nlabels; k++)
+ temp[k] = f_argv[k];
+
+ free(f_argv);
+ f_argv = temp;
+ f_argc += 5;
+ }
+ f_argv[nlabels] = malloc(strlen(s) + 1);
+ if (f_argv[nlabels] == nil)
+ memory("temporary text");
+ strcpy(f_argv[nlabels], s);
+ ++nlabels;
+ }
+ }
+
+ labels = (char **) malloc((numitems + nlabels) * sizeof(char *));
+ commands = (char **) malloc((numitems + nlabels) * sizeof(char *));
+ if (commands == nil || labels == nil)
+ memory("command and label arrays");
+
+ for (j = 0; j < numitems; j++) {
+ labels[j] = argv[i + j];
+ if ((cp = strchr(labels[j], ':')) != nil) {
+ *cp++ = '\0';
+ commands[j] = cp;
+ } else
+ commands[j] = labels[j];
+ if(strcmp(labels[j], initial) == 0)
+ cur = j;
+ }
+
+ /*
+ * Now we no longer need i (our offset into argv) so we recycle it,
+ * while keeping the old value of j!
+ */
+ for (i = 0; i < nlabels; i++) {
+ labels[j] = f_argv[i];
+ if ((cp = strchr(labels[j], ':')) != nil) {
+ *cp++ = '\0';
+ commands[j] = cp;
+ } else
+ commands[j] = labels[j];
+ ++j;
+ }
+
+ /* And now we merge the totals */
+ numitems += nlabels;
+
+ dpy = XOpenDisplay(displayname);
+ if (dpy == nil) {
+ fprintf(stderr, "%s: cannot open display", progname);
+ if (displayname != nil)
+ fprintf(stderr, " %s", displayname);
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+ screen = DefaultScreen(dpy);
+ root = RootWindow(dpy, screen);
+ /*
+ * This used to be
+ * black = BlackPixel(dpy, screen);
+ * white = WhitePixel(dpy, screen);
+ */
+ defcmap = DefaultColormap(dpy, screen);
+ if (sbgname == nil
+ || XParseColor(dpy, defcmap, sbgname, &color) == 0
+ || XAllocColor(dpy, defcmap, &color) == 0)
+ selbg = BlackPixel(dpy, screen);
+ else
+ selbg = color.pixel;
+
+ if (sfgname == nil
+ || XParseColor(dpy, defcmap, sfgname, &color) == 0
+ || XAllocColor(dpy, defcmap, &color) == 0)
+ selfg = WhitePixel(dpy, screen);
+ else
+ selfg = color.pixel;
+
+ if (nbgname == nil
+ || XParseColor(dpy, defcmap, nbgname, &color) == 0
+ || XAllocColor(dpy, defcmap, &color) == 0)
+ normbg = selfg;
+ else
+ normbg = color.pixel;
+
+ if (nfgname == nil
+ || XParseColor(dpy, defcmap, nfgname, &color) == 0
+ || XAllocColor(dpy, defcmap, &color) == 0)
+ normfg = selbg;
+ else
+ normfg = color.pixel;
+
+ if (brcname == nil
+ || XParseColor(dpy, defcmap, brcname, &color) == 0
+ || XAllocColor(dpy, defcmap, &color) == 0)
+ border = selbg;
+ else
+ border = color.pixel;
+
+ /* try user's font first */
+ if (fontname != nil) {
+ font = XLoadQueryFont(dpy, fontname);
+ if (font == nil)
+ fprintf(stderr, "%s: warning: can't load font %s\n",
+ progname, fontname);
+ }
+
+ /* if no user font, try one of our default fonts */
+ if (font == nil) {
+ for (i = 0; fontlist[i] != nil; i++) {
+ font = XLoadQueryFont(dpy, fontlist[i]);
+ if (font != nil)
+ break;
+ }
+ }
+
+ if (font == nil) {
+ fprintf(stderr, "%s: fatal: cannot load a font\n", progname);
+ exit(1);
+ }
+
+ gv.foreground = normfg;
+ gv.background = normbg;
+ gv.font = font->fid;
+ gv.line_width = 0;
+ mask = GCForeground | GCBackground | GCFont | GCLineWidth;
+ gc = XCreateGC(dpy, root, mask, &gv);
+
+ run_menu();
+
+ XCloseDisplay(dpy);
+ exit(0);
+}
+
+/* usage --- print a usage message and die */
+
+void
+usage()
+{
+ fprintf(stderr, "usage: %s [-display <displayname>] [-font <fontname>] ", progname);
+ fprintf(stderr, "[-file filename] ");
+ fprintf(stderr, "[-{n,s}{f,b} <color>] [-br <color>] ");
+ fprintf(stderr, "[-version] menitem[:command] ...\n");
+ exit(0);
+}
+
+/* run_menu --- put up the window, execute selected commands */
+
+void
+run_menu()
+{
+ XEvent ev;
+ int i, old, wide, high, dx, dy;
+
+ dx = 0;
+ for (i = 0; i < numitems; i++) {
+ wide = XTextWidth(font, labels[i], strlen(labels[i])) + 4;
+ if (wide > dx)
+ dx = wide;
+ }
+ wide = dx;
+
+ high = font->ascent + font->descent + 1;
+ dy = numitems * high;
+
+ enum {
+ MouseMask =
+ ButtonPressMask
+ | ButtonReleaseMask
+ | ButtonMotionMask
+ | PointerMotionMask,
+ MenuMask =
+ MouseMask
+ | StructureNotifyMask
+ | ExposureMask
+ };
+
+ create_window(wide, high);
+ warpmouse(wide, high);
+
+ XSelectInput(dpy, menuwin, MenuMask);
+
+ XMapWindow(dpy, menuwin);
+
+ i = 0; /* save menu Item position */
+
+ for (;;) {
+ XNextEvent(dpy, &ev);
+ switch (ev.type) {
+ default:
+ fprintf(stderr, "%s: unknown ev.type %d\n",
+ progname, ev.type);
+ break;
+ case ButtonRelease:
+ i = ev.xbutton.y/high;
+ if (ev.xbutton.x < 0 || ev.xbutton.x > wide)
+ return;
+ else if (i < 0 || i >= numitems)
+ return;
+
+ printf("%s\n", commands[i]);
+ return;
+ case ButtonPress:
+ case MotionNotify:
+ old = cur;
+ cur = ev.xbutton.y/high;
+ if (ev.xbutton.x < 0 || ev.xbutton.x > wide)
+ cur = ~0;
+ if (cur == old)
+ break;
+ redraw(high, wide);
+ break;
+ case MapNotify:
+ redraw(high, wide);
+ if(XGrabPointer(dpy, menuwin, False, MouseMask,
+ GrabModeAsync, GrabModeAsync,
+ 0, None, CurrentTime
+ ) != GrabSuccess) {
+ fprintf(stderr, "Failed to grab the mouse\n");
+ }
+ break;
+ case Expose:
+ redraw(high, wide);
+ break;
+ case MappingNotify: /* why do we get this? */
+ break;
+ }
+ }
+}
+
+/* set_wm_hints --- set all the window manager hints */
+
+void
+create_window(int wide, int high)
+{
+ XSetWindowAttributes wa = { 0 };
+ unsigned int h;
+ int x, y, dummy;
+ Window wdummy;
+
+ h = high * numitems;
+
+ XQueryPointer(dpy, root, &wdummy, &wdummy, &x, &y,
+ &dummy, &dummy, (uint*)&dummy);
+ x -= wide / 2;
+ if (x < 0)
+ x = 0;
+ else if (x + wide > DisplayWidth(dpy, screen))
+ x = DisplayWidth(dpy, screen) - wide;
+
+ y -= cur * high + high / 2;
+ if (y < 0)
+ y = 0;
+ else if (y + h > DisplayHeight(dpy, screen))
+ y = DisplayHeight(dpy, screen) - h;
+
+ wa.override_redirect = True;
+ wa.border_pixel = border;
+ wa.background_pixel = normbg;
+ menuwin = XCreateWindow(dpy, root, x, y, wide, h,
+ 1, DefaultDepth(dpy, screen), CopyFromParent,
+ DefaultVisual(dpy, screen),
+ CWOverrideRedirect
+ | CWBackPixel
+ | CWBorderPixel
+ | CWEventMask,
+ &wa);
+
+ XSetCommand(dpy, menuwin, g_argv, g_argc);
+}
+
+/* redraw --- actually redraw the menu */
+
+void
+redraw(int high, int wide)
+{
+ int tx, ty, i;
+
+ for (i = 0; i < numitems; i++) {
+ tx = (wide - XTextWidth(font, labels[i], strlen(labels[i]))) / 2;
+ ty = i*high + font->ascent + 1;
+ if (cur == i)
+ XSetForeground(dpy, gc, selbg);
+ else
+ XSetForeground(dpy, gc, normbg);
+ XFillRectangle(dpy, menuwin, gc, 0, i*high, wide, high);
+ if (cur == i)
+ XSetForeground(dpy, gc, selfg);
+ else
+ XSetForeground(dpy, gc, normfg);
+ XDrawString(dpy, menuwin, gc, tx, ty, labels[i], strlen(labels[i]));
+ }
+}
+
+/* warpmouse --- bring the mouse to the menu */
+
+void
+warpmouse(int wide, int high)
+{
+ int offset;
+
+ /* move tip of pointer into middle of menu item */
+ offset = (font->ascent + font->descent + 1) / 2;
+ offset += 6; /* fudge factor */
+
+ XWarpPointer(dpy, None, menuwin, 0, 0, 0, 0,
+ wide/2, cur*high-high/2+offset);
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmii9rc.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmii9rc.sh Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,19 @@
+#!/bin/sh -f
+RC=""
+for i in "$PLAN9" P9PATHS; do
+ if [ -d "$i" -a -x "$i/bin/rc" ]; then
+ export PLAN9="$i"
+ RC="$i/bin/rc"
+ break;
+ fi
+done
+
+if [ ! -n "$RC" ]; then
+ exit 1
+fi
+
+if [ -n "$1" ]; then
+ exec $RC $@
+else
+ true
+fi
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmiiloop.awk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmiiloop.awk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,35 @@
+#!AWKPATH -f
+BEGIN {
+ arg[1] = "Nop"
+ body = "";
+ writekeys = "wmiir write /keys"
+ print "IFS=''"
+}
+
+function addevent() {
+ if(arg[1] == "Key")
+ keys[arg[2]] = 1;
+
+ var = arg[1] "s"
+ print var "=\"$" var " " arg[2] "\""
+
+ gsub("[^a-zA-Z_0-9]", "_", arg[2]);
+ if(body != "")
+ print arg[1] "_" arg[2] "() {" body "\n}"
+}
+
+/^(Event|Key|Action)[ \t]/ {
+ addevent()
+ split($0, arg)
+ body = ""
+}
+/^[ \t]/ {
+ body = body"\n"$0
+}
+
+END {
+ addevent()
+ for(key in keys)
+ print key | writekeys;
+ close(writekeys);
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmiir.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmiir.c Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,321 @@
+/* Copyright ©2007 Kris Maglione <fbsdaemon_AT_gmail.com>
+ * See LICENSE file for license details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <ixp.h>
+#include <util.h>
+
+static IxpClient *client;
+
+static void
+usage() {
+ fprintf(stderr,
+ "usage: %1$s [-a <address>] {create | read | ls [-ld] | remove | write} <file>\n"
+ " %1$s [-a <address>] xwrite <file> <data>\n"
+ " %1$s -v\n", argv0);
+ exit(1);
+}
+
+/* Utility Functions */
+static void
+write_data(IxpCFid *fid) {
+ void *buf;
+ uint len;
+
+ buf = ixp_emalloc(fid->iounit);;
+ while((len = read(0, buf, fid->iounit)) > 0)
+ if(ixp_write(fid, buf, len) != len)
+ fatal("cannot write file: %s\n", errstr);
+ /* do an explicit empty write when no writing has been done yet */
+ if(fid->offset == 0)
+ if(ixp_write(fid, buf, 0) != 0)
+ fatal("cannot write file: %s\n", errstr);
+ free(buf);
+}
+
+static int
+comp_stat(const void *s1, const void *s2) {
+ Stat *st1, *st2;
+
+ st1 = (Stat*)s1;
+ st2 = (Stat*)s2;
+ return strcmp(st1->name, st2->name);
+}
+
+static void
+setrwx(long m, char *s) {
+ static char *modes[] = {
+ "---", "--x", "-w-",
+ "-wx", "r--", "r-x",
+ "rw-", "rwx",
+ };
+ strncpy(s, modes[m], 3);
+}
+
+static char *
+str_of_mode(uint mode) {
+ static char buf[16];
+
+ buf[0]='-';
+ if(mode & P9_DMDIR)
+ buf[0]='d';
+ buf[1]='-';
+ setrwx((mode >> 6) & 7, &buf[2]);
+ setrwx((mode >> 3) & 7, &buf[5]);
+ setrwx((mode >> 0) & 7, &buf[8]);
+ buf[11] = 0;
+ return buf;
+}
+
+static char *
+str_of_time(uint val) {
+ static char buf[32];
+
+ ctime_r((time_t*)&val, buf);
+ buf[strlen(buf) - 1] = '\0';
+ return buf;
+}
+
+static void
+print_stat(Stat *s, int details) {
+ if(details)
+ fprintf(stdout, "%s %s %s %5llu %s %s\n", str_of_mode(s->mode),
+ s->uid, s->gid, s->length, str_of_time(s->mtime), s->name);
+ else {
+ if((s->mode&P9_DMDIR) && strcmp(s->name, "/"))
+ fprintf(stdout, "%s/\n", s->name);
+ else
+ fprintf(stdout, "%s\n", s->name);
+ }
+}
+
+/* Service Functions */
+static int
+xwrite(int argc, char *argv[]) {
+ IxpCFid *fid;
+ char *file;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+
+ file = EARGF(usage());
+ fid = ixp_open(client, file, P9_OWRITE);
+ if(fid == nil)
+ fatal("Can't open file '%s': %s\n", file, errstr);
+
+ write_data(fid);
+ return 0;
+}
+
+static int
+xawrite(int argc, char *argv[]) {
+ IxpCFid *fid;
+ char *file, *buf, *arg;
+ int nbuf, mbuf, len;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+
+ file = EARGF(usage());
+ fid = ixp_open(client, file, P9_OWRITE);
+ if(fid == nil)
+ fatal("Can't open file '%s': %s\n", file, errstr);
+
+ nbuf = 0;
+ mbuf = 128;
+ buf = ixp_emalloc(mbuf);
+ while(argc) {
+ arg = ARGF();
+ len = strlen(arg);
+ if(nbuf + len > mbuf) {
+ mbuf <<= 1;
+ buf = ixp_erealloc(buf, mbuf);
+ }
+ memcpy(buf+nbuf, arg, len);
+ nbuf += len;
+ if(argc)
+ buf[nbuf++] = ' ';
+ }
+
+ if(ixp_write(fid, buf, nbuf) == -1)
+ fatal("cannot write file '%s': %s\n", file, errstr);
+ return 0;
+}
+
+static int
+xcreate(int argc, char *argv[]) {
+ IxpCFid *fid;
+ char *file;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+
+ file = EARGF(usage());
+ fid = ixp_create(client, file, 0777, P9_OREAD);
+ if(fid == nil)
+ fatal("Can't create file '%s': %s\n", file, errstr);
+
+ if((fid->qid.type&P9_DMDIR) == 0)
+ write_data(fid);
+
+ return 0;
+}
+
+static int
+xremove(int argc, char *argv[]) {
+ char *file;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+
+ file = EARGF(usage());
+ if(ixp_remove(client, file) == 0)
+ fatal("Can't remove file '%s': %s\n", file, errstr);
+ return 0;
+}
+
+static int
+xread(int argc, char *argv[]) {
+ IxpCFid *fid;
+ char *file, *buf;
+ int count;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+
+ file = EARGF(usage());
+ fid = ixp_open(client, file, P9_OREAD);
+ if(fid == nil)
+ fatal("Can't open file '%s': %s\n", file, errstr);
+
+ buf = ixp_emalloc(fid->iounit);
+ while((count = ixp_read(fid, buf, fid->iounit)) > 0)
+ write(1, buf, count);
+
+ if(count == -1)
+ fatal("cannot read file/directory '%s': %s\n", file, errstr);
+
+ return 0;
+}
+
+static int
+xls(int argc, char *argv[]) {
+ Message m;
+ Stat *stat;
+ IxpCFid *fid;
+ char *file, *buf;
+ int lflag, dflag, count, nstat, mstat, i;
+
+ lflag = dflag = 0;
+
+ ARGBEGIN{
+ case 'l':
+ lflag++;
+ break;
+ case 'd':
+ dflag++;
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ file = EARGF(usage());
+
+ stat = ixp_stat(client, file);
+ if(stat == nil)
+ fatal("cannot stat file '%s': %s\n", file, errstr);
+
+ if(dflag || (stat->mode&P9_DMDIR) == 0) {
+ print_stat(stat, lflag);
+ ixp_freestat(stat);
+ return 0;
+ }
+ ixp_freestat(stat);
+
+ fid = ixp_open(client, file, P9_OREAD);
+ if(fid == nil)
+ fatal("Can't open file '%s': %s\n", file, errstr);
+
+ nstat = 0;
+ mstat = 16;
+ stat = ixp_emalloc(sizeof(*stat) * mstat);
+ buf = ixp_emalloc(fid->iounit);
+ while((count = ixp_read(fid, buf, fid->iounit)) > 0) {
+ m = ixp_message(buf, count, MsgUnpack);
+ while(m.pos < m.end) {
+ if(nstat == mstat) {
+ mstat <<= 1;
+ stat = ixp_erealloc(stat, mstat);
+ }
+ ixp_pstat(&m, &stat[nstat++]);
+ }
+ }
+
+ qsort(stat, nstat, sizeof(*stat), comp_stat);
+ for(i = 0; i < nstat; i++) {
+ print_stat(&stat[i], lflag);
+ ixp_freestat(&stat[i]);
+ }
+ free(stat);
+
+ if(count == -1)
+ fatal("cannot read directory '%s': %s\n", file, errstr);
+ return 0;
+}
+
+int
+main(int argc, char *argv[]) {
+ int ret;
+ char *cmd, *address;
+
+ address = getenv("WMII_ADDRESS");
+
+ ARGBEGIN{
+ case 'v':
+ puts("ixpc-" VERSION ", ©2007 Kris Maglione\n");
+ exit(0);
+ case 'a':
+ address = EARGF(usage());
+ }ARGEND;
+
+ cmd = EARGF(usage());
+
+ if(!address)
+ fatal("$WMII_ADDRESS not set\n");
+
+ client = ixp_mount(address);
+ if(client == nil)
+ fatal("%s\n", errstr);
+
+ if(!strcmp(cmd, "create"))
+ ret = xcreate(argc, argv);
+ else if(!strcmp(cmd, "ls"))
+ ret = xls(argc, argv);
+ else if(!strcmp(cmd, "read"))
+ ret = xread(argc, argv);
+ else if(!strcmp(cmd, "remove"))
+ ret = xremove(argc, argv);
+ else if(!strcmp(cmd, "write"))
+ ret = xwrite(argc, argv);
+ else if(!strcmp(cmd, "xwrite"))
+ ret = xawrite(argc, argv);
+ else
+ usage();
+
+ ixp_unmount(client);
+ return ret;
+}
diff -r 7ce25d709bbe -r de2320e9f616 cmd/wmiistartrc.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/wmiistartrc.sh Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,13 @@
+#!/bin/sh -f
+# start wmiirc
+
+export WMII_CONFPATH="$HOME/.wmii-CONFVERSION:CONFPREFIX/wmii-CONFVERSION"
+
+if wmii9rc; then
+ WMIIRC=`PATH="$WMII_CONFPATH:$PATH" which rc.wmii`
+else
+ WMIIRC=`PATH="$WMII_CONFPATH:$PATH" which wmiirc`
+fi
+
+mkdir $HOME/.wmii-CONFVERSION 2>/dev/null && CONFPREFIX/wmii-CONFVERSION/welcome &
+exec "$WMIIRC" $@
diff -r 7ce25d709bbe -r de2320e9f616 column.c
--- a/column.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <math.h>
-#include <string.h>
-#include "wmii.h"
-
-char *
-str_of_column_mode(int mode) {
- switch(mode) {
- case Coldefault: return "default"; break;
- case Colstack: return "stack"; break;
- case Colmax: return "max"; break;
- default: break;
- }
- return nil;
-}
-
-int
-column_mode_of_str(char *arg) {
- if(!strncmp("default", arg, 8))
- return Coldefault;
- if(!strncmp("stack", arg, 6))
- return Colstack;
- if(!strncmp("max", arg, 4))
- return Colmax;
- return -1;
-}
-
-static void
-scale_column(Area *a) {
- Frame *f, **fp;
- uint min_height, yoff, dy;
- uint num_col, num_uncol;
- uint col_h, uncol_h;
- int surplus, i, j;
-
- if(!a->frame)
- return;
-
- /* This works by comparing heights based on a surplus of their
- * minimum size. We start by subtracting the minimum size, then
- * scale the surplus, and add back the minimum size later. This
- * is based on the size of the client, rather than the frame, so
- * increment gaps can be equalized later */
- /* Frames that can't be accomodated are pushed to the floating layer */
-
- min_height = labelh(&def.font);
- col_h = labelh(&def.font);
- uncol_h = min_height + frame_delta_h();
-
- num_col = 0;
- num_uncol = 0;
- dy = 0;
- for(f=a->frame; f; f=f->anext)
- if(f->collapsed)
- num_col++;
- else
- num_uncol++;
-
- surplus = a->rect.height;
- surplus -= num_col * col_h;
- surplus -= num_uncol * uncol_h;
- if(surplus < 0) {
- i = ceil((float)(-surplus)/(uncol_h - col_h));
- if(i >= num_uncol)
- i = num_uncol - 1;
- num_uncol -= i;
- num_col += i;
- surplus += i * (uncol_h - col_h);
- }
- if(surplus < 0) {
- i = ceil((float)(-surplus)/col_h);
- if(i > num_col)
- i = num_col;
- num_col -= i;
- surplus += i * col_h;
- }
-
- i = num_col - 1;
- j = num_uncol - 1;
- for(f=a->frame; f; f=f->anext) {
- if(f == a->sel)
- j++;
- if(!f->collapsed) {
- if(j < 0 && f != a->sel)
- f->collapsed = True;
- else {
- if(f->crect.height <= min_height)
- f->crect.height = 1;
- else
- f->crect.height -= min_height;
- dy += f->crect.height;
- }
- j--;
- }
- }
- for(fp=&a->frame; *fp;) {
- f = *fp;
- if(f == a->sel)
- i++;
- if(f->collapsed) {
- if(i < 0 && f != a->sel) {
- f->collapsed = False;
- send_to_area(f->view->area, f);
- continue;
- }
- i--;
- }
- fp=&f->anext;
- }
-
- i = num_uncol;
- for(f=a->frame; f; f=f->anext) {
- f->rect.x = a->rect.x;
- f->rect.width = a->rect.width;
- if(!f->collapsed) {
- i--;
- f->rect.height = (float)f->crect.height / dy * surplus;
- if(!i)
- f->rect.height = surplus;
- f->rect.height += min_height + frame_delta_h();
- apply_sizehints(f->client, &f->rect, False, True, NWEST);
-
- dy -= f->crect.height;
- surplus -= f->rect.height - frame_delta_h() - min_height;
- }else
- f->rect.height = labelh(&def.font);
- }
-
- yoff = a->rect.y;
- i = num_uncol;
- for(f=a->frame; f; f=f->anext) {
- f->rect.y = yoff;
- f->rect.x = a->rect.x;
- f->rect.width = a->rect.width;
- if(f->collapsed)
- yoff += f->rect.height;
- else{
- i--;
- f->rect.height += surplus / num_uncol;
- if(!i)
- f->rect.height += surplus % num_uncol;
- yoff += f->rect.height;
- }
- }
-}
-
-void
-arrange_column(Area *a, Bool dirty) {
- Frame *f;
-
- if(a->floating || !a->frame)
- return;
-
- switch(a->mode) {
- case Coldefault:
- for(f=a->frame; f; f=f->anext) {
- f->collapsed = False;
- if(dirty)
- f->crect.height = 100;
- }
- break;
- case Colstack:
- for(f=a->frame; f; f=f->anext)
- f->collapsed = (f != a->sel);
- break;
- case Colmax:
- for(f=a->frame; f; f=f->anext) {
- f->collapsed = False;
- f->rect = a->rect;
- }
- goto resize;
- default:
- break;
- }
- scale_column(a);
-resize:
- if(a->view == screen->sel) {
- restack_view(a->view);
- resize_client(a->sel->client, &a->sel->rect);
- for(f=a->frame; f; f=f->anext)
- if(!f->collapsed && f != a->sel)
- resize_client(f->client, &f->rect);
- for(f=a->frame; f; f=f->anext)
- if(f->collapsed && f != a->sel)
- resize_client(f->client, &f->rect);
- }
-}
-
-static void
-match_horiz(Area *a, XRectangle *r) {
- Frame *f;
-
- for(f=a->frame; f; f=f->anext) {
- f->rect.x = r->x;
- f->rect.width = r->width;
- resize_frame(f, &f->rect);
- }
-}
-
-void
-resize_column(Client *c, XRectangle *new) {
- Area *west, *east, *a;
- Frame *north, *south, *f;
- View *v;
- BlitzAlign sticky;
- uint min_height;
- uint min_width;
-
- f = c->sel;
- a = f->area;
- v = a->view;
- min_height = 2 * labelh(&def.font);
- min_width = screen->rect.width/NCOL;
-
- for(west=v->area->next; west; west=west->next)
- if(west->next == a) break;
- east = a->next;
- for(north=a->frame; north; north=north->anext)
- if(north->anext == f) break;
- south = f->anext;
- /* validate (and trim if necessary) horizontal resize */
- sticky = get_sticky(&f->rect, new);
- if(new->width < min_width) {
- if(sticky & EAST)
- new->x = r_east(&a->rect) - min_width;
- new->width = min_width;
- }
- if(west && !(sticky & WEST)) {
- if(new->x < 0 || new->x < (west->rect.x + min_width)) {
- new->width -= (west->rect.x + min_width) - new->x;
- new->x = west->rect.x + min_width;
- }
- } else {
- new->width += new->x - a->rect.x;
- new->x = a->rect.x;
- }
- if(east && !(sticky & EAST)) {
- if(r_east(new) > r_east(&east->rect) - min_width)
- new->width = r_east(&east->rect) - min_width - new->x;
- } else
- new->width = r_east(&a->rect) - new->x;
- if(new->width < min_width)
- goto AfterHorizontal;
- /* horizontal resize */
- sticky = get_sticky(&a->rect, new);
- if(west && !(sticky & WEST)) {
- west->rect.width = new->x - west->rect.x;
- a->rect.width += a->rect.x - new->x;
- a->rect.x = new->x;
- match_horiz(a, &a->rect);
- match_horiz(west, &west->rect);
- //relax_column(west);
- }
- if(east && !(sticky & EAST)) {
- east->rect.width -= r_east(new) - east->rect.x;
- east->rect.x = r_east(new);
- a->rect.width = r_east(new) - a->rect.x;
- match_horiz(a, &a->rect);
- match_horiz(east, &east->rect);
- //relax_column(east);
- }
-AfterHorizontal:
- /* skip vertical resize unless the column is in equal mode */
- if(a->mode != Coldefault)
- goto AfterVertical;
- /* validate (and trim if necessary) vertical resize */
- sticky = get_sticky(&f->rect, new);
- if(new->height < min_height) {
- if((f->rect.height < min_height) && sticky & (NORTH|SOUTH))
- goto AfterVertical;
- if(sticky & SOUTH)
- new->y = r_south(&f->rect) - min_height;
- new->height = min_height;
- }
- if(north && !(sticky & NORTH))
- if(new->y < 0 || new->y < (north->rect.y + min_height)) {
- new->height -= (north->rect.y + min_height) - new->y;
- new->y = north->rect.y + min_height;
- }
- if(south && !(sticky & SOUTH)) {
- if(r_south(new) > r_south(&south->rect) - min_height)
- new->height = r_south(&south->rect) - min_height - new->y;
- }
- if(new->height < min_height)
- goto AfterVertical;
- /* vertical resize */
- if(north && !(sticky & NORTH)) {
- north->rect.height = new->y - north->rect.y;
- f->rect.height += f->rect.y - new->y;
- f->rect.y = new->y;
- resize_frame(north, &north->rect);
- resize_frame(f, &f->rect);
- }
- if(south && !(sticky & SOUTH)) {
- south->rect.height -= r_south(new) - south->rect.y;
- south->rect.y = r_south(new);
- f->rect.y = new->y;
- f->rect.height = new->height;
- resize_frame(f, &f->rect);
- resize_frame(south, &south->rect);
- }
-AfterVertical:
- arrange_column(a, False);
- focus_view(screen, v);
-}
-
-Area *
-new_column(View *v, Area *pos, uint w) {
- Area *a = create_area(v, pos, w);
- if(!a)
- return nil;
- arrange_view(v);
- return a;
-}
diff -r 7ce25d709bbe -r de2320e9f616 config.mk
--- a/config.mk Sun Mar 25 15:16:24 2007 -0400
+++ b/config.mk Mon Mar 26 00:48:00 2007 -0400
@@ -1,35 +1,38 @@
-# wmii version
-VERSION = $$(hg tip --template 'hg{rev}' 2>/dev/null)
-CONFVERSION = 3.5
-
# Customize below to fit your system
# paths
PREFIX = /usr/local
-CONFPREFIX = ${PREFIX}/etc
-MANPREFIX = ${PREFIX}/share/man
+BIN = ${PREFIX}/bin
+MAN = ${PREFIX}/share/man
+ETC = ${PREFIX}/etc
+LIBDIR = ${PREFIX}/lib
+INCLUDE = ${PREFIX}/include
+
+# Includes and libs
+INCS = -I. -I${ROOT}/include -I${INCLUDE} -I/usr/include
+LIBS = -L/usr/lib -lc
+
+# Flags
+CFLAGS = -g -Wall ${INCS} -DVERSION=\"${VERSION}\"
+LDFLAGS = -g ${LIBS}
+
+# Compiler
+CC = cc -c
+# Linker (Under normal circumstances, this should *not* be 'ld')
+LD = cc
+# Other
+AR = ar cr
+RANLIB = ranlib
+
AWKPATH = /usr/bin/awk
P9PATHS = /usr/local/plan9 /usr/local/9 /opt/plan9 /opt/9 /usr/plan9 /usr/9
-X11INC = /usr/X11R6/include
-X11LIB = /usr/X11R6/lib
-
-# includes and libs
-INCS = -I. -I${PREFIX}/include -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lm -L${X11LIB} -lX11
-LIBIXP = -L${PREFIX}/lib -lixp
-
-# flags
-#CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
-#LDFLAGS = ${LIBS}
-CFLAGS = -g -Wall ${INCS} -DVERSION=\"${VERSION}\"
-LDFLAGS = -g ${LIBS}
+INCX11 = -I/usr/X11R6/include
+LIBX11 = -L/usr/X11R6/lib -lX11
+LIBIXP = ${ROOT}/libixp/libixp.a
# Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS} -R${PREFIX}/lib
#LDFLAGS += -lsocket -lnsl
#CFLAGS += -xtarget=ultra
-
-# compiler and linker
-CC = cc
diff -r 7ce25d709bbe -r de2320e9f616 draw.c
--- a/draw.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-#include <stdlib.h>
-#include <string.h>
-#include "wmii.h"
-
-uint
-textwidth_l(BlitzFont *font, char *text, uint len) {
- if(font->set) {
- XRectangle r;
- XmbTextExtents(font->set, text, len, &r, nil);
- return r.width;
- }
- return XTextWidth(font->xfont, text, len);
-}
-
-uint
-textwidth(BlitzFont *font, char *text) {
- return textwidth_l(font, text, strlen(text));
-}
-
-void
-loadfont(Blitz *blitz, BlitzFont *font) {
- char *fontname = font->fontstr;
- char **missing = nil, *def = "?";
- int n;
-
- if(font->set)
- XFreeFontSet(blitz->dpy, font->set);
- font->set = XCreateFontSet(blitz->dpy, fontname, &missing, &n, &def);
- if(missing) {
- while(n--)
- fprintf(stderr, "wmii: missing fontset for '%s': %s\n",
- fontname, missing[n]);
- XFreeStringList(missing);
- }
- if(font->set) {
- XFontSetExtents *font_extents;
- XFontStruct **xfonts;
- char **font_names;
-
- font->ascent = font->descent = 0;
- font_extents = XExtentsOfFontSet(font->set);
- XFontsOfFontSet(font->set, &xfonts, &font_names);
- font->ascent = xfonts[0]->ascent;
- font->descent = xfonts[0]->descent;
- }
- else {
- if(font->xfont)
- XFreeFont(blitz->dpy, font->xfont);
- font->xfont = nil;
- font->xfont = XLoadQueryFont(blitz->dpy, fontname);
- if (!font->xfont) {
- if(!strncmp(fontname, BLITZ_FONT, sizeof(BLITZ_FONT)))
- fatal("cannot load font: %s",
- BLITZ_FONT);
- free(font->fontstr);
- font->fontstr = estrdup(BLITZ_FONT);
- loadfont(blitz, font);
- return;
- }
- font->ascent = font->xfont->ascent;
- font->descent = font->xfont->descent;
- }
- font->height = font->ascent + font->descent;
-}
-
-uint
-labelh(BlitzFont *font) {
- return font->height + 2;
-}
-
-void
-draw_tile(BlitzBrush *b) {
- drawbg(b->blitz->dpy, b->drawable, b->gc, &b->rect,
- b->color, True, b->border);
-}
-
-void
-draw_border(BlitzBrush *b) {
- drawbg(b->blitz->dpy, b->drawable, b->gc, &b->rect,
- b->color, False, b->border);
-}
-
-void
-draw_label(BlitzBrush *b, char *text) {
- uint x, y, w, h, len;
- Bool shortened = False;
- static char buf[2048];
- XRectangle r = {0};
- XGCValues gcv;
-
- draw_tile(b);
- if(!text)
- return;
- shortened = 0;
- strncpy(buf, text, sizeof(buf));
- len = strlen(buf);
- gcv.foreground = b->color.fg;
- gcv.background = b->color.bg;
- h = b->font->ascent + b->font->descent;
- y = b->rect.y + b->rect.height / 2 - h / 2 + b->font->ascent;
- /* shorten text if necessary */
- while(len
- && (w = textwidth(b->font, buf)) > b->rect.width - (b->font->height & ~1)) {
- buf[--len] = 0;
- shortened = True;
- }
- if(!len)
- return;
- if(w > b->rect.width)
- return;
- /* mark shortened info in the string */
- if(shortened) {
- if (len > 3)
- buf[len - 3] = '.';
- if (len > 2)
- buf[len - 2] = '.';
- if (len > 1)
- buf[len - 1] = '.';
- }
-
- if(b->font->set) {
- XmbTextExtents(b->font->set, text, len, &r, nil);
- }
-
- switch (b->align) {
- case EAST:
- x = b->rect.x + b->rect.width - (w + (b->font->height / 2));
- break;
- default:
- x = b->rect.x + (b->font->height / 2) - r.x;
- break;
- }
- if(b->font->set) {
- XChangeGC(b->blitz->dpy, b->gc, GCForeground | GCBackground, &gcv);
- XmbDrawImageString(b->blitz->dpy, b->drawable, b->font->set, b->gc,
- x, y, buf, len);
- }
- else {
- gcv.font = b->font->xfont->fid;
- XChangeGC(b->blitz->dpy, b->gc, GCForeground | GCBackground | GCFont, &gcv);
- XDrawImageString(b->blitz->dpy, b->drawable, b->gc, x, y, buf, len);
- }
-}
-
-void
-drawbg(Display *dpy, Drawable drawable, GC gc, XRectangle *rect,
- BlitzColor c, Bool fill, int border)
-{
- if(fill) {
- XSetForeground(dpy, gc, c.bg);
- XFillRectangles(dpy, drawable, gc, rect, 1);
- }
- if(border) {
- XSetLineAttributes(dpy, gc, border, LineSolid, CapButt, JoinMiter);
- XSetForeground(dpy, gc, c.border);
- XDrawRectangle(dpy, drawable, gc, rect->x + border / 2, rect->y + border / 2,
- rect->width - border, rect->height - border);
- }
-}
-
-void
-drawcursor(Display *dpy, Drawable drawable, GC gc,
- int x, int y, uint h, BlitzColor c)
-{
- XSegment s[5];
-
- XSetForeground(dpy, gc, c.fg);
- XSetLineAttributes(dpy, gc, 1, LineSolid, CapButt, JoinMiter);
- s[0].x1 = x - 1;
- s[0].y1 = s[0].y2 = y;
- s[0].x2 = x + 2;
- s[1].x1 = x - 1;
- s[1].y1 = s[1].y2 = y + 1;
- s[1].x2 = x + 2;
- s[2].x1 = s[2].x2 = x;
- s[2].y1 = y;
- s[2].y2 = y + h;
- s[3].x1 = x - 1;
- s[3].y1 = s[3].y2 = y + h;
- s[3].x2 = x + 2;
- s[4].x1 = x - 1;
- s[4].y1 = s[4].y2 = y + h - 1;
- s[4].x2 = x + 2;
- XDrawSegments(dpy, drawable, gc, s, 5);
-}
-
-static ulong
-xloadcolor(Blitz *blitz, char *colstr) {
- XColor color;
- char col[8];
-
- strncpy(col, colstr, sizeof(col));
- col[7] = 0;
- XAllocNamedColor(blitz->dpy,
- DefaultColormap(blitz->dpy, blitz->screen), col, &color, &color);
- return color.pixel;
-}
-
-int
-loadcolor(Blitz *blitz, BlitzColor *c) {
- if(!c->colstr || strlen(c->colstr) != 23)
- return -1;
- c->fg = xloadcolor(blitz, &c->colstr[0]);
- c->bg = xloadcolor(blitz, &c->colstr[8]);
- c->border = xloadcolor(blitz, &c->colstr[16]);
- return 0;
-}
-
-char *
-parse_colors(char **buf, int *buflen, BlitzColor *col) {
- uint i;
- if(*buflen < 23 || 3 != sscanf(*buf, "#%06x #%06x #%06x", &i,&i,&i))
- return "bad value";
- (*buflen) -= 23;
- bcopy(*buf, col->colstr, 23);
- loadcolor(&blz, col);
-
- (*buf) += 23;
- if(**buf == '\n' || **buf == ' ') {
- (*buf)++;
- (*buflen)--;
- }
- return nil;
-}
diff -r 7ce25d709bbe -r de2320e9f616 event.c
--- a/event.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,448 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <X11/keysym.h>
-#include "wmii.h"
-#include "printevent.h"
-
-void
-dispatch_event(XEvent *e) {
- if(handler[e->type])
- handler[e->type](e);
-}
-
-uint
-flushevents(long event_mask, Bool dispatch) {
- XEvent ev;
- uint n = 0;
-
- while(XCheckMaskEvent(blz.dpy, event_mask, &ev)) {
- if(dispatch)
- dispatch_event(&ev);
- n++;
- }
- return n;
-}
-
-static void
-buttonrelease(XEvent *e) {
- XButtonPressedEvent *ev;
- Frame *f;
- Bar *b;
-
- ev = &e->xbutton;
- if(ev->window == screen->barwin) {
- for(b=screen->bar[BarLeft]; b; b=b->next)
- if(ptinrect(ev->x, ev->y, &b->brush.rect)) {
- write_event("LeftBarClick %d %s\n", ev->button, b->name);
- return;
- }
- for(b=screen->bar[BarRight]; b; b=b->next)
- if(ptinrect(ev->x, ev->y, &b->brush.rect)) {
- write_event("RightBarClick %d %s\n", ev->button, b->name);
- return;
- }
- }
- else if((f = frame_of_win(ev->window)))
- write_event("ClientClick 0x%x %d\n", f->client->win, ev->button);
-}
-
-static void
-buttonpress(XEvent *e) {
- XButtonPressedEvent *ev;
- Frame *f;
-
- ev = &e->xbutton;
- if((f = frame_of_win(ev->window))) {
- if((ev->state & def.mod) == def.mod) {
- switch(ev->button) {
- case Button1:
- do_mouse_resize(f->client, False, CENTER);
- focus(f->client, True);
- frame_to_top(f);
- focus(f->client, True);
- break;
- case Button3:
- do_mouse_resize(f->client, False,
- quadrant(&f->rect, ev->x_root, ev->y_root));
- frame_to_top(f);
- focus(f->client, True);
- break;
- default: break;
- XAllowEvents(blz.dpy, ReplayPointer, ev->time);
- }
- }else{
- if(ev->button == Button1) {
- if(frame_to_top(f))
- restack_view(f->view);
-
- if(ptinrect(ev->x, ev->y, &f->grabbox))
- do_mouse_resize(f->client, True, CENTER);
- else if(!ev->subwindow && !ptinrect(ev->x, ev->y, &f->titlebar))
- do_mouse_resize(f->client, False, quadrant(&f->rect, ev->x_root, ev->y_root));
-
- if(f->client != sel_client())
- focus(f->client, True);
- }
- if(ev->subwindow)
- XAllowEvents(blz.dpy, ReplayPointer, ev->time);
- else {
- /* Ungrab so a menu can receive events before the button is released */
- XUngrabPointer(blz.dpy, ev->time);
- XSync(blz.dpy, False);
-
- write_event("ClientMouseDown 0x%x %d\n", f->client->win, ev->button);
- }
- }
- }else
- XAllowEvents(blz.dpy, ReplayPointer, ev->time);
-}
-
-static void
-configurerequest(XEvent *e) {
- XConfigureRequestEvent *ev;
- XWindowChanges wc;
- XRectangle *frect;
- Client *c;
- Frame *f;
-
- ev = &e->xconfigurerequest;
- c = client_of_win(ev->window);
- if(c) {
- f = c->sel;
- gravitate_client(c, True);
- if(ev->value_mask & CWX)
- c->rect.x = ev->x;
- if(ev->value_mask & CWY)
- c->rect.y = ev->y;
- if(ev->value_mask & CWWidth)
- c->rect.width = ev->width;
- if(ev->value_mask & CWHeight)
- c->rect.height = ev->height;
- if(ev->value_mask & CWBorderWidth)
- c->border = ev->border_width;
- gravitate_client(c, False);
-
- if((c->rect.height == screen->rect.height)
- && (c->rect.width == screen->rect.width)) {
- c->fullscreen = True;
- if(c->sel) {
- if(!c->sel->area->floating)
- send_to_area(c->sel->view->area, c->sel);
- focus_client(c);
- restack_view(c->sel->view);
- }
- }
-
- if(c->sel->area->floating)
- frect=&c->sel->rect;
- else
- frect=&c->sel->revert;
-
- *frect = c->rect;
- frect->y -= labelh(&def.font);
- frect->x -= def.border;
- frect->width += 2 * def.border;
- frect->height += frame_delta_h();
-
- if(c->sel->area->floating || c->fullscreen)
- resize_client(c, frect);
- else
- configure_client(c);
- }else{
- wc.x = ev->x;
- wc.y = ev->y;
- wc.width = ev->width;
- wc.height = ev->height;
- wc.border_width = ev->border_width;
- wc.sibling = ev->above;
- wc.stack_mode = ev->detail;
- ev->value_mask &= ~(CWStackMode|CWSibling);
- XConfigureWindow(blz.dpy, ev->window, ev->value_mask, &wc);
- XSync(blz.dpy, False);
- }
-}
-
-static void
-destroynotify(XEvent *e) {
- XDestroyWindowEvent *ev;
- Client *c;
-
- ev = &e->xdestroywindow;
- if((c = client_of_win(ev->window)))
- destroy_client(c);
-}
-
-static void
-enternotify(XEvent *e) {
- XCrossingEvent *ev;
- Client *c;
- Frame *f;
-
- ev = &e->xcrossing;
- if(ev->mode != NotifyNormal)
- return;
-
- if((c = client_of_win(ev->window))) {
- if(ev->detail != NotifyInferior) {
- if(screen->focus != c) {
- if(verbose) fprintf(stderr, "enter_notify(c) => %s\n", c->name);
- focus(c, False);
- }
- set_cursor(c, cursor[CurNormal]);
- }else if(verbose) fprintf(stderr, "enter_notify(c[NotifyInferior]) => %s\n", c->name);
- }
- else if((f = frame_of_win(ev->window))) {
- if(screen->focus != c) {
- if(verbose) fprintf(stderr, "enter_notify(f) => %s\n", f->client->name);
- if(f->area->floating || !f->collapsed)
- focus(f->client, False);
- }
- set_frame_cursor(f, ev->x, ev->y);
- }
- else if(ev->window == blz.root) {
- sel_screen = True;
- draw_frames();
- }
-}
-
-static void
-leavenotify(XEvent *e) {
- XCrossingEvent *ev;
-
- ev = &e->xcrossing;
- if((ev->window == blz.root) && !ev->same_screen) {
- sel_screen = True;
- draw_frames();
- }
-}
-
-void
-print_focus(Client *c, char *to) {
- if(verbose) {
- fprintf(stderr, "screen->focus: %p => %p\n",
- screen->focus, c);
- fprintf(stderr, "\t%s => %s\n",
- screen->focus ? screen->focus->name : "<nil>",
- to);
- }
-}
-
-static void
-focusin(XEvent *e) {
- XFocusChangeEvent *ev;
- Client *c, *old;
- XEvent me;
-
- ev = &e->xfocus;
- /* Yes, we're focusing in on nothing, here. */
- if(ev->detail == NotifyDetailNone) {
- XSetInputFocus(blz.dpy, screen->barwin, RevertToParent, CurrentTime);
- return;
- }
-
- if(!((ev->detail == NotifyNonlinear)
- ||(ev->detail == NotifyNonlinearVirtual)
- ||(ev->detail == NotifyVirtual)
- ||(ev->detail == NotifyInferior)
- ||(ev->detail == NotifyAncestor)))
- return;
- if((ev->mode == NotifyWhileGrabbed)
- && (screen->hasgrab != &c_root))
- return;
-
- old = screen->focus;
- c = client_of_win(ev->window);
- if(c) {
- print_focus(c, c->name);
- if(ev->mode == NotifyGrab)
- screen->hasgrab = c;
- screen->focus = c;
- if(c != old) {
- update_client_grab(c);
- if(c->sel)
- draw_frame(c->sel);
- if(old && old->sel)
- draw_frame(old->sel);
- }
- }else if(ev->window == screen->barwin) {
- print_focus(nil, "<nil>");
- screen->focus = nil;
- }else if(ev->mode == NotifyGrab) {
- if(ev->window == blz.root)
- if(XCheckMaskEvent(blz.dpy, KeyPressMask, &me)) {
- /* wmii has grabbed focus */
- screen->hasgrab = &c_root;
- dispatch_event(&me);
- return;
- }
- /* Some unmanaged window has grabbed focus */
- if((c = screen->focus)) {
- print_focus(&c_magic, "<magic>");
- screen->focus = &c_magic;
- if(c->sel)
- draw_frame(c->sel);
- }
- }
-}
-
-static void
-focusout(XEvent *e) {
- XFocusChangeEvent *ev;
- Client *c;
-
- ev = &e->xfocus;
- if(!((ev->detail == NotifyNonlinear)
- ||(ev->detail == NotifyNonlinearVirtual)))
- return;
- if(ev->mode == NotifyUngrab)
- screen->hasgrab = nil;
-
- c = client_of_win(ev->window);
- if(c) {
- if((ev->mode == NotifyWhileGrabbed)
- && (screen->hasgrab != &c_root)) {
- if((screen->focus)
- && (screen->hasgrab != screen->focus))
- screen->hasgrab = screen->focus;
- if(screen->hasgrab == c)
- return;
- }else if(ev->mode != NotifyGrab) {
- if(screen->focus == c) {
- print_focus(&c_magic, "<magic>");
- screen->focus = &c_magic;
- }
- update_client_grab(c);
- if(c->sel)
- draw_frame(c->sel);
- }
- }
-}
-
-static void
-expose(XEvent *e) {
- XExposeEvent *ev;
- static Frame *f;
-
- ev = &e->xexpose;
- if(ev->count == 0) {
- if(ev->window == screen->barwin)
- draw_bar(screen);
- else if((f = frame_of_win(ev->window)))
- draw_frame(f);
- }
-}
-
-static void
-keypress(XEvent *e) {
- XKeyEvent *ev;
-
- ev = &e->xkey;
- ev->state &= valid_mask;
- if(ev->window == blz.root)
- kpress(blz.root, ev->state, (KeyCode) ev->keycode);
-}
-
-static void
-mappingnotify(XEvent *e) {
- XMappingEvent *ev;
-
- ev = &e->xmapping;
- XRefreshKeyboardMapping(ev);
- if(ev->request == MappingKeyboard)
- update_keys();
-}
-
-static void
-maprequest(XEvent *e) {
- XMapRequestEvent *ev;
- static XWindowAttributes wa;
-
- ev = &e->xmaprequest;
- if(!XGetWindowAttributes(blz.dpy, ev->window, &wa))
- return;
- if(wa.override_redirect) {
- XSelectInput(blz.dpy, ev->window,
- (StructureNotifyMask | PropertyChangeMask));
- return;
- }
- if(!client_of_win(ev->window))
- manage_client(create_client(ev->window, &wa));
-}
-
-static void
-motionnotify(XEvent *e) {
- XMotionEvent *ev;
- Frame *f;
-
- ev = &e->xmotion;
- if((f = frame_of_win(ev->window)))
- set_frame_cursor(f, ev->x, ev->y);
-}
-
-static void
-propertynotify(XEvent *e) {
- XPropertyEvent *ev;
- Client *c;
-
- ev = &e->xproperty;
- if(ev->state == PropertyDelete)
- return; /* ignore */
- if((c = client_of_win(ev->window)))
- prop_client(c, ev->atom);
-}
-
-static void
-mapnotify(XEvent *e) {
- XMapEvent *ev;
- Client *c;
-
- ev = &e->xmap;
- if((c = client_of_win(ev->window)))
- if(c == sel_client())
- focus_client(c);
-}
-
-static void
-unmapnotify(XEvent *e) {
- XUnmapEvent *ev;
- Client *c;
-
- ev = &e->xunmap;
- if((c = client_of_win(ev->window)))
- if(ev->send_event || (c->unmapped-- == 0))
- destroy_client(c);
-}
-
-void (*handler[LASTEvent]) (XEvent *) = {
- [ButtonPress] = buttonpress,
- [ButtonRelease] = buttonrelease,
- [ConfigureRequest]=configurerequest,
- [DestroyNotify] = destroynotify,
- [EnterNotify] = enternotify,
- [Expose] = expose,
- [FocusIn] = focusin,
- [FocusOut] = focusout,
- [KeyPress] = keypress,
- [LeaveNotify] = leavenotify,
- [MapNotify] = mapnotify,
- [MapRequest] = maprequest,
- [MappingNotify] = mappingnotify,
- [MotionNotify] = motionnotify,
- [PropertyNotify]= propertynotify,
- [UnmapNotify] = unmapnotify,
-
-};
-
-void
-check_x_event(IXPConn *c) {
- XEvent ev;
- while(XPending(blz.dpy)) {
- XNextEvent(blz.dpy, &ev);
- if(verbose)
- printevent(&ev);
- dispatch_event(&ev);
- XPending(blz.dpy);
- }
-}
diff -r 7ce25d709bbe -r de2320e9f616 frame.c
--- a/frame.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-/* Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include "wmii.h"
-
-Frame *
-create_frame(Client *c, View *v) {
- static ushort id = 1;
- Frame *f = emallocz(sizeof(Frame));
-
- f->id = id++;
- f->client = c;
- f->view = v;
- if(c->sel) {
- f->revert = c->sel->revert;
- f->rect = c->sel->rect;
- }
- else{
- c->sel = f;
- f->revert = f->rect = c->rect;
- f->revert.width = f->rect.width += 2 * def.border;
- f->revert.height = f->rect.height += frame_delta_h();
- }
- f->collapsed = False;
-
- return f;
-}
-
-void
-remove_frame(Frame *f) {
- Area *a;
- Frame **ft;
-
- a = f->area;
- for(ft = &a->frame; *ft; ft=&(*ft)->anext)
- if(*ft == f) break;
- *ft = f->anext;
-
- if(a->floating) {
- for(ft = &a->stack; *ft; ft=&(*ft)->snext)
- if(*ft == f) break;
- *ft = f->snext;
- }
-}
-
-void
-insert_frame(Frame *pos, Frame *f, Bool before) {
- Frame *ft, **p;
- Area *a = f->area;
-
- if(before) {
- for(ft=a->frame; ft; ft=ft->anext)
- if(ft->anext == pos) break;
- pos=ft;
- }
- p = &a->frame;
- if(pos)
- p = &pos->anext;
- f->anext = *p;
- *p = f;
-
- if(a->floating) {
- f->snext = a->stack;
- a->stack = f;
- }
-}
-
-void
-frame2client(XRectangle *r) {
- r->width = max(r->width - def.border * 2, 1);
- r->height = max(r->height - frame_delta_h(), 1);
-}
-
-void
-client2frame(XRectangle *r) {
- r->width += def.border * 2;
- r->height += frame_delta_h();
-}
-
-void
-resize_frame(Frame *f, XRectangle *r) {
- BlitzAlign stickycorner;
- Client *c;
-
- c = f->client;
- stickycorner = get_sticky(&f->rect, r);
-
- f->rect = *r;
- f->crect = *r;
- apply_sizehints(c, &f->crect, f->area->floating, True, stickycorner);
-
- if(f->area->floating)
- f->rect = f->crect;
-
- frame2client(&f->crect);
-
- if(f->crect.height < labelh(&def.font))
- f->collapsed = True;
- else
- f->collapsed = False;
-
- if(f->crect.width < labelh(&def.font)) {
- f->rect.width = frame_delta_h();
- f->collapsed = True;
- }
-
- if(f->collapsed) {
- f->rect.height = labelh(&def.font);
- f->crect = f->rect;
- }
- f->crect.y = labelh(&def.font);
- f->crect.x = (f->rect.width - f->crect.width) / 2;
-
-
- if(f->area->floating) {
- if(c->fullscreen) {
- f->crect.width = screen->rect.width;
- f->crect.height = screen->rect.height;
- f->rect = f->crect;
- client2frame(&f->rect);
- f->rect.x = -def.border;
- f->rect.y = -labelh(&def.font);
- }else
- check_frame_constraints(&f->rect);
- }
-}
-
-void
-set_frame_cursor(Frame *f, int x, int y) {
- XRectangle r;
- Cursor cur;
-
- if(!ptinrect(x, y, &f->titlebar)
- &&!ptinrect(x, y, &f->crect)) {
- r = f->rect;
- r.x = 0;
- r.y = 0;
- cur = cursor_of_quad(quadrant(&r, x, y));
- set_cursor(f->client, cur);
- }else
- set_cursor(f->client, cursor[CurNormal]);
-}
-
-Bool
-frame_to_top(Frame *f) {
- Frame **tf;
- Area *a;
-
- a = f->area;
- if(!a->floating || f == a->stack)
- return False;
- for(tf=&a->stack; *tf; tf=&(*tf)->snext)
- if(*tf == f) break;
- *tf = f->snext;
- f->snext = a->stack;
- a->stack = f;
- update_client_grab(f->client);
- return True;
-}
-
-void
-swap_frames(Frame *fa, Frame *fb) {
- XRectangle trect;
- Area *a;
- Frame **fp_a, **fp_b, *ft;
-
- if(fa == fb) return;
-
- a = fa->area;
- for(fp_a = &a->frame; *fp_a; fp_a = &(*fp_a)->anext)
- if(*fp_a == fa) break;
- a = fb->area;
- for(fp_b = &a->frame; *fp_b; fp_b = &(*fp_b)->anext)
- if(*fp_b == fb) break;
-
- if(fa->anext == fb) {
- *fp_a = fb;
- fa->anext = fb->anext;
- fb->anext = fa;
- } else if(fb->anext == fa) {
- *fp_b = fa;
- fb->anext = fa->anext;
- fa->anext = fb;
- } else {
- *fp_a = fb;
- *fp_b = fa;
- ft = fb->anext;
- fb->anext = fa->anext;
- fa->anext = ft;
- }
-
- if(fb->area->sel == fb)
- fb->area->sel = fa;
- if(fa->area->sel == fa)
- fa->area->sel = fb;
-
- fb->area = fa->area;
- fa->area = a;
-
- trect = fa->rect;
- fa->rect = fb->rect;
- fb->rect = trect;
-}
-
-void
-focus_frame(Frame *f, Bool restack) {
- Frame *old, *old_in_a;
- View *v;
- Area *a, *old_a;
-
- a = f->area;
- v = f->view;
- old = v->sel->sel;
- old_a = v->sel;
- old_in_a = a->sel;
-
- a->sel = f;
-
- if(a != old_a)
- focus_area(f->area);
-
- if(v != screen->sel)
- return;
-
- focus_client(f->client);
-
- if(!a->floating
- && ((a->mode == Colstack) || (a->mode == Colmax)))
- arrange_column(a, False);
-
- if((f != old)
- && (f->area == old_a))
- write_event("ClientFocus 0x%x\n", f->client->win);
-
- if(restack)
- restack_view(v);
-}
-
-int
-frame_delta_h() {
- return def.border + labelh(&def.font);
-}
-
-void
-draw_frame(Frame *f) {
- BlitzBrush br = { 0 };
- Frame *tf;
-
- if(f->view != screen->sel)
- return;
-
- br.blitz = &blz;
- br.font = &def.font;
- br.drawable = pmap;
- br.gc = f->client->gc;
- if(f->client == screen->focus)
- br.color = def.focuscolor;
- else
- br.color = def.normcolor;
- if(!f->area->floating && f->area->mode == Colmax)
- for(tf = f->area->frame; tf; tf=tf->anext)
- if(tf->client == screen->focus) {
- br.color = def.focuscolor;
- break;
- }
-
- br.rect = f->rect;
- br.rect.x = 0;
- br.rect.y = 0;
- draw_tile(&br);
-
- br.rect.x += def.font.height - 3;
- br.rect.width -= br.rect.x;
- br.rect.height = labelh(&def.font);
- draw_label(&br, f->client->name);
-
- br.border = 1;
- br.rect.width += br.rect.x;
- br.rect.x = 0;
- f->titlebar.x = br.rect.x + 3;
- f->titlebar.height = br.rect.height - 3;
- f->titlebar.y = br.rect.y + 3;
- f->titlebar.width = br.rect.width - 6;
- draw_border(&br);
- br.rect.height = f->rect.height;
- if(def.border)
- draw_border(&br);
-
- if(f->client->urgent)
- br.color.bg = br.color.fg;
- br.rect.x = 2;
- br.rect.y = 2;
- br.rect.height = labelh(&def.font) - 4;
- br.rect.width = def.font.height - 3;
- f->grabbox = br.rect;
- draw_tile(&br);
-
- XCopyArea(
- /* display */ blz.dpy,
- /* src */ pmap,
- /* dest */ f->client->framewin,
- /* gc */ f->client->gc,
- /* x, y */ 0, 0,
- /* width */ f->rect.width,
- /* height */ f->rect.height,
- /* dest_x */ 0,
- /* dest_y */ 0
- );
- XSync(blz.dpy, False);
-}
-
-void
-draw_frames() {
- Client *c;
-
- for(c=client; c; c=c->next)
- if(c->sel && c->sel->view == screen->sel)
- draw_frame(c->sel);
-}
-
-void
-check_frame_constraints(XRectangle *rect) {
- int max_height;
- int barheight;
-
- barheight = screen->brect.height;
- max_height = screen->rect.height - barheight;
-
- if(rect->height > max_height)
- rect->height = max_height;
- if(rect->width > screen->rect.width)
- rect->width = screen->rect.width;
- if(rect->x + barheight > screen->rect.width)
- rect->x = screen->rect.width - barheight;
- if(rect->y + barheight > max_height)
- rect->y = max_height - barheight;
- if(r_east(rect) < barheight)
- rect->x = barheight - rect->width;
- if(r_south(rect) < barheight)
- rect->y = barheight - rect->height;
-}
diff -r 7ce25d709bbe -r de2320e9f616 fs.c
--- a/fs.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,966 +0,0 @@
-/* Copyright ©2006 Kris Maglione <fbsdaemon at gmail dot com>
- * See LICENSE file for license details.
- */
-#include <assert.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "wmii.h"
-
-
-/* Datatypes: */
-/**************/
-typedef struct Dirtab Dirtab;
-struct Dirtab {
- char *name;
- uchar qtype;
- uint type;
- uint perm;
-};
-
-typedef struct FidLink FidLink;
-struct FidLink {
- FidLink *next;
- Fid *fid;
-};
-
-typedef struct FileId FileId;
-struct FileId {
- FileId *next;
- union {
- void *ref;
- char *buf;
- Bar *bar;
- Bar **bar_p;
- View *view;
- Client *client;
- Ruleset *rule;
- BlitzColor *col;
- } content;
- uint id;
- uint index;
- Dirtab tab;
- ushort nref;
-};
-
-/* Constants */
-/*************/
-enum { /* Dirs */
- FsRoot, FsDClient, FsDClients, FsDBars,
- FsDTag, FsDTags,
- /* Files */
- FsFBar, FsFCctl, FsFColRules,
- FsFCtags, FsFEvent, FsFKeys, FsFRctl,
- FsFTagRules, FsFTctl, FsFTindex,
- FsFprops
-};
-
-/* Error messages */
-static char
- Enoperm[] = "permission denied",
- Enofile[] = "file not found",
- Ebadvalue[] = "bad value",
- Einterrupted[] = "interrupted",
- Ebadcmd[] = "bad command";
-
-/* Macros */
-#define QID(t, i) (((vlong)((t)&0xFF)<<32)|((i)&0xFFFFFFFF))
-
-/* Global Vars */
-/***************/
-FileId *free_fileid;
-P9Req *pending_event_reads;
-P9Req *outgoing_event_reads;
-FidLink *pending_event_fids;
-P9Srv p9srv = {
- .open= fs_open,
- .walk= fs_walk,
- .read= fs_read,
- .stat= fs_stat,
- .write= fs_write,
- .clunk= fs_clunk,
- .flush= fs_flush,
- .attach=fs_attach,
- .create=fs_create,
- .remove=fs_remove,
- .freefid=fs_freefid
-};
-
-/* ad-hoc file tree. Empty names ("") indicate dynamic entries to be filled
- * in by lookup_file */
-static Dirtab
-dirtab_root[]= {{".", P9QTDIR, FsRoot, 0500|P9DMDIR },
- {"rbar", P9QTDIR, FsDBars, 0700|P9DMDIR },
- {"lbar", P9QTDIR, FsDBars, 0700|P9DMDIR },
- {"client", P9QTDIR, FsDClients, 0500|P9DMDIR },
- {"tag", P9QTDIR, FsDTags, 0500|P9DMDIR },
- {"ctl", P9QTAPPEND, FsFRctl, 0600|P9DMAPPEND },
- {"colrules", P9QTFILE, FsFColRules, 0600 },
- {"event", P9QTFILE, FsFEvent, 0600 },
- {"keys", P9QTFILE, FsFKeys, 0600 },
- {"tagrules", P9QTFILE, FsFTagRules, 0600 },
- {nil}},
-dirtab_clients[]={{".", P9QTDIR, FsDClients, 0500|P9DMDIR },
- {"", P9QTDIR, FsDClient, 0500|P9DMDIR },
- {nil}},
-dirtab_client[]= {{".", P9QTDIR, FsDClient, 0500|P9DMDIR },
- {"ctl", P9QTAPPEND, FsFCctl, 0600|P9DMAPPEND },
- {"tags", P9QTFILE, FsFCtags, 0600 },
- {"props", P9QTFILE, FsFprops, 0400 },
- {nil}},
-dirtab_bars[]= {{".", P9QTDIR, FsDBars, 0700|P9DMDIR },
- {"", P9QTFILE, FsFBar, 0600 },
- {nil}},
-dirtab_tags[]= {{".", P9QTDIR, FsDTags, 0500|P9DMDIR },
- {"", P9QTDIR, FsDTag, 0500|P9DMDIR },
- {nil}},
-dirtab_tag[]= {{".", P9QTDIR, FsDTag, 0500|P9DMDIR },
- {"ctl", P9QTAPPEND, FsFTctl, 0600|P9DMAPPEND },
- {"index", P9QTFILE, FsFTindex, 0400 },
- {nil}};
-/* Writing the lists separately and using an array of their references
- * removes the need for casting and allows for C90 conformance,
- * since otherwise we would need to use compound literals */
-static Dirtab *dirtab[] = {
- [FsRoot] = dirtab_root,
- [FsDBars] = dirtab_bars,
- [FsDClients] = dirtab_clients,
- [FsDClient] = dirtab_client,
- [FsDTags] = dirtab_tags,
- [FsDTag] = dirtab_tag,
-};
-
-/* Utility Functions */
-/*********************/
-
-/* get_file/free_file save and reuse old FileId structs
- * since so many of them are needed for so many
- * purposes */
-static FileId *
-get_file() {
- FileId *temp;
- if(!free_fileid) {
- uint i = 15;
- temp = emallocz(sizeof(FileId) * i);
- for(; i; i--) {
- temp->next = free_fileid;
- free_fileid = temp++;
- }
- }
- temp = free_fileid;
- free_fileid = temp->next;
- temp->nref = 1;
- temp->next = nil;
- return temp;
-}
-
-static void
-free_file(FileId *f) {
- if(--f->nref)
- return;
- free(f->tab.name);
- f->next = free_fileid;
- free_fileid = f;
-}
-
-/* This function's name belies it's true purpose. It increases
- * the reference counts of the FileId list */
-static void
-clone_files(FileId *f) {
- for(; f; f=f->next)
- assert(f->nref++);
-}
-
-/* This should be moved to libixp */
-static void
-write_buf(P9Req *r, char *buf, uint len) {
- if(r->ifcall.offset >= len)
- return;
-
- len -= r->ifcall.offset;
- if(len > r->ifcall.count)
- len = r->ifcall.count;
- r->ofcall.data = emalloc(len);
- memcpy(r->ofcall.data, buf + r->ifcall.offset, len);
- r->ofcall.count = len;
-}
-
-/* This should be moved to libixp */
-void
-write_to_buf(P9Req *r, void *buf, uint *len, uint max) {
- uint offset, count;
-
- offset = (r->fid->omode&P9OAPPEND) ? *len : r->ifcall.offset;
- if(offset > *len || r->ifcall.count == 0) {
- r->ofcall.count = 0;
- return;
- }
-
- count = r->ifcall.count;
- if(max && (count > max - offset))
- count = max - offset;
-
- *len = offset + count;
-
- if(max == 0) {
- *(void **)buf = erealloc(*(void **)buf, *len + 1);
- buf = *(void **)buf;
- }
-
- memcpy((uchar*)buf + offset, r->ifcall.data, count);
- r->ofcall.count = count;
- ((char *)buf)[offset+count] = '\0';
-}
-
-/* This should be moved to libixp */
-void
-data_to_cstring(P9Req *r) {
- uint i;
- i = r->ifcall.count;
- if(!i || r->ifcall.data[i - 1] != '\n')
- r->ifcall.data = erealloc(r->ifcall.data, ++i);
- assert(r->ifcall.data);
- r->ifcall.data[i - 1] = '\0';
-}
-
-char *
-message_root(char *message)
-{
- uint n;
-
- if(!strchr(message, ' ')) {
- snprintf(buffer, BUFFER_SIZE, "%s ", message);
- message = buffer;
- }
- if(!strcmp(message, "quit "))
- srv.running = 0;
- else if(!strncmp(message, "exec ", 5)) {
- srv.running = 0;
- execstr = estrdup(&message[5]);
- message += strlen(message);
- }
- else if(!strncmp(message, "view ", 5))
- select_view(&message[5]);
- else if(!strncmp(message, "selcolors ", 10)) {
- fprintf(stderr, "wmii: warning: selcolors have been removed\n");
- return Ebadcmd;
- }
- else if(!strncmp(message, "focuscolors ", 12)) {
- message += 12;
- n = strlen(message);
- return parse_colors(&message, (int *)&n, &def.focuscolor);
- }
- else if(!strncmp(message, "normcolors ", 11)) {
- message += 11;
- n = strlen(message);
- return parse_colors(&message, (int *)&n, &def.normcolor);
- }
- else if(!strncmp(message, "font ", 5)) {
- message += 5;
- free(def.font.fontstr);
- def.font.fontstr = estrdup(message);
- loadfont(&blz, &def.font);
- resize_bar(screen);
- }
- else if(!strncmp(message, "border ", 7)) {
- message += 7;
- n = (uint)strtol(message, &message, 10);
- if(*message)
- return Ebadvalue;
- def.border = n;
- }
- else if(!strncmp(message, "grabmod ", 8)) {
- message += 8;
- ulong mod;
- mod = mod_key_of_str(message);
- if(!(mod & (Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)))
- return Ebadvalue;
- strncpy(def.grabmod, message, sizeof(def.grabmod));
- def.mod = mod;
- if(view)
- restack_view(screen->sel);
- }
- else
- return Ebadcmd;
- return nil;
-}
-
-char *
-read_root_ctl() {
- uint i = 0;
- if(screen->sel)
- i += snprintf(&buffer[i], (BUFFER_SIZE - i), "view %s\n", screen->sel->name);
- i += snprintf(&buffer[i], (BUFFER_SIZE - i), "focuscolors %s\n", def.focuscolor.colstr);
- i += snprintf(&buffer[i], (BUFFER_SIZE - i), "normcolors %s\n", def.normcolor.colstr);
- i += snprintf(&buffer[i], (BUFFER_SIZE - i), "font %s\n", def.font.fontstr);
- i += snprintf(&buffer[i], (BUFFER_SIZE - i), "grabmod %s\n", def.grabmod);
- i += snprintf(&buffer[i], (BUFFER_SIZE - i), "border %d\n", def.border);
- return buffer;
-}
-
-
-void
-respond_event(P9Req *r) {
- FileId *f = r->fid->aux;
- if(f->content.buf) {
- r->ofcall.data = (void *)f->content.buf;
- r->ofcall.count = strlen(f->content.buf);
- respond(r, nil);
- f->content.buf = nil;
- }else{
- r->aux = pending_event_reads;
- pending_event_reads = r;
- }
-}
-
-void
-write_event(char *format, ...) {
- uint len, slen;
- va_list ap;
- FidLink *f;
- FileId *fi;
- P9Req *req;
-
- va_start(ap, format);
- vsnprintf(buffer, BUFFER_SIZE, format, ap);
- va_end(ap);
- if(!(len = strlen(buffer)))
- return;
- for(f=pending_event_fids; f; f=f->next) {
- fi = f->fid->aux;
- slen = fi->content.buf ? strlen(fi->content.buf) : 0;
- fi->content.buf = (char *) erealloc(fi->content.buf, slen + len + 1);
- (fi->content.buf)[slen] = '\0';
- strcat(fi->content.buf, buffer);
- }
- outgoing_event_reads = pending_event_reads;
- pending_event_reads = nil;
- while((req = outgoing_event_reads)) {
- outgoing_event_reads = outgoing_event_reads->aux;
- respond_event(req);
- }
-}
-
-static void
-dostat(Stat *s, uint len, FileId *f) {
- s->type = 0;
- s->dev = 0;
- s->qid.path = QID(f->tab.type, f->id);
- s->qid.version = 0;
- s->qid.type = f->tab.qtype;
- s->mode = f->tab.perm;
- s->atime = time(nil);
- s->mtime = time(nil);
- s->length = len;
- s->name = f->tab.name;
- s->uid = user;
- s->gid = user;
- s->muid = user;
-}
-
-/* lookup_file */
-/***************/
-/* All lookups and directory organization should be performed through
- * lookup_file, mostly through the dirtabs[] tree. */
-static FileId *
-lookup_file(FileId *parent, char *name)
-{
- FileId *ret, *file, **last;
- Dirtab *dir;
- Client *c;
- View *v;
- Bar *b;
- uint id;
-
- if(!(parent->tab.perm & P9DMDIR))
- return nil;
- dir = dirtab[parent->tab.type];
- last = &ret;
- ret = nil;
- for(; dir->name; dir++) {
- /* Dynamic dirs */
- if(!*dir->name) { /* strlen(dir->name) == 0 */
- switch(parent->tab.type) {
- case FsDClients:
- if(!name || !strcmp(name, "sel")) {
- if((c = sel_client())) {
- file = get_file();
- *last = file;
- last = &file->next;
- file->content.client = c;
- file->id = c->win;
- file->index = c->win;
- file->tab = *dir;
- file->tab.name = estrdup("sel");
- }if(name) goto LastItem;
- }
- if(name) {
- id = (uint)strtol(name, &name, 16);
- if(*name) goto NextItem;
- }
- for(c=client; c; c=c->next) {
- if(!name || c->win == id) {
- file = get_file();
- *last = file;
- last = &file->next;
- file->content.client = c;
- file->id = c->win;
- file->index = c->win;
- file->tab = *dir;
- file->tab.name = emallocz(16);
- snprintf(file->tab.name, 16, "0x%x", (uint)c->win);
- if(name) goto LastItem;
- }
- }
- break;
- case FsDTags:
- if(!name || !strcmp(name, "sel")) {
- if(screen->sel) {
- file = get_file();
- *last = file;
- last = &file->next;
- file->content.view = screen->sel;
- file->id = screen->sel->id;
- file->tab = *dir;
- file->tab.name = estrdup("sel");
- }if(name) goto LastItem;
- }
- for(v=view; v; v=v->next) {
- if(!name || !strcmp(name, v->name)) {
- file = get_file();
- *last = file;
- last = &file->next;
- file->content.view = v;
- file->id = v->id;
- file->tab = *dir;
- file->tab.name = estrdup(v->name);
- if(name) goto LastItem;
- }
- }
- break;
- case FsDBars:
- for(b=*parent->content.bar_p; b; b=b->next) {
- if(!name || !strcmp(name, b->name)) {
- file = get_file();
- *last = file;
- last = &file->next;
- file->content.bar = b;
- file->id = b->id;
- file->tab = *dir;
- file->tab.name = estrdup(b->name);
- if(name) goto LastItem;
- }
- }
- break;
- }
- }else /* Static dirs */
- if(!name || !strcmp(name, dir->name)) {
- file = get_file();
- *last = file;
- last = &file->next;
- file->id = 0;
- file->content.ref = parent->content.ref;
- file->index = parent->index;
- file->tab = *dir;
- file->tab.name = estrdup(file->tab.name);
- /* Special considerations: */
- switch(file->tab.type) {
- case FsDBars:
- if(!strcmp(file->tab.name, "lbar"))
- file->content.bar_p = &screen[0].bar[BarLeft];
- else
- file->content.bar_p = &screen[0].bar[BarRight];
- break;
- case FsFColRules:
- file->content.rule = &def.colrules;
- break;
- case FsFTagRules:
- file->content.rule = &def.tagrules;
- break;
- }
- if(name) goto LastItem;
- }
- NextItem:
- continue;
- }
-LastItem:
- *last = nil;
- return ret;
-}
-
-Bool
-verify_file(FileId *f) {
- FileId *nf;
-
- if(!f->next)
- return True;
- if(verify_file(f->next)) {
- nf = lookup_file(f->next, f->tab.name);
- if(nf) {
- free_file(nf);
- return True;
- }
- }
- return False;
-}
-
-/* Service Functions */
-/*********************/
-void
-fs_attach(P9Req *r) {
- FileId *f = get_file();
- f->tab = dirtab[FsRoot][0];
- f->tab.name = estrdup("/");
- f->content.ref = nil; /* shut up valgrind */
- r->fid->aux = f;
- r->fid->qid.type = f->tab.qtype;
- r->fid->qid.path = QID(f->tab.type, 0);
- r->ofcall.qid = r->fid->qid;
- respond(r, nil);
-}
-
-void
-fs_walk(P9Req *r) {
- FileId *f, *nf;
- int i;
-
- f = r->fid->aux;
- clone_files(f);
- for(i=0; i < r->ifcall.nwname; i++) {
- if(!strcmp(r->ifcall.wname[i], "..")) {
- if(f->next) {
- nf=f;
- f=f->next;
- free_file(nf);
- }
- }else{
- nf = lookup_file(f, r->ifcall.wname[i]);
- if(!nf)
- break;
- assert(!nf->next);
- if(strcmp(r->ifcall.wname[i], ".")) {
- nf->next = f;
- f = nf;
- }
- }
- r->ofcall.wqid[i].type = f->tab.qtype;
- r->ofcall.wqid[i].path = QID(f->tab.type, f->id);
- }
- /* There should be a way to do this on freefid() */
- if(i < r->ifcall.nwname) {
- while((nf = f)) {
- f=f->next;
- free_file(nf);
- }
- respond(r, Enofile);
- return;
- }
- /* Remove refs for r->fid if no new fid */
- if(r->ifcall.fid == r->ifcall.newfid) {
- nf = r->fid->aux;
- r->fid->aux = f;
- while((f = nf)) {
- nf = nf->next;
- free_file(f);
- }
- }else
- r->newfid->aux = f;
- r->ofcall.nwqid = i;
- respond(r, nil);
-}
-
-uint
-fs_size(FileId *f) {
- switch(f->tab.type) {
- default:
- return 0;
- case FsFColRules:
- case FsFTagRules:
- return f->content.rule->size;
- case FsFKeys:
- return def.keyssz;
- case FsFCtags:
- return strlen(f->content.client->tags);
- case FsFprops:
- return strlen(f->content.client->props);
- }
-}
-
-void
-fs_stat(P9Req *r) {
- Stat s;
- int size;
- uchar *buf;
- FileId *f = r->fid->aux;
-
- if(!verify_file(f)) {
- respond(r, Enofile);
- return;
- }
-
- dostat(&s, fs_size(f), f);
- r->ofcall.nstat = size = ixp_sizeof_stat(&s);
- buf = emallocz(size);
- r->ofcall.stat = buf;
- ixp_pack_stat(&buf, &size, &s);
- respond(r, nil);
-}
-
-void
-fs_read(P9Req *r) {
- char *buf;
- FileId *f, *tf;
- int n, offset;
- int size;
-
- offset = 0;
- f = r->fid->aux;
-
- if(!verify_file(f)) {
- respond(r, Enofile);
- return;
- }
-
- if(f->tab.perm & P9DMDIR && f->tab.perm & 0400) {
- Stat s;
- offset = 0;
- size = r->ifcall.count;
- buf = emallocz(size);
- r->ofcall.data = buf;
- tf = f = lookup_file(f, nil);
- /* Note: f->tab.name == "." so we skip it */
- for(f=f->next; f; f=f->next) {
- dostat(&s, fs_size(f), f);
- n = ixp_sizeof_stat(&s);
- if(offset >= r->ifcall.offset) {
- if(size < n)
- break;
- ixp_pack_stat((uchar **)&buf, &size, &s);
- }
- offset += n;
- }
- while((f = tf)) {
- tf=tf->next;
- free_file(f);
- }
- r->ofcall.count = r->ifcall.count - size;
- respond(r, nil);
- return;
- }
- else{
- switch(f->tab.type) {
- case FsFprops:
- write_buf(r, f->content.client->props, strlen(f->content.client->props));
- respond(r, nil);
- return;
- case FsFColRules:
- case FsFTagRules:
- write_buf(r, f->content.rule->string, f->content.rule->size);
- respond(r, nil);
- return;
- case FsFKeys:
- write_buf(r, def.keys, def.keyssz);
- respond(r, nil);
- return;
- case FsFCtags:
- write_buf(r, f->content.client->tags, strlen(f->content.client->tags));
- respond(r, nil);
- return;
- case FsFTctl:
- write_buf(r, f->content.view->name, strlen(f->content.view->name));
- respond(r, nil);
- return;
- case FsFBar:
- write_buf(r, f->content.bar->buf, strlen(f->content.bar->buf));
- respond(r, nil);
- return;
- case FsFRctl:
- buf = read_root_ctl();
- write_buf(r, buf, strlen(buf));
- respond(r, nil);
- return;
- case FsFCctl:
- if(r->ifcall.offset) {
- respond(r, nil);
- return;
- }
- r->ofcall.data = emallocz(16);
- n = snprintf(r->ofcall.data, 16, "0x%x", (uint)f->index);
- assert(n >= 0);
- r->ofcall.count = n;
- respond(r, nil);
- return;
- case FsFTindex:
- buf = (char *)view_index(f->content.view);
- n = strlen(buf);
- write_buf(r, buf, n);
- respond(r, nil);
- return;
- case FsFEvent:
- respond_event(r);
- return;
- }
- }
- /* This is an assert because it should this should not be called if
- * the file is not open for reading. */
- assert(!"Read called on an unreadable file");
-}
-
-/* This function needs to be seriously cleaned up */
-void
-fs_write(P9Req *r) {
- FileId *f;
- char *errstr = nil;
- uint i;
-
- if(r->ifcall.count == 0) {
- respond(r, nil);
- return;
- }
- f = r->fid->aux;
-
- if(!verify_file(f)) {
- respond(r, Enofile);
- return;
- }
-
- switch(f->tab.type) {
- case FsFColRules:
- case FsFTagRules:
- write_to_buf(r, &f->content.rule->string, &f->content.rule->size, 0);
- respond(r, nil);
- return;
- case FsFKeys:
- write_to_buf(r, &def.keys, &def.keyssz, 0);
- respond(r, nil);
- return;
- case FsFCtags:
- data_to_cstring(r);
- apply_tags(f->content.client, r->ifcall.data);
- r->ofcall.count = r->ifcall.count;
- respond(r, nil);
- return;
- case FsFBar:
- /* XXX: This should validate after each write */
- i = strlen(f->content.bar->buf);
- write_to_buf(r, &f->content.bar->buf, &i, 279);
- r->ofcall.count = i - r->ifcall.offset;
- respond(r, nil);
- return;
- case FsFCctl:
- data_to_cstring(r);
- if((errstr = message_client(f->content.client, r->ifcall.data))) {
- respond(r, errstr);
- return;
- }
- r->ofcall.count = r->ifcall.count;
- respond(r, nil);
- return;
- case FsFTctl:
- data_to_cstring(r);
- if((errstr = message_view(f->content.view, r->ifcall.data))) {
- respond(r, errstr);
- return;
- }
- r->ofcall.count = r->ifcall.count;
- respond(r, nil);
- return;
- case FsFRctl:
- data_to_cstring(r);
- { uint n;
- char *toks[32];
- n = tokenize(toks, 32, r->ifcall.data, '\n');
- for(i = 0; i < n; i++) {
- if(errstr)
- message_root(toks[i]);
- else
- errstr = message_root(toks[i]);
- }
- }
- if(screen->sel)
- focus_view(screen, screen->sel);
- if(errstr) {
- respond(r, errstr);
- return;
- }
- r->ofcall.count = r->ifcall.count;
- respond(r, nil);
- return;
- case FsFEvent:
- if(r->ifcall.data[r->ifcall.count-1] == '\n')
- write_event("%.*s", r->ifcall.count, r->ifcall.data);
- else
- write_event("%.*s\n", r->ifcall.count, r->ifcall.data);
- r->ofcall.count = r->ifcall.count;
- respond(r, nil);
- return;
- }
- /* This is an assert because this function should not be called if
- * the file is not open for writing. */
- assert(!"Write called on an unwritable file");
-}
-
-void
-fs_open(P9Req *r) {
- FidLink *fl;
- FileId *f = r->fid->aux;
-
- if(!verify_file(f)) {
- respond(r, Enofile);
- return;
- }
-
- switch(f->tab.type) {
- case FsFEvent:
- fl = emallocz(sizeof(FidLink));
- fl->fid = r->fid;
- fl->next = pending_event_fids;
- pending_event_fids = fl;
- break;
- }
- if((r->ifcall.mode&3) == P9OEXEC) {
- respond(r, Enoperm);
- return;
- }
- if((r->ifcall.mode&3) != P9OREAD && !(f->tab.perm & 0200)) {
- respond(r, Enoperm);
- return;
- }
- if((r->ifcall.mode&3) != P9OWRITE && !(f->tab.perm & 0400)) {
- respond(r, Enoperm);
- return;
- }
- if((r->ifcall.mode&~(3|P9OAPPEND|P9OTRUNC))) {
- respond(r, Enoperm);
- return;
- }
- respond(r, nil);
-}
-
-void
-fs_create(P9Req *r) {
- FileId *f = r->fid->aux;
-
- switch(f->tab.type) {
- default:
- /* XXX: This should be taken care of by the library */
- respond(r, Enoperm);
- return;
- case FsDBars:
- if(!strlen(r->ifcall.name)) {
- respond(r, Ebadvalue);
- return;
- }
- create_bar(f->content.bar_p, r->ifcall.name);
- f = lookup_file(f, r->ifcall.name);
- if(!f) {
- respond(r, Enofile);
- return;
- }
- r->ofcall.qid.type = f->tab.qtype;
- r->ofcall.qid.path = QID(f->tab.type, f->id);
- f->next = r->fid->aux;
- r->fid->aux = f;
- respond(r, nil);
- break;
- }
-}
-
-void
-fs_remove(P9Req *r) {
- FileId *f = r->fid->aux;
-
- if(!verify_file(f)) {
- respond(r, Enofile);
- return;
- }
-
-
- switch(f->tab.type) {
- default:
- /* XXX: This should be taken care of by the library */
- respond(r, Enoperm);
- return;
- case FsFBar:
- destroy_bar(f->next->content.bar_p, f->content.bar);
- draw_bar(screen);
- respond(r, nil);
- break;
- }
-}
-
-void
-fs_clunk(P9Req *r) {
- Client *c;
- FidLink **fl, *ft;
- char *buf;
- int i;
- FileId *f = r->fid->aux;
-
- if(!verify_file(f)) {
- respond(r, nil);
- return;
- }
-
- switch(f->tab.type) {
- case FsFColRules:
- update_rules(&f->content.rule->rule, f->content.rule->string);
- break;
- case FsFTagRules:
- update_rules(&f->content.rule->rule, f->content.rule->string);
- for(c=client; c; c=c->next)
- apply_rules(c);
- update_views();
- break;
- case FsFKeys:
- update_keys();
- break;
- case FsFBar:
- buf = f->content.bar->buf;
- i = strlen(f->content.bar->buf);
- parse_colors(&buf, &i, &f->content.bar->brush.color);
- while(i > 0 && buf[i - 1] == '\n')
- buf[--i] = '\0';
- strncpy(f->content.bar->text, buf, sizeof(f->content.bar->text));
- draw_bar(screen);
- break;
- case FsFEvent:
- for(fl=&pending_event_fids; *fl; fl=&(*fl)->next)
- if((*fl)->fid == r->fid) {
- ft = *fl;
- *fl = (*fl)->next;
- f = ft->fid->aux;
- free(f->content.buf);
- free(ft);
- break;
- }
- break;
- }
- respond(r, nil);
-}
-
-void
-fs_flush(P9Req *r) {
- P9Req **i, **j;
-
- for(i=&pending_event_reads; i != &outgoing_event_reads; i=&outgoing_event_reads)
- for(j=i; *j; j=(P9Req **)&(*j)->aux)
- if(*j == r->oldreq) {
- *j = (*j)->aux;
- respond(r->oldreq, Einterrupted);
- goto done;
- }
-done:
- respond(r, nil);
-}
-
-void
-fs_freefid(Fid *f) {
- FileId *id, *tid;
-
- for(id=f->aux; id; id = tid) {
- tid = id->next;
- free_file(id);
- }
-}
diff -r 7ce25d709bbe -r de2320e9f616 geom.c
--- a/geom.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-#include "wmii.h"
-
-Bool
-ptinrect(int x, int y, XRectangle * r) {
- return (x >= r->x) && (x < r_east(r))
- && (y >= r->y) && (y < r_south(r));
-}
-
-BlitzAlign
-quadrant(XRectangle *rect, int x, int y) {
- BlitzAlign ret = 0;
- x -= rect->x;
- y -= rect->y;
-
- if(x >= rect->width * .5)
- ret |= EAST;
- if(x <= rect->width * .5)
- ret |= WEST;
- if(y <= rect->height * .5)
- ret |= NORTH;
- if(y >= rect->height * .5)
- ret |= SOUTH;
-
- return ret;
-}
-
-Cursor
-cursor_of_quad(BlitzAlign align) {
- switch(align) {
- case NEAST:
- return cursor[CurNECorner];
- case NWEST:
- return cursor[CurNWCorner];
- case SEAST:
- return cursor[CurSECorner];
- case SWEST:
- return cursor[CurSWCorner];
- default:
- return cursor[CurMove];
- }
-}
-
-/* Syntax: <x> <y> <width> <height> */
-int
-strtorect(XRectangle *r, const char *val) {
- XRectangle new;
- if (!val)
- return -1;
-
- if(sscanf(val, "%hd %hd %hu %hu", &new.x, &new.y, &new.width, &new.height) != 4)
- return -1;
-
- *r = new;
- return 0;
-}
-
-int
-r_east(XRectangle *r) {
- return r->x + r->width;
-}
-
-int
-r_south(XRectangle *r) {
- return r->y + r->height;
-}
-
-BlitzAlign
-get_sticky(XRectangle *src, XRectangle *dst) {
- BlitzAlign stickycorner = 0;
-
- if(src->x != dst->x && r_east(src) == r_east(dst))
- stickycorner |= EAST;
- else
- stickycorner |= WEST;
- if(src->y != dst->y && r_south(src) == r_south(dst))
- stickycorner |= SOUTH;
- else
- stickycorner |= NORTH;
-
- return stickycorner;
-}
diff -r 7ce25d709bbe -r de2320e9f616 img/wmii.eps
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/img/wmii.eps Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,29 @@
+%!PS-Adobe-2.0 EPSF-1.2
+%%BoundingBox: -1 0 51 27
+%%Creator: MetaPost
+%%CreationDate: 2007.02.27:1944
+%%Pages: 1
+%%EndProlog
+%%Page: 1 1
+ 0 6.23616 dtransform truncate idtransform setlinewidth pop [] 0 setdash
+ 0 setlinecap 2 setlinejoin 10 setmiterlimit
+newpath 2.83461 17.00761 moveto
+2.83461 2.83461 lineto
+14.17302 2.83461 lineto
+14.17302 17.00761 lineto
+14.17302 2.83461 lineto
+25.51143 2.83461 lineto
+25.51143 14.173 lineto
+36.84984 14.173 lineto stroke
+ 0 setlinejoin
+newpath 36.84984 14.173 moveto
+36.84984 0 lineto
+36.84984 14.173 lineto
+48.18825 14.173 lineto
+48.18825 0 lineto stroke
+newpath 36.84984 20.40916 moveto
+36.84984 26.07837 lineto stroke
+newpath 48.18825 20.40916 moveto
+48.18825 26.07837 lineto stroke
+showpage
+%%EOF
diff -r 7ce25d709bbe -r de2320e9f616 img/wmii.mp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/img/wmii.mp Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,19 @@
+beginfig(1)
+%u=0.6cm;
+u=0.2cm;
+h=3u;
+space=u;
+linecap:=butt;
+linejoin:=beveled;
+pickup pencircle scaled 1.1u;
+draw (.5u,h)--(.5u,.5u)--(1.5u+space,.5u)--(1.5u+space,h)--(1.5u+space,.5u)--(2.5u+2space,.5u)\
+ --(2.5u+2space,h-.5u)--(3.5u+3space,h-.5u);
+linejoin:=mitered;
+draw (3.5u+3space,h-.5u)--(3.5u+3space,0)--(3.5u+3space,h-.5u)--(4.5u+4space,h-.5u)--(4.5u+4space,0);;
+
+gap=.6u;
+draw (3.5u+3space,h+gap)--(3.5u+3space,h+u+gap);
+draw (4.5u+4space,h+gap)--(4.5u+4space,h+u+gap);
+endfig
+
+end
diff -r 7ce25d709bbe -r de2320e9f616 include/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Makefile Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,6 @@
+ROOT= ..
+include ${ROOT}/mk/hdr.mk
+
+HFILES = ixp.h ixp_fcall.h
+
+include ${ROOT}/mk/common.mk
diff -r 7ce25d709bbe -r de2320e9f616 include/util.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/util.h Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,36 @@
+#define strlcat wmii_strlcat
+/* util.c */
+uint tokenize(char *res[], uint reslen, char *str, char delim);
+char *estrdup(const char *str);
+void *erealloc(void *ptr, uint size);
+void *emallocz(uint size);
+void *emalloc(uint size);
+void fatal(const char *fmt, ...);
+int max(int a, int b);
+int min(int a, int b);
+char *str_nil(char *s);
+uint strlcat(char *dst, const char *src, unsigned int siz);
+
+char *argv0;
+#undef ARGBEGIN
+#undef ARGEND
+#undef ARGF
+#undef EARGF
+#define ARGBEGIN int _argi, _argtmp, _inargv=0; char *_argv; \
+ if(!argv0)argv0=ARGF(); _inargv=1; \
+ while(argc && argv[0][0] == '-') { \
+ _argi=1; _argv=*argv++; argc++; \
+ while(_argv[_argi]) switch(_argv[_argi++])
+#define ARGEND }_inargv=0;USED(_argtmp);USED(_argv);USED(_argi)
+#define ARGF() ((_inargv && _argv[_argi]) ? \
+ (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \
+ : ((argc > 0) ? (argc--, *argv++) : ((char*)0)))
+#define EARGF(f) ((_inargv && _argv[_argi]) ? \
+ (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \
+ : ((argc > 0) ? (argc--, *argv++) : ((f), (char*)0)))
+
+#undef USED
+#undef SET
+#define USED(x) if(x){}else
+#define SET(x) ((x)=0)
+
diff -r 7ce25d709bbe -r de2320e9f616 key.c
--- a/key.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-#include <string.h>
-#include <stdlib.h>
-#include <X11/keysym.h>
-#include "wmii.h"
-
-void
-init_lock_keys() {
- XModifierKeymap *modmap;
- KeyCode num_lock;
- static int masks[] = {
- ShiftMask, LockMask, ControlMask, Mod1Mask,
- Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
- };
- int i;
-
- num_lock_mask = 0;
- modmap = XGetModifierMapping(blz.dpy);
- num_lock = XKeysymToKeycode(blz.dpy, XStringToKeysym("Num_Lock"));
- if(modmap && modmap->max_keypermod > 0) {
- int max = (sizeof(masks) / sizeof(int)) * modmap->max_keypermod;
- for(i = 0; i < max; i++)
- if(num_lock && (modmap->modifiermap[i] == num_lock))
- num_lock_mask = masks[i / modmap->max_keypermod];
- }
- XFreeModifiermap(modmap);
- valid_mask = 255 & ~(num_lock_mask | LockMask);
-}
-
-ulong
-mod_key_of_str(char *val) {
- ulong mod = 0;
-
- if (strstr(val, "Shift"))
- mod |= ShiftMask;
- if (strstr(val, "Control"))
- mod |= ControlMask;
- if (strstr(val, "Mod1"))
- mod |= Mod1Mask;
- if (strstr(val, "Mod2"))
- mod |= Mod2Mask;
- if (strstr(val, "Mod3"))
- mod |= Mod3Mask;
- if (strstr(val, "Mod4"))
- mod |= Mod4Mask;
- if (strstr(val, "Mod5"))
- mod |= Mod5Mask;
- return mod;
-}
-
-static void
-grab_key(Key *k) {
- XGrabKey(blz.dpy, k->key, k->mod, blz.root,
- True, GrabModeAsync, GrabModeAsync);
- if(num_lock_mask) {
- XGrabKey(blz.dpy, k->key, k->mod | num_lock_mask, blz.root,
- True, GrabModeAsync, GrabModeAsync);
- XGrabKey(blz.dpy, k->key, k->mod | num_lock_mask | LockMask, blz.root,
- True, GrabModeAsync, GrabModeAsync);
- }
- XSync(blz.dpy, False);
-}
-
-static void
-ungrab_key(Key *k) {
- XUngrabKey(blz.dpy, k->key, k->mod, blz.root);
- if(num_lock_mask) {
- XUngrabKey(blz.dpy, k->key, k->mod | num_lock_mask, blz.root);
- XUngrabKey(blz.dpy, k->key, k->mod | num_lock_mask | LockMask, blz.root);
- }
- XSync(blz.dpy, False);
-}
-
-static Key *
-name2key(const char *name) {
- Key *k;
- for(k=key; k; k=k->lnext)
- if(!strncmp(k->name, name, sizeof(k->name))) break;
- return k;
-}
-
-static Key *
-get_key(const char *name) {
- char buf[128];
- char *seq[8];
- char *kstr;
- uint i, toks;
- static ushort id = 1;
- Key *k = 0, *r = 0;
-
- if((k = name2key(name))) {
- ungrab_key(k);
- return k;
- }
- strncpy(buf, name, sizeof(buf));
- toks = tokenize(seq, 8, buf, ',');
- for(i = 0; i < toks; i++) {
- if(!k)
- r = k = emallocz(sizeof(Key));
- else {
- k->next = emallocz(sizeof(Key));
- k = k->next;
- }
- strncpy(k->name, name, sizeof(k->name));
- kstr = strrchr(seq[i], '-');
- if(kstr)
- kstr++;
- else
- kstr = seq[i];
- k->key = XKeysymToKeycode(blz.dpy, XStringToKeysym(kstr));
- k->mod = mod_key_of_str(seq[i]);
- }
- if(r) {
- r->id = id++;
- r->lnext = key;
- key = r;
- }
-
- return r;
-}
-
-static void
-next_keystroke(ulong *mod, KeyCode *code) {
- XEvent e;
- KeySym sym;
- *mod = 0;
-
- do {
- XMaskEvent(blz.dpy, KeyPressMask, &e);
- *mod |= e.xkey.state & valid_mask;
- *code = (KeyCode) e.xkey.keycode;
- sym = XKeycodeToKeysym(blz.dpy, e.xkey.keycode, 0);
- } while(IsModifierKey(sym));
-}
-
-static void
-emulate_key_press(ulong mod, KeyCode key) {
- XEvent e;
- Window client_win;
- int revert;
-
- XGetInputFocus(blz.dpy, &client_win, &revert);
- e.xkey.type = KeyPress;
- e.xkey.time = CurrentTime;
- e.xkey.window = client_win;
- e.xkey.display = blz.dpy;
- e.xkey.state = mod;
- e.xkey.keycode = key;
- XSendEvent(blz.dpy, client_win, True, KeyPressMask, &e);
- e.xkey.type = KeyRelease;
- XSendEvent(blz.dpy, client_win, True, KeyReleaseMask, &e);
- XSync(blz.dpy, False);
-}
-
-static Key *
-match_keys(Key *k, ulong mod, KeyCode keycode, Bool seq) {
- Key *ret = nil, *next;
-
- for(next = k->tnext; k; (k=next) && (next=k->tnext)) {
- if(seq)
- k = k->next;
- if(k && (k->mod == mod) && (k->key == keycode)) {
- k->tnext = ret;
- ret = k;
- }
- }
- return ret;
-}
-
-static void
-kpress_seq(Window w, Key *done) {
- ulong mod;
- KeyCode key;
- Key *found;
-
- next_keystroke(&mod, &key);
- found = match_keys(done, mod, key, True);
- if((done->mod == mod) && (done->key == key))
- emulate_key_press(mod, key); /* double key */
- else {
- if(!found) {
- XBell(blz.dpy, 0);
- } /* grabbed but not found */
- else if(!found->tnext && !found->next)
- write_event("Key %s\n", found->name);
- else
- kpress_seq(w, found);
- }
-}
-
-void
-kpress(Window w, ulong mod, KeyCode keycode) {
- Key *k, *found;
-
- for(k=key; k; k=k->lnext)
- k->tnext=k->lnext;
- found = match_keys(key, mod, keycode, False);
- if(!found) {
- XBell(blz.dpy, 0);
- } /* grabbed but not found */
- else if(!found->tnext && !found->next)
- write_event("Key %s\n", found->name);
- else {
- XGrabKeyboard(blz.dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- kpress_seq(w, found);
- XUngrabKeyboard(blz.dpy, CurrentTime);
- XSync(blz.dpy, False);
- }
-}
-
-void
-update_keys() {
- Key *k, *n;
- char *l, *p;
-
- init_lock_keys();
- while((k = key)) {
- key = key->lnext;
- ungrab_key(k);
- while((n = k)) {
- k = k->next;
- free(n);
- }
- }
- for(l = p = def.keys; p && *p;) {
- if(*p == '\n') {
- *p = 0;
- if((k = get_key(l)))
- grab_key(k);
- *p = '\n';
- l = ++p;
- }
- else
- p++;
- }
- if(l < p && strlen(l)) {
- if((k = get_key(l)))
- grab_key(k);
- }
- XSync(blz.dpy, False);
-}
diff -r 7ce25d709bbe -r de2320e9f616 main.c
--- a/main.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,596 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <X11/Xatom.h>
-#include <X11/Xproto.h>
-#include <X11/cursorfont.h>
-#include <errno.h>
-#include <locale.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include "wmii.h"
-
-static const char
- version[] = "wmii - " VERSION ", ©2007 Kris Maglione\n";
-
-static int (*x_error_handler) (Display *, XErrorEvent *);
-static char *address, *ns_path;
-static Bool check_other_wm;
-static struct sigaction sa;
-static struct passwd *passwd;
-static int sleeperfd, sock;
-
-static void
-usage() {
- fatal("usage: wmii [-a <address>] [-r <wmiirc>] [-v]\n");
-}
-
-static void
-scan_wins() {
- int i;
- uint num;
- Window *wins;
- XWindowAttributes wa;
- Window d1, d2;
-
- if(XQueryTree(blz.dpy, blz.root, &d1, &d2, &wins, &num)) {
- for(i = 0; i < num; i++) {
- if(!XGetWindowAttributes(blz.dpy, wins[i], &wa))
- continue;
- if(wa.override_redirect || XGetTransientForHint(blz.dpy, wins[i], &d1))
- continue;
- if(wa.map_state == IsViewable)
- manage_client(create_client(wins[i], &wa));
- }
- for(i = 0; i < num; i++) {
- if(!XGetWindowAttributes(blz.dpy, wins[i], &wa))
- continue;
- if(XGetTransientForHint(blz.dpy, wins[i], &d1)
- && wa.map_state == IsViewable)
- manage_client(create_client(wins[i], &wa));
- }
- }
- if(wins)
- XFree(wins);
-}
-
-int
-win_proto(Window w) {
- Atom *protocols;
- Atom real;
- ulong nitems, extra;
- int i, format, status, protos;
-
- status = XGetWindowProperty(
- /* display */ blz.dpy,
- /* window */ w,
- /* property */ atom[WMProtocols],
- /* offset */ 0L,
- /* length */ 20L,
- /* delete */ False,
- /* req_type */ XA_ATOM,
- /* type_ret */ &real,
- /* format_ret */&format,
- /* nitems_ret */&nitems,
- /* extra_bytes */&extra,
- /* prop_return */(uchar**)&protocols
- );
-
- if(status != Success || protocols == 0) {
- return 0;
- }
-
- if(nitems == 0) {
- free(protocols);
- return 0;
- }
-
- protos = 0;
- for(i = 0; i < nitems; i++) {
- if(protocols[i] == atom[WMDelete])
- protos |= WM_PROTOCOL_DELWIN;
- }
-
- free(protocols);
- return protos;
-}
-
-static void
-ns_display() {
- char *p, *disp;
-
- disp = getenv("DISPLAY");
- if(disp == nil)
- fatal("DISPLAY is unset");
-
- disp = estrdup(disp);
- p = &disp[strlen(disp) - 2];
- if(strcmp(p, ".0") == 0)
- *p = '\0';
-
- ns_path = emalloc(strlen(disp) + strlen(user) + strlen("/tmp/ns..") + 1);
- sprintf(ns_path, "/tmp/ns.%s.%s", user, disp);
-
- free(disp);
-}
-
-static void
-rmkdir(char *path, int mode) {
- char *p, *q;
- int ret;
- char c;
-
- q = path + strlen(ns_path);
- for(p = &path[1]; p <= q; p++) {
- c = *p;
- if((c == '/') || (c == '\0')) {
- *p = '\0';
- ret = mkdir(path, mode);
- if((ret == -1) && (errno != EEXIST))
- fatal("Can't create ns_path '%s':", path);
- *p = c;
- }
- }
-}
-
-static void
-init_ns() {
- struct stat st;
- char *p;
-
- if(address && strncmp(address, "unix!", 5) == 0) {
- ns_path = estrdup(&address[5]);
- p = strrchr(ns_path, '/');
- if(p != nil)
- p = '\0';
- }
- else if((p = getenv("WMII_NS_PATH")) || (p = getenv("NAMESPACE")))
- ns_path = p;
- else
- ns_display();
-
- if((ns_path[0] != '/') || (strlen(ns_path) == 0))
- fatal("Bad ns_path");
-
- rmkdir(ns_path, 0700);
-
- if(stat(ns_path, &st))
- fatal("Can't stat ns_path '%s':", ns_path);
- if(getuid() != st.st_uid)
- fatal("ns_path '%s' exists but is not owned by you",
- ns_path);
- if(st.st_mode & 077)
- fatal("ns_path '%s' exists, but has group or world permissions",
- ns_path);
-}
-
-static void
-init_environment() {
- if(address == nil)
- address = getenv("WMII_ADDRESS");
-
- init_ns();
-
- if(address == nil) {
- address = emalloc(strlen(ns_path) + strlen("unix!/wmii") + 1);
- sprintf(address, "unix!%s/wmii", ns_path);
- }
-
- setenv("WMII_NS_DIR", ns_path, True);
- setenv("WMII_ADDRESS", address, True);
-}
-
-static void
-intern_atom(int ident, char *name) {
- atom[ident] = XInternAtom(blz.dpy, name, False);
-}
-
-static void
-init_atoms() {
- intern_atom(WMState, "WM_STATE");
- intern_atom(WMProtocols, "WM_PROTOCOLS");
- intern_atom(WMDelete, "WM_DELETE_WINDOW");
- intern_atom(NetSupported, "_NET_SUPPORTED");
- intern_atom(NetWMName, "_NET_WM_NAME");
- intern_atom(TagsAtom, "_WIN_TAGS");
-
- XChangeProperty(blz.dpy, blz.root, atom[NetSupported], XA_ATOM, 32,
- PropModeReplace, (uchar *)&atom[NetSupported], 2);
-}
-
-static void
-create_cursor(int ident, uint shape) {
- cursor[ident] = XCreateFontCursor(blz.dpy, shape);
-}
-
-static void
-init_cursors() {
- Pixmap pix;
- XColor black, dummy;
-
- create_cursor(CurNormal, XC_left_ptr);
- create_cursor(CurNECorner, XC_top_right_corner);
- create_cursor(CurNWCorner, XC_top_left_corner);
- create_cursor(CurSECorner, XC_bottom_right_corner);
- create_cursor(CurSWCorner, XC_bottom_left_corner);
- create_cursor(CurMove, XC_fleur);
- create_cursor(CurInput, XC_xterm);
-
- XAllocNamedColor(blz.dpy, DefaultColormap(blz.dpy, blz.screen),
- "black", &black,
- &dummy);
- pix = XCreateBitmapFromData(blz.dpy, blz.root,
- (char[]){0}, 1, 1);
-
- cursor[CurInvisible] = XCreatePixmapCursor(blz.dpy,
- pix, pix,
- &black, &black,
- 0, 0);
-
- XFreePixmap(blz.dpy, pix);
-}
-
-static void
-init_screen(WMScreen *screen) {
- Window w;
- int ret;
- unsigned mask;
- XGCValues gcv;
-
- gcv.subwindow_mode = IncludeInferiors;
- gcv.function = GXxor;
- gcv.foreground = def.normcolor.bg;
- gcv.plane_mask = AllPlanes;
- gcv.graphics_exposures = False;
- xorgc = XCreateGC(blz.dpy, blz.root,
- GCForeground
- | GCGraphicsExposures
- | GCFunction
- | GCSubwindowMode
- | GCPlaneMask,
- &gcv);
-
- screen->rect.x = screen->rect.y = 0;
- screen->rect.width = DisplayWidth(blz.dpy, blz.screen);
- screen->rect.height = DisplayHeight(blz.dpy, blz.screen);
- def.snap = screen->rect.height / 63;
-
- sel_screen = XQueryPointer(blz.dpy, blz.root,
- &w, &w,
- &ret, &ret, &ret, &ret,
- &mask);
-}
-
-/*
- * There's no way to check accesses to destroyed windows, thus
- * those cases are ignored (especially on UnmapNotify's).
- * Other types of errors call Xlib's default error handler, which
- * calls exit().
- */
-int
-wmii_error_handler(Display *dpy, XErrorEvent *error) {
- if(check_other_wm)
- fatal("another window manager is already running");
-
- if(error->error_code == BadWindow
- ||(error->request_code == X_SetInputFocus
- && error->error_code == BadMatch)
- ||(error->request_code == X_PolyText8
- && error->error_code == BadDrawable)
- ||(error->request_code == X_PolyFillRectangle
- && error->error_code == BadDrawable)
- ||(error->request_code == X_PolySegment
- && error->error_code == BadDrawable)
- ||(error->request_code == X_ConfigureWindow
- && error->error_code == BadMatch)
- ||(error->request_code == X_GrabKey
- && error->error_code == BadAccess))
- return 0;
-
- fprintf(stderr, "wmii: fatal error: Xrequest code=%d, Xerror code=%d\n",
- error->request_code, error->error_code);
- return x_error_handler(blz.dpy, error); /* calls exit() */
-}
-
-static void
-cleanup() {
- Client *c;
-
- for(c=client; c; c=c->next)
- reparent_client(c, blz.root, c->sel->rect.x, c->sel->rect.y);
- XSync(blz.dpy, False);
-}
-
-static void
-cleanup_handler(int signal) {
- sa.sa_handler = SIG_DFL;
- sigaction(signal, &sa, nil);
-
- switch(signal) {
- case SIGINT:
- srv.running = False;
- break;
- default:
- cleanup();
- XCloseDisplay(blz.dpy);
- raise(signal);
- break;
- }
-}
-
-static void
-init_traps() {
- char buf[1];
- int fd[2];
-
- if(pipe(fd) != 0)
- fatal("Can't pipe():");
-
- switch(fork()) {
- case -1:
- fatal("Can't fork():");
- break; /* not reached */
- case 0:
- close(fd[1]);
- close(ConnectionNumber(blz.dpy));
- setsid();
-
- blz.dpy = XOpenDisplay(0);
- if(!blz.dpy)
- fatal("Can't open display");
-
- /* Wait for parent to exit */
- read(fd[0], buf, 1);
-
- XSetInputFocus(blz.dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
- XCloseDisplay(blz.dpy);
- exit(0);
- default:
- break;
- }
-
- close(fd[0]);
- sleeperfd = fd[1];
-
- sa.sa_flags = 0;
- sa.sa_handler = cleanup_handler;
- sigaction(SIGINT, &sa, nil);
- sigaction(SIGTERM, &sa, nil);
- sigaction(SIGQUIT, &sa, nil);
- sigaction(SIGHUP, &sa, nil);
-}
-
-static void
-spawn_command(const char *cmd) {
- char *shell, *p;
- pid_t pid;
- int status;
-
- /* Double fork hack */
- switch(pid = fork()) {
- case -1:
- fatal("Can't fork:");
- break; /* Not reached */
- case 0:
- switch(fork()) {
- case -1:
- fatal("Can't fork:");
- break; /* Not reached */
- case 0:
- if(setsid() == -1)
- fatal("Can't setsid:");
- close(sock);
- close(ConnectionNumber(blz.dpy));
-
- shell = passwd->pw_shell;
- if(shell[0] != '/')
- fatal("Shell is not an absolute path: %s", shell);
-
- /* Run through the user's shell as a login shell */
- p = malloc((strlen(shell) + 2));
- sprintf(p, "-%s", strrchr(shell, '/') + 1);
-
- execl(shell, p, "-c", cmd, nil);
- fatal("Can't exec '%s':", cmd);
- break; /* Not reached */
- default:
- exit(0);
- break; /* Not reached */
- }
- default:
- waitpid(pid, &status, 0);
- if(status != 0)
- exit(1); /* Error already printed */
- break;
- }
-}
-
-void
-check_9pcon(IXPConn *c) {
- serve_9pcon(c);
- check_x_event(nil);
-}
-
-int
-main(int argc, char *argv[]) {
- char *wmiirc, *errstr;
- WMScreen *s;
- XSetWindowAttributes wa;
- int i;
-
- passwd = getpwuid(getuid());
- user = estrdup(passwd->pw_name);
- wmiirc = "wmiistartrc";
-
- /* command line args */
- for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- printf("%s", version);
- exit(0);
- break;
- case 'V':
- verbose = True;
- break;
- case 'a':
- if(argv[i][2] != '\0')
- address = &argv[i][2];
- else if(++i < argc)
- address = argv[i];
- else
- usage();
- break;
- case 'r':
- if(argv[i][2] != '\0')
- wmiirc = &argv[i][2];
- else if(++i < argc)
- wmiirc = argv[i];
- else
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- setlocale(LC_CTYPE, "");
- starting = True;
-
- blz.dpy = XOpenDisplay(0);
- if(!blz.dpy)
- fatal("Can't open display");
- blz.screen = DefaultScreen(blz.dpy);
- blz.root = RootWindow(blz.dpy, blz.screen);
-
- check_other_wm = True;
- x_error_handler = XSetErrorHandler(wmii_error_handler);
- XSelectInput(blz.dpy, blz.root, SubstructureRedirectMask | EnterWindowMask);
- XSync(blz.dpy, False);
- check_other_wm = False;
-
- init_environment();
- init_traps();
-
- errstr = nil;
- sock = ixp_create_sock(address, &errstr);
- if(sock < 0)
- fatal("Can't create socket '%s': %s", address, errstr);
-
- if(wmiirc)
- spawn_command(wmiirc);
-
- ixp_server_open_conn(&srv, sock, &p9srv, check_9pcon, nil);
- ixp_server_open_conn(&srv, ConnectionNumber(blz.dpy), nil, check_x_event, nil);
-
- view = nil;
- client = nil;
- key = nil;
-
- def.font.fontstr = estrdup(BLITZ_FONT);
- def.border = 1;
- def.colmode = Coldefault;
-
- def.mod = Mod1Mask;
- strncpy(def.grabmod, "Mod1", sizeof(def.grabmod));
-
- strncpy(def.focuscolor.colstr, BLITZ_FOCUSCOLORS, sizeof(def.focuscolor.colstr));
- strncpy(def.normcolor.colstr, BLITZ_NORMCOLORS, sizeof(def.normcolor.colstr));
- loadcolor(&blz, &def.focuscolor);
- loadcolor(&blz, &def.normcolor);
-
- init_atoms();
- init_cursors();
- loadfont(&blz, &def.font);
- init_lock_keys();
-
- num_screens = 1;
- screens = emallocz(num_screens * sizeof(*screens));
- for(i = 0; i < num_screens; i++) {
- s = &screens[i];
- init_screen(s);
- pmap = XCreatePixmap(
- /* display */ blz.dpy,
- /* drawable */ blz.root,
- /* width */ s->rect.width,
- /* height */ s->rect.height,
- /* depth */ DefaultDepth(blz.dpy, blz.screen)
- );
- wa.event_mask =
- SubstructureRedirectMask
- | EnterWindowMask
- | LeaveWindowMask
- | FocusChangeMask;
- wa.cursor = cursor[CurNormal];
- XChangeWindowAttributes(blz.dpy, blz.root, CWEventMask | CWCursor, &wa);
- wa.override_redirect = 1;
- wa.background_pixmap = ParentRelative;
- wa.event_mask =
- ExposureMask
- | ButtonReleaseMask
- | FocusChangeMask
- | SubstructureRedirectMask
- | SubstructureNotifyMask;
- s->brect = s->rect;
- s->brect.height = labelh(&def.font);
- s->brect.y = s->rect.height - s->brect.height;
- s->barwin = XCreateWindow(
- /* display */ blz.dpy,
- /* parent */ RootWindow(blz.dpy, blz.screen),
- /* x */ s->brect.x,
- /* y */ s->brect.y,
- /* width */ s->brect.width,
- /* height */ s->brect.height,
- /*border_width*/0,
- /* depth */ DefaultDepth(blz.dpy, blz.screen),
- /* class */ CopyFromParent,
- /* visual */ DefaultVisual(blz.dpy, blz.screen),
- /* valuemask */ CWOverrideRedirect | CWBackPixmap | CWEventMask,
- /* attrubutes */&wa
- );
- XSync(blz.dpy, False);
- s->bbrush.blitz = &blz;
- s->bbrush.gc = XCreateGC(blz.dpy, s->barwin, 0, 0);
- s->bbrush.drawable = pmap;
- s->bbrush.rect = s->brect;
- s->bbrush.rect.x = 0;
- s->bbrush.rect.y = 0;
- s->bbrush.color = def.normcolor;
- s->bbrush.font = &def.font;
- s->bbrush.border = 1;
- draw_bar(s);
- XMapRaised(blz.dpy, s->barwin);
- }
-
- screen = &screens[0];
- screen->focus = nil;
- XSetInputFocus(blz.dpy, screen->barwin, RevertToParent, CurrentTime);
-
- scan_wins();
- starting = False;
- update_views();
- if(view)
- write_event("FocusTag %s\n", screen->sel->name);
-
- check_x_event(nil);
- errstr = ixp_server_loop(&srv);
- if(errstr)
-
- cleanup();
- XCloseDisplay(blz.dpy);
- ixp_server_close(&srv);
- close(sleeperfd);
-
- if(execstr)
- execl("/bin/sh", "sh", "-c", execstr, nil);
-
- if(errstr)
- fatal("%s", errstr);
- return 0;
-}
diff -r 7ce25d709bbe -r de2320e9f616 man/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/man/Makefile Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,14 @@
+ROOT=..
+include ${ROOT}/mk/hdr.mk
+
+TARG = wmii.1 \
+ wmiiloop.1 \
+ wmiir.1 \
+ wmiiwm.1
+
+FILTER = sed "s|CONFPREFIX|${CONFPREFIX}|g; \
+ s|CONFVERSION|${CONFVERSION}|g; \
+ s|P9PATHS|${P9PATHS}|g; \
+ s|AWKPATH|${AWKPATH}|g"
+
+include ${ROOT}/mk/man.mk
diff -r 7ce25d709bbe -r de2320e9f616 man/wmii.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/man/wmii.1 Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,205 @@
+.TH WMII 1 wmii-VERSION
+.SH NAME
+wmii \(em window manager improved\(emimproved
+.SH SYNOPSIS
+.B wmii
+.SH DESCRIPTION
+.SS Overview
+.B wmii
+is a dynamic window manager for X11. See
+.BR wmiiwm (1)
+for more info.
+.SS Actions
+An action is a shell script in the default setup, but it can actually be
+any executable file. It is executed usually by selecting it from the
+actions menu.
+You can customize an action by copying it from the global action
+directory CONFPREFIX/wmii-3.5 to $HOME/.wmii-3.5 and then editing the copy to
+fit your needs. Of course you can also create your own actions there; make
+sure that they are executable.
+.P
+Here is a list of the default actions:
+.TP 2
+quit
+leave the window manager nicely
+.TP 2
+status
+periodically print date and load average to the bar
+.TP 2
+welcome
+display a welcome message that contains the wmii tutorial
+.TP 2
+wmiirc
+configure wmii
+.SS Default Key Bindings
+.PD 0
+.B Moving Around
+.RS 2
+.TP 16
+.I Key
+.I Action
+.TP
+.B Mod-h
+Move to a
+.B window
+to the
+.B left
+of the one currently focused
+.TP
+.B Mod-l
+Move to a
+.B window
+to the
+.B right
+of the one currently focused
+.TP
+.B Mod-j
+Move to a
+.B window below
+the one currently focused
+.TP
+.B Mod-k
+Move to a
+.B window above
+the one currently focused
+.TP
+.B Mod-space
+.B Toggle
+between the managed and floating
+.B layer
+.TP
+.BI Mod-t \ tag
+Move to the
+.B view
+of the given
+.I tag
+.TP
+.B Mod-[0-9]
+Move to the
+.B view
+with the given number
+.PD 1
+.P
+.RE
+.B Moving Things Around
+.RS 2
+.PD 0
+.TP 16
+.I Key
+.I Action
+.TP
+.B Mod-Shift-h
+Move the current window
+.B window
+to a column on the
+.B left
+.TP
+.B Mod-Shift-l
+Move the current window
+.B window
+to a column on the
+.B right
+.TP
+.B Mod-Shift-j
+Move the current
+.B window below
+the one beneath it
+.TP
+.B Mod-Shift-k
+Move the current
+.B window above
+the one above it
+.TP
+.B Mod-Shift-space
+.B Toggle
+the current
+.B window
+between the managed and floating
+.B layer
+.TP
+.BI Mod-Shift-t \ tag
+Move the current window to the
+.B view
+of the given
+.I tag
+.TP
+.B Mod-Shift-[0-9]
+Move to the current window to the
+.B view
+with the given number
+.PD 1
+.P
+.RE
+.B Miscellaneous
+.RS 2
+.PD 0
+.TP 16
+.I Key
+.I Action
+.TP
+.B Mod-m
+Switch the current column to
+.B max mode
+.TP
+.B Mod-s
+Switch the current column to
+.B stack mode
+.TP
+.B Mod-d
+Switch the current column to
+.B default mode
+.TP
+.B Mod-Shift-c
+.B Kill
+the selected client
+.TP
+.BI Mod-p \ program
+.B Execute
+.I program
+.TP
+.BI Mod-a \ action
+Execute the
+.B named action
+.TP
+.B Mod-Enter
+Start an
+.B xterm
+
+.SS Configuration
+If you feel the need to change the default configuration, then customize (as
+described above) the
+.B wmiirc
+action. This action is executed at the end of the
+.B wmii
+script and does all the work of setting up the window manager, the key
+bindings, the bar labels, etc.
+.SH FILES
+.TP
+/tmp/ns.$USER.${DISPLAY%.0}/wmii
+The wmii socket file which provides a 9P service.
+.TP
+CONFPREFIX/wmii-3.5
+Global action directory.
+.TP
+$HOME/.wmii-3.5
+User-specific action directory. Actions are first searched here.
+.SH ENVIRONMENT
+.TP
+HOME, DISPLAY
+See the section
+.B FILES
+above.
+.P
+The following variables are set and exported within
+.B wmii
+and thus can be used in actions:
+.TP
+WMII_ADDRESS
+Socket file of
+.BR wmiiwm (1).
+Used by
+.BR wmiir (1).
+.SH SEE ALSO
+.BR wmiiwm (1),
+.BR dmenu (1),
+.BR wmiir (1)
diff -r 7ce25d709bbe -r de2320e9f616 man/wmiiloop.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/man/wmiiloop.1 Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,79 @@
+.TH WMIIR 1 wmii\-VERSION
+.SH NAME
+wmiiloop \(em wmii event loop processor
+.SH SYNOPSIS
+.B cat
+.I events
+|
+.B wmiiloop
+|
+.B sh
+.br
+.SH DESCRIPTION
+.SS Overview
+.B wmiiloop
+is an awk script which preprocesses
+.BR sh (1)
+syntax to simplify writing a wmii event loop.
+
+.br
+.B eventloop
+sends any text up to the first line containing
+.I #
+.IR Events|Actions|Key ,
+and any text after any other line begining with
+.IR # ,
+directly to its standard output. Any other line is processed based
+on its first word, with every indented line after it taken as its
+.IR body .
+.TP 2
+.BI "Key " sequence
+The key sequence
+.I sequence
+is bound to its
+.IR body .
+.I sequence
+is written to
+.I /keys
+and
+.I body
+is executed, with
+.I $key
+set to
+.I sequence
+whenever the key is pressed.
+
+.TP 2
+.BI "Event " name
+Whenever an event with
+.I name
+is read from
+.IR /event ,
+.I body
+is executed, with
+.I $event
+set to
+.IR name ,
+and
+.I $[1\-9]
+set to further arguments.
+
+.TP 2
+.BI "Action " name
+A function called
+.BI Action_ name
+is created with
+.I body
+as its body, and
+.I name
+is added to the
+.I $ACTIONS
+variable.
+
+.SH SEE ALSO
+.BR wmii (1),
+.BR wmiir (1),
+.BR wmiiwm (1)
+.B PREFIX/etc/wmiirc
+
+http://www.cs.bell\-labs.com/sys/man/5/INDEX.html
diff -r 7ce25d709bbe -r de2320e9f616 man/wmiir.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/man/wmiir.1 Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,51 @@
+.TH WMIIR 1 wmii-VERSION
+.SH NAME
+wmiir \(em wrapper script for ixpc
+.SH SYNOPSIS
+.B wmiir
+.RB [ \-a
+.IR address ]
+.I action
+.I file
+.br
+.B wmiir
+.B \-v
+.SH DESCRIPTION
+.SS Overview
+.B wmiir
+is a wrapper script for
+.BR ixpc (1)
+to conveniently access the filesystem of
+.BR wmiiwm (1)
+from the command line or from shell
+scripts. It can be used to configure
+.BR wmii (1).
+
+.SS Options
+See the manual page of
+.BR ixpc (1) .
+.SH ENVIRONMENT
+.TP
+WMII_ADDRESS
+The address of the wmiiwm file server to which wmiir will connect.
+.SH EXAMPLES
+.TP
+.B wmiir ls /
+This prints the root directory of the wmii filesystem. For more information
+about the contents of this filesystem, see
+.BR wmiiwm (1).
+.TP
+.B echo -n quit | wmiir write /ctl
+Write 'quit' to the main control file of the wmii filesystem, effectively
+leaving wmii.
+.TP
+.B echo -n view 2 | wmiir write /ctl
+Bring into view all clients tagged '2'. To learn about clients and
+tags, see
+.BR wmii (1).
+.SH SEE ALSO
+.BR wmii (1),
+.BR ixpc (1),
+.BR wmiiwm (1)
+
+http://www.cs.bell-labs.com/sys/man/5/INDEX.html
diff -r 7ce25d709bbe -r de2320e9f616 man/wmiiwm.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/man/wmiiwm.1 Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,150 @@
+.TH WMIIWM 1 wmii-VERSION
+.SH NAME
+wmiiwm \(em window manager improved\(emimproved (core)
+.SH SYNOPSIS
+.B wmiiwm
+.B \-a
+.I <address>
+.RB [ \-c ]
+.RB [ \-v ]
+.SH DESCRIPTION
+
+.PD 0
+.SS Overview
+.BR wmiiwm (1)
+is the core of window manager improved\(emimproved.
+.P
+.B wmii
+is a dynamic window manager for X11. In contrast to static window management
+the user rarely has to think about how to organize windows, no matter what he
+is doing or how many applications are used at the same time. The window manager
+adapts to the current environment and fits to the needs of the user, rather
+than forcing him to use a preset, fixed layout and trying to shoehorn all
+windows and applications into it.
+.P
+.B wmii
+supports classic and tiled window management with extended keyboard and mouse
+control. The classic window management arranges windows in a floating layer
+in which windows can be moved and resized freely. The tiled window management
+is based on columns which split up the screen horizontally. Each column handles
+arbitrary windows and arranges them vertically in a non\-overlapping way. They
+can then be moved and resized between and within columns at will.
+.P
+.B wmii
+provides a virtual filesystem which represents the internal state similar to
+the procfs of Unix operating systems. Modifying this virtual filesystem results
+in changing the state of the window manager. The virtual filesystem service can
+be accessed through 9P\-capable client programs, like
+.BR wmiir (1) .
+This allows simple and powerful remote control of the core window manager.
+.P
+.B wmii
+basically consists of clients, columns, views, and the bar, which are described
+in detail in the
+.B Terminology
+section.
+.SS Options
+.TP
+.BI \-a " address"
+Lets you specify the address which
+.B wmiiwm
+uses to listen for connections. The syntax for
+.I address
+is taken (along with many other profound ideas) from the Plan 9 operating
+system and has the form
+.B unix!/path/to/socket
+for unix socket files, and
+.B tcp!hostname!port
+for tcp sockets.
+.TP
+.B \-c
+Checks if another window manager is running. If not it exits with termination code
+0.
+.TP
+.B \-v
+Prints version information to stdout, then exits.
+.SS Terminology
+.TP 2
+Display
+A running X server instance consisting of input devices and screens.
+.TP 2
+Screen
+A physical or virtual (Xinerama or
+.BR Xnest (1))
+screen of an X display. A screen displays a bar window and a view at a time.
+.TP 2
+Window
+A (rectangular) drawable X object which is displayed on a screen, usually an
+application window.
+.TP 2
+Client
+An application window surrounded by a frame window containing a border and a
+title\-bar.
+.TP 2
+Floating layer
+A screen layer of
+.B wmii
+on top of all other layers, where clients are arranged in a classic (floating)
+way. They can be resized or moved freely.
+.TP 2
+Managed layer
+A screen layer of
+.B wmii
+behind the floating layer, where clients are arranged in a non\-overlapping
+(managed) way. Here, the window manager dynamically assigns each client a
+size and position. The managed layer consists of columns.
+.TP 2
+Tag
+Alphanumeric strings which can be assigned to a client. This provides a
+mechanism to group clients with similar properties. Clients can have one
+tag, e.g.
+.IR work ,
+or several tags, e.g.
+.IR work+mail .
+Tags are separated with the
+.I +
+character.
+.TP 2
+View
+A set of clients containing a specific tag, quite similiar to a workspace in
+other window managers. It consists of the floating and managed layers.
+.TP 2
+Column
+A column is a screen area which arranges clients vertically in a
+non\-overlapping way. Columns provide three different modes, which arrange
+clients with equal size, stacked, or maximized respectively. Clients can be
+moved and resized between and within columns freely.
+.TP 2
+Bar
+The bar at the bottom of the screen displays a label for each view and
+allows the creation of arbitrary user\-defined labels.
+.TP 2
+Event
+An event is a message which can be read from a special file in the filesystem
+of
+.BR wmiiwm ,
+such as a mouse button press, a key press, or a message written by a different
+9P\-client.
+.SS Basic window management
+Running a raw
+.B wmiiwm
+process without the
+.BR wmii (1)
+script provides basic window management capabilities already. However to use
+it effectively, remote control through its filesystem interface is necessary.
+By default it is only usable with the mouse in conjunction with the
+.I Mod1 (Alt)
+modifier key. Other interactions like customizing the style, killing or
+retagging clients, or grabbing keys cannot be achieved without accessing the
+filesystem.
+.P
+The filesystem can be accessed by connecting to the
+.I address
+of
+.B wmiiwm
+with any 9P\-capable client, like
+.BR wmiir (1).
+.SH SEE ALSO
+.BR wmii (1),
+.BR dmenu (1),
+.BR wmiir (1)
diff -r 7ce25d709bbe -r de2320e9f616 mk/common.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/common.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,18 @@
+all:
+
+install: all
+depend: cleandep
+
+MANDIRS=${MAN}/man1
+mkdirs:
+ for i in ${BIN} ${ETC} ${MANDIRS} ${DIRS}; do \
+ test -d $$i || echo MKDIR $$i; \
+ mkdir -pm 0755 $$i; \
+ done
+
+install: ${HFILES:.h=.install}
+
+cleandep:
+ rm .depend 2>/dev/null || true
+
+.PHONY: all options clean dist install uninstall depend cleandep
diff -r 7ce25d709bbe -r de2320e9f616 mk/dir.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/dir.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,29 @@
+dall:
+ for i in ${DIRS}; do \
+ if [ ! -d $$i ]; then echo Skipping nonexistent directory: $$i 1>&2; continue; fi; \
+ echo MAKE all ${BASE}$$i/; \
+ (cd $$i && ${MAKE} BASE="${BASE}$$i/" all) || exit $?; \
+ done
+dclean:
+ for i in ${DIRS}; do \
+ if [ ! -d $$i ]; then echo Skipping nonexistent directory: $$i 1>&2; continue; fi; \
+ echo MAKE clean ${BASE}$$i/; \
+ (cd $$i && ${MAKE} BASE="${BASE}$$i/" clean) || exit $?; \
+ done
+dinstall:
+ for i in ${DIRS}; do \
+ if [ ! -d $$i ]; then echo Skipping nonexistent directory: $$i 1>&2; continue; fi; \
+ echo MAKE install ${BASE}$$i/; \
+ (cd $$i && ${MAKE} BASE="${BASE}$$i/" install) || exit $?; \
+ done
+ddepend:
+ for i in ${DIRS}; do \
+ if [ ! -d $$i ]; then echo Skipping nonexistent directory: $$i 1>&2; continue; fi; \
+ echo MAKE depend ${BASE}$$i/; \
+ (cd $$i && ${MAKE} BASE="${BASE}$$i/" depend) || exit $?; \
+ done
+
+all: dall
+clean: dclean
+install: dinstall
+depend: ddepend
diff -r 7ce25d709bbe -r de2320e9f616 mk/hdr.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/hdr.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,60 @@
+.SILENT:
+.SUFFIXES: .O .o .c .sh .rc .awk .1 .depend .install .clean
+all:
+
+.c.o:
+ ${COMPILE} $@ $<
+
+.c.depend:
+ ${DEPEND} $< >>.depend
+
+.o.O:
+ ${LINK} $@ $<
+
+.awk.O:
+ echo FILTER ${BASE}$<
+ ${FILTER} $< >$@
+
+.rc.O:
+ echo FILTER ${BASE}$<
+ ${FILTER} $< >$@
+
+.sh.O:
+ echo FILTER ${BASE}$<
+ ${FILTER} $< >$@
+
+.O.install:
+ echo INSTALL $*
+ cp -f $< ${BIN}/$*
+ chmod 0755 ${BIN}/$*
+
+.a.install:
+ echo INSTALL $<
+ cp -f $< ${LIBDIR}/$<
+ chmod 0644 ${LIBDIR}/$<
+
+.h.install:
+ echo INSTALL $<
+ cp -f $< ${INCLUDE}/$<
+ chmod 0644 ${INCLUDE}/$<
+
+.1.install:
+ echo INSTALL man $*'(1)'
+ ${FILTER} $< >${MAN}/man1/$<
+ chmod 0644 ${MAN}/man1/$<
+
+.O.clean:
+ rm $< || true 2>/dev/null
+ rm $*.o || true 2>/dev/null
+.o.clean:
+ rm $< || true 2>/dev/null
+
+printinstall:
+mkdirs:
+clean:
+install: printinstall mkdirs
+
+COMPILE= CC="${CC}" CFLAGS="${CFLAGS} ${EXCFLAGS}" ${ROOT}/util/compile
+LINK= LD="${LD}" LDFLAGS="${LDFLAGS} ${EXLDFLAGS}" ${ROOT}/util/link
+
+include ${ROOT}/config.mk
diff -r 7ce25d709bbe -r de2320e9f616 mk/lib.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/lib.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,24 @@
+LIB = ${TARG}.a
+OFILES = ${OBJ:=.o}
+
+all: ${HFILES} ${LIB}
+
+install: ${TARG}.install
+clean: libclean
+depend: ${OBJ:=.depend}
+
+libclean:
+ for i in ${LIB} ${OFILES}; do \
+ rm $$i; \
+ done 2>/dev/null || true
+
+printinstall:
+ echo 'Install directories:'
+ echo ' Lib: ${LIBDIR}'
+
+${LIB}: ${OFILES}
+ @echo AR $@
+ @${AR} $@ ${OFILES}
+ @${RANLIB} $@
+
+include ${ROOT}/mk/common.mk
diff -r 7ce25d709bbe -r de2320e9f616 mk/man.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/man.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,7 @@
+install: ${TARG:.1=.install}
+
+printinstall:
+ echo 'Install directories:'
+ echo ' Man: ${MAN}'
+
+include ${ROOT}/mk/common.mk
diff -r 7ce25d709bbe -r de2320e9f616 mk/many.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/many.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,18 @@
+PROGS = ${TARG:=.O}
+
+all: ${PROGS}
+
+install: ${TARG:=.install}
+clean: manyclean
+
+printinstall:
+ echo 'Install directories:'
+ echo ' Bin: ${BIN}'
+
+manyclean:
+ for i in ${TARG}; do \
+ rm $$i.o; rm $$i.O; \
+ done 2>/dev/null || true
+
+include ${ROOT}/mk/common.mk
+
diff -r 7ce25d709bbe -r de2320e9f616 mk/one.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/one.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,22 @@
+PROG = ${TARG}.O
+OFILES = ${OBJ:=.o}
+
+all: ${PROG}
+
+install: ${TARG}.install
+clean: oneclean
+depend: ${OBJ:=.depend}
+
+printinstall:
+ echo 'Install directories:'
+ echo ' Bin: ${BIN}'
+
+oneclean:
+ for i in ${PROG} ${OFILES}; do \
+ rm $$i; \
+ done 2>/dev/null || true
+
+${PROG}: ${OFILES} ${LIB}
+ ${LINK} $@ ${OFILES} ${LIB}
+
+include ${ROOT}/mk/common.mk
diff -r 7ce25d709bbe -r de2320e9f616 mk/wmii.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mk/wmii.mk Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,2 @@
+VERSION = $$(hg tip --template 'hg{rev}' 2>/dev/null)
+CONFVERSION = 3.5
diff -r 7ce25d709bbe -r de2320e9f616 mouse.c
--- a/mouse.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
-/* Copyright ©2006 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <stdlib.h>
-#include <string.h>
-#include "wmii.h"
-
-enum {
- ButtonMask =
- ButtonPressMask | ButtonReleaseMask,
- MouseMask =
- ButtonMask | PointerMotionMask
-};
-
-static void
-rect_morph_xy(XRectangle *rect, int dx, int dy, BlitzAlign *mask) {
- BlitzAlign new_mask = 0;
- if(*mask & NORTH) {
- if(rect->height - dy >= 0 || *mask & SOUTH) {
- rect->y += dy;
- rect->height -= dy;
- }
- else {
- rect->y += rect->height;
- rect->height = dy - rect->height;
- new_mask ^= NORTH|SOUTH;
- }
- }
- if(*mask & SOUTH) {
- if(rect->height + dy >= 0 || *mask & NORTH)
- rect->height += dy;
- else {
- rect->height = -dy - rect->height;
- rect->y -= rect->height;
- new_mask ^= NORTH|SOUTH;
- }
- }
- if(*mask & EAST) {
- if(rect->width + dx >= 0 || *mask & WEST)
- rect->width += dx;
- else {
- rect->width = -dx - rect->width;
- rect->x -= rect->width;
- new_mask ^= EAST|WEST;
- }
- }
- if(*mask & WEST) {
- if(rect->width - dx >= 0 || *mask & EAST) {
- rect->x += dx;
- rect->width -= dx;
- }
- else {
- rect->x += rect->width;
- rect->width = dx - rect->width;
- new_mask ^= EAST|WEST;
- }
- }
- *mask ^= new_mask;
-}
-
-typedef struct {
- XRectangle *rects;
- int num;
- int x1, y1, x2, y2;
- BlitzAlign mask;
- int *delta;
-} SnapArgs;
-
-static void
-snap_line(SnapArgs *a) {
- int i, t_xy;
-
- /* horizontal */
- if(a->y1 == a->y2 && (a->mask & (NORTH|SOUTH))) {
- for(i=0; i < a->num; i++) {
- if(!(r_east(&a->rects[i]) < a->x1) ||
- (a->rects[i].x > a->x2)) {
-
- if(abs(a->rects[i].y - a->y1) <= abs(*a->delta))
- *a->delta = a->rects[i].y - a->y1;
-
- t_xy = r_south(&a->rects[i]);
- if(abs(t_xy - a->y1) < abs(*a->delta))
- *a->delta = t_xy - a->y1;
- }
- }
- }
- else if (a->mask & (EAST|WEST)) {
- /* This is the same as above, tr/xy/yx/,
- * s/width/height/, s/height/width/ */
- for(i=0; i < a->num; i++) {
- if(!(r_south(&a->rects[i]) < a->y1) ||
- (a->rects[i].y > a->y2)) {
-
- if(abs(a->rects[i].x - a->x1) <= abs(*a->delta))
- *a->delta = a->rects[i].x - a->x1;
-
- t_xy = r_east(&a->rects[i]);
- if(abs(t_xy - a->x1) < abs(*a->delta))
- *a->delta = t_xy - a->x1;
- }
- }
- }
-}
-
-BlitzAlign
-snap_rect(XRectangle *rects, int num, XRectangle *current, BlitzAlign *mask, int snap) {
- SnapArgs a = { rects, num, 0, 0, 0, 0, *mask, nil };
- int dx, dy;
- BlitzAlign ret;
-
- dx = dy = snap + 1;
-
- a.x1 = current->x;
- a.x2 = r_east(current);
- a.delta = &dy;
- if(*mask & NORTH) {
- a.y2 = a.y1 = current->y;
- snap_line(&a);
- }
- if(*mask & SOUTH) {
- a.y2 = a.y1 = r_south(current);
- snap_line(&a);
- }
-
- a.y1 = current->y;
- a.y2 = r_south(current);
- a.delta = &dx;
- if(*mask & EAST) {
- a.x1 = a.x2 = r_east(current);
- snap_line(&a);
- }
- if(*mask & WEST) {
- a.x1 = a.x2 = current->x;
- snap_line(&a);
- }
-
- rect_morph_xy(current,
- abs(dx) <= snap ? dx : 0,
- abs(dy) <= snap ? dy : 0,
- mask);
-
- ret = *mask;
- if(abs(dx) <= snap)
- ret ^= EAST|WEST;
- if(abs(dy) <= snap)
- ret ^= NORTH|SOUTH;
- return ret ^ CENTER;
-}
-
-static void
-draw_xor_border(XRectangle *r) {
- XRectangle xor;
-
- xor = *r;
- xor.x += 2;
- xor.y += 2;
- xor.width = xor.width > 4 ? xor.width - 4 : 0;
- xor.height = xor.height > 4 ? xor.height - 4 : 0;
-
- XSetLineAttributes(blz.dpy, xorgc, 1, LineSolid, CapNotLast, JoinMiter);
- XSetForeground(blz.dpy, xorgc, def.focuscolor.bg);
- if(xor.height > 4 && xor.width > 2)
- XDrawLine(blz.dpy, blz.root, xorgc,
- xor.x + 2,
- xor.y + xor.height / 2,
- r_east(&xor) - 2,
- xor.y + xor.height / 2);
- if(xor.width > 4 && xor.height > 2)
- XDrawLine(blz.dpy, blz.root, xorgc,
- xor.x + xor.width / 2,
- xor.y + 2,
- xor.x + xor.width / 2,
- r_south(&xor) - 2);
- XSetLineAttributes(blz.dpy, xorgc, 4, LineSolid, CapNotLast, JoinMiter);
- XDrawRectangles(blz.dpy, blz.root, xorgc, &xor, 1);
-}
-
-static void
-find_droppoint(Frame *frame, int x, int y, XRectangle *rect, Bool do_move) {
- View *v;
- Area *a, *a_prev;
- Frame *f, *f_close;
-
- v = frame->view;
- rect->y = 0;
- rect->height = screen->rect.height - screen->brect.height;
-
- a_prev = v->area;
- for(a = a_prev->next; a && a->next; a = a->next) {
- if(x < r_east(&a->rect))
- break;
- a_prev = a;
- }
- if(x < (a->rect.x + labelh(&def.font))) {
- rect->x = a->rect.x - 4;
- rect->width = 8;
-
- if(do_move) {
- a = new_column(v, a_prev, 0);
- send_to_area(a, frame);
- focus(frame->client, False);
- }
- return;
- }
- if(x > (r_east(&a->rect) - labelh(&def.font))) {
- rect->x = r_east(&a->rect) - 4;
- rect->width = 8;
-
- if(do_move) {
- a = new_column(v, a, 0);
- send_to_area(a, frame);
- focus(frame->client, False);
- }
- return;
- }
-
- rect->x = a->rect.x;
- rect->width = a->rect.width;
-
- f_close = nil;
- for(f = a->frame; f; f = f->anext) {
- if(y < f->rect.y)
- break;
- if(y < r_south(&f->rect))
- break;
- f_close = f;
- }
- if(f == nil)
- f = f_close;
- if(y < (f->rect.y + labelh(&def.font))) {
- rect->y = f->rect.y;
- rect->height = 2;
- if(f_close) {
- rect->y = r_south(&f_close->rect);
- rect->height = f->rect.y - rect->y;
- }
- if(do_move)
- goto do_move;
- return;
- }
- if(y > r_south(&f->rect) - labelh(&def.font)) {
- rect->y = r_south(&f->rect);
- rect->height = (screen->rect.height - labelh(&def.font) - rect->y);
- if(f->anext)
- rect->height = (f->anext->rect.y - rect->y);
- if(do_move)
- goto do_move;
- return;
- }
-
- *rect = f->rect;
- if(do_move) {
- swap_frames(frame, f);
- focus(frame->client, False);
- }
- return;
-
-do_move:
- if(frame == f)
- return;
- if(a != frame->area)
- send_to_area(a, frame);
- remove_frame(frame);
- insert_frame(f, frame, False);
- arrange_column(f->area, False);
- focus(frame->client, True);
-}
-
-static void
-do_managed_move(Client *c) {
- XRectangle frect, ofrect;
- Window dummy;
- XEvent ev;
- Frame *f;
- uint di;
- int x, y, i;
-
- focus(c, False);
- f = c->sel;
-
- XSync(blz.dpy, False);
- if(XGrabPointer(blz.dpy, c->framewin, False, MouseMask, GrabModeAsync, GrabModeAsync,
- None, cursor[CurMove], CurrentTime) != GrabSuccess)
- return;
- XGrabServer(blz.dpy);
-
- XQueryPointer(blz.dpy, blz.root, &dummy, &dummy, &i, &i, &x, &y, &di);
-
- find_droppoint(f, x, y, &frect, False);
- draw_xor_border(&frect);
- for(;;) {
- XMaskEvent(blz.dpy, MouseMask | ExposureMask, &ev);
- switch (ev.type) {
- case ButtonRelease:
- draw_xor_border(&frect);
-
- find_droppoint(f, x, y, &frect, True);
-
- XUngrabServer(blz.dpy);
- XUngrabPointer(blz.dpy, CurrentTime);
- XSync(blz.dpy, False);
- return;
- case MotionNotify:
- ofrect = frect;
- x = ev.xmotion.x_root;
- y = ev.xmotion.y_root;
-
- find_droppoint(f, x, y, &frect, False);
-
- if(memcmp(&frect, &ofrect, sizeof(frect))) {
- draw_xor_border(&ofrect);
- draw_xor_border(&frect);
- }
- break;
- case Expose:
- (handler[Expose])(&ev);
- break;
- default: break;
- }
- }
-}
-
-void
-do_mouse_resize(Client *c, Bool grabbox, BlitzAlign align) {
- BlitzAlign grav;
- Window dummy;
- Cursor cur;
- XEvent ev;
- XRectangle *rects, ofrect, frect, origin;
- int snap, dx, dy, pt_x, pt_y, hr_x, hr_y, i;
- uint num, di;
- Bool floating;
- float rx, ry;
- Frame *f;
-
- f = c->sel;
- floating = f->area->floating;
- origin = frect = f->rect;
- cur = cursor_of_quad(align);
- if(floating) {
- rects = rects_of_view(f->area->view, &num, (grabbox ? c->frame : nil));
- snap = screen->rect.height / 66;
- }else{
- rects = nil;
- snap = 0;
- }
-
- if(align == CENTER) {
- if(!grabbox)
- cur = cursor[CurInvisible];
- if(!floating) {
- do_managed_move(c);
- return;
- }
- }
-
- XQueryPointer(blz.dpy, c->framewin, &dummy, &dummy, &i, &i, &pt_x, &pt_y, &di);
- rx = (float)pt_x / frect.width;
- ry = (float)pt_y / frect.height;
-
- if(XGrabPointer(
- /* display */ blz.dpy,
- /* window */ c->framewin,
- /* owner_events */ False,
- /* event_mask */ MouseMask,
- /* pointer_mode */ GrabModeAsync,
- /* keyboard_mode */ GrabModeAsync,
- /* confine_to */ None,
- /* cursor */ cur,
- /* time */ CurrentTime
- ) != GrabSuccess)
- return;
-
- XQueryPointer(blz.dpy, blz.root, &dummy, &dummy, &i, &i, &pt_x, &pt_y, &di);
-
- if(align != CENTER) {
- hr_x = dx = frect.width / 2;
- hr_y = dy = frect.height / 2;
- if(align&NORTH) dy -= hr_y;
- if(align&SOUTH) dy += hr_y;
- if(align&EAST) dx += hr_x;
- if(align&WEST) dx -= hr_x;
- XTranslateCoordinates(blz.dpy, c->framewin, blz.root, dx, dy,
- &pt_x, &pt_y, &dummy);
- XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, pt_x, pt_y);
- }
- else if(!grabbox) {
- hr_x = screen->rect.width / 2;
- hr_y = screen->rect.height / 2;
- XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, hr_x, hr_y);
- flushevents(PointerMotionMask, False);
- }
-
-
- XSync(blz.dpy, False);
- if(!grabbox) {
- XGrabServer(blz.dpy);
- draw_xor_border(&frect);
- }else
- unmap_client(c, IconicState);
-
- for(;;) {
- XMaskEvent(blz.dpy, MouseMask | ExposureMask, &ev);
- switch (ev.type) {
- case ButtonRelease:
- if(!grabbox)
- draw_xor_border(&frect);
-
- if(!floating)
- resize_column(c, &frect);
- else
- resize_client(c, &frect);
-
- if(!grabbox) {
- if(align != CENTER)
- XTranslateCoordinates(blz.dpy, c->framewin, blz.root,
- (frect.width * rx), (frect.height * ry),
- &pt_x, &pt_y, &dummy);
- if(pt_y > screen->brect.y)
- pt_y = screen->brect.y - 1;
- XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, pt_x, pt_y);
- XUngrabServer(blz.dpy);
- }else
- map_client(c);
-
- if(rects)
- free(rects);
-
- XUngrabPointer(blz.dpy, CurrentTime);
- XSync(blz.dpy, False);
- return;
- case MotionNotify:
- ofrect = frect;
- dx = ev.xmotion.x_root;
- dy = ev.xmotion.y_root;
-
- if(align == CENTER && !grabbox) {
- if(dx == hr_x && dy == hr_y)
- continue;
- XWarpPointer(blz.dpy, None, blz.root, 0, 0, 0, 0, hr_x, hr_y);
- dx -= hr_x;
- dy -= hr_y;
- }else{
- dx -= pt_x;
- dy -= pt_y;
- }
- pt_x += dx;
- pt_y += dy;
-
- rect_morph_xy(&origin, dx, dy, &align);
- if(align != CENTER)
- check_frame_constraints(&origin);
- frect = origin;
-
- if(floating)
- grav = snap_rect(rects, num, &frect, &align, snap);
- else
- grav = align ^ CENTER;
-
- apply_sizehints(c, &frect, floating, True, grav);
-
- if(grabbox) {
- XMoveWindow(blz.dpy, c->framewin, frect.x, frect.y);
- XSync(blz.dpy, False);
- } else {
- draw_xor_border(&ofrect);
- draw_xor_border(&frect);
- }
- break;
- case Expose:
- (handler[Expose])(&ev);
- break;
- default:
- break;
- }
- }
-}
-
-void
-grab_button(Window w, uint button, ulong mod) {
- XGrabButton(blz.dpy, button, mod, w, False, ButtonMask,
- GrabModeSync, GrabModeSync, None, None);
- if((mod != AnyModifier) && num_lock_mask) {
- XGrabButton(blz.dpy, button, mod | num_lock_mask, w, False, ButtonMask,
- GrabModeSync, GrabModeAsync, None, None);
- XGrabButton(blz.dpy, button, mod | num_lock_mask | LockMask, w, False,
- ButtonMask, GrabModeSync, GrabModeAsync, None, None);
- }
-}
diff -r 7ce25d709bbe -r de2320e9f616 printevent.c
--- a/printevent.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,997 +0,0 @@
-/*
- * Original code posted to comp.sources.x
- * Modifications by Russ Cox <rsc_AT_swtch.com>.
- */
-
-/*
-Path: uunet!wyse!mikew
-From: mikew_AT_wyse.wyse.com (Mike Wexler)
-Newsgroups: comp.sources.x
-Subject: v02i056: subroutine to print events in human readable form, Part01/01
-Message-ID: <1935_AT_wyse.wyse.com>
-Date: 22 Dec 88 19:28:25 GMT
-Organization: Wyse Technology, San Jose
-Lines: 1093
-Approved: mikew_AT_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_AT_richsun.UUCP
-*/
-
-#include <stdio.h>
-#include <X11/Intrinsic.h>
-#include <X11/Xproto.h>
-#include "wmii.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)
-{
- ulong msec;
- ulong sec;
- ulong min;
- ulong hr;
- ulong 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
-{
- uint value;
- char *string;
-};
-
-/* Returns the string equivalent of a mask of buttons and/or modifier keys */
-static char*
-ButtonAndOrModifierState(uint 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(uint 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)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
- fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
- fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
- fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
- fprintf(stderr, "is_hint=%s%s", IsHint(ev->is_hint), sep);
- fprintf(stderr, "same_screen=%s\n", TorF(ev->same_screen));
-}
-
-static void
-VerbButton(XButtonEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
- fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
- fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
- fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
- fprintf(stderr, "button=%s%s", ButtonAndOrModifierState(ev->button), sep);
- fprintf(stderr, "same_screen=%s\n", TorF(ev->same_screen));
-}
-
-static void
-VerbColormap(XColormapEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "colormap=%s%s", MaybeNone(ev->colormap), sep);
- fprintf(stderr, "new=%s%s", TorF(ev->new), sep);
- fprintf(stderr, "state=%s\n", ColormapState(ev->state));
-}
-
-static void
-VerbCrossing(XCrossingEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
- fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
- fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
- fprintf(stderr, "mode=%s%s", GrabMode(ev->mode), sep);
- fprintf(stderr, "detail=%s%s", CrossingDetail(ev->detail), sep);
- fprintf(stderr, "same_screen=%s%s", TorF(ev->same_screen), sep);
- fprintf(stderr, "focus=%s%s", TorF(ev->focus), sep);
- fprintf(stderr, "state=%s\n", ButtonAndOrModifierState(ev->state));
-}
-
-static void
-VerbExpose(XExposeEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
- fprintf(stderr, "count=%d\n", ev->count);
-}
-
-static void
-VerbGraphicsExpose(XGraphicsExposeEvent *ev)
-{
- fprintf(stderr, "drawable=0x%x%s", (int)ev->drawable, sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
- fprintf(stderr, "major_code=%s%s", MajorCode(ev->major_code), sep);
- fprintf(stderr, "minor_code=%d\n", ev->minor_code);
-}
-
-static void
-VerbNoExpose(XNoExposeEvent *ev)
-{
- fprintf(stderr, "drawable=0x%x%s", (int)ev->drawable, sep);
- fprintf(stderr, "major_code=%s%s", MajorCode(ev->major_code), sep);
- fprintf(stderr, "minor_code=%d\n", ev->minor_code);
-}
-
-static void
-VerbFocus(XFocusChangeEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "mode=%s%s", GrabMode(ev->mode), sep);
- fprintf(stderr, "detail=%s\n", FocusChangeDetail(ev->detail));
-}
-
-static void
-VerbKeymap(XKeymapEvent *ev)
-{
- int i;
-
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "key_vector=");
- for (i = 0; i < 32; i++)
- fprintf(stderr, "%02x", ev->key_vector[i]);
- fprintf(stderr, "\n");
-}
-
-static void
-VerbKey(XKeyEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
- if(ev->subwindow)
- fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
- fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
- fprintf(stderr, "[%d,%d]%s", ev->x, ev->y, sep);
- fprintf(stderr, "root=[%d,%d]%s", ev->x_root, ev->y_root, sep);
- if(ev->state)
- fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
- fprintf(stderr, "keycode=%s%s", Keycode(ev), sep);
- if(!ev->same_screen)
- fprintf(stderr, "!same_screen");
- fprintf(stderr, "\n");
- return;
-
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "root=0x%x%s", (int)ev->root, sep);
- fprintf(stderr, "subwindow=0x%x%s", (int)ev->subwindow, sep);
- fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
- fprintf(stderr, "state=%s%s", ButtonAndOrModifierState(ev->state), sep);
- fprintf(stderr, "keycode=%s%s", Keycode(ev), sep);
- fprintf(stderr, "same_screen=%s\n", TorF(ev->same_screen));
-}
-
-static void
-VerbProperty(XPropertyEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "atom=%s%s", AtomName(ev->display, ev->atom), sep);
- fprintf(stderr, "time=%s%s", ServerTime(ev->time), sep);
- fprintf(stderr, "state=%s\n", PropertyState(ev->state));
-}
-
-static void
-VerbResizeRequest(XResizeRequestEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "width=%d height=%d\n", ev->width, ev->height);
-}
-
-static void
-VerbCirculate(XCirculateEvent *ev)
-{
- fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "place=%s\n", Place(ev->place));
-}
-
-static void
-VerbConfigure(XConfigureEvent *ev)
-{
- fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
- fprintf(stderr, "border_width=%d%s", ev->border_width, sep);
- fprintf(stderr, "above=%s%s", MaybeNone(ev->above), sep);
- fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
-}
-
-static void
-VerbCreateWindow(XCreateWindowEvent *ev)
-{
- fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
- fprintf(stderr, "border_width=%d%s", ev->border_width, sep);
- fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
-}
-
-static void
-VerbDestroyWindow(XDestroyWindowEvent *ev)
-{
- fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
- fprintf(stderr, "window=0x%x\n", (int)ev->window);
-}
-
-static void
-VerbGravity(XGravityEvent *ev)
-{
- fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "x=%d y=%d\n", ev->x, ev->y);
-}
-
-static void
-VerbMap(XMapEvent *ev)
-{
- fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
-}
-
-static void
-VerbReparent(XReparentEvent *ev)
-{
- fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "override_redirect=%s\n", TorF(ev->override_redirect));
-}
-
-static void
-VerbUnmap(XUnmapEvent *ev)
-{
- fprintf(stderr, "event=0x%x%s", (int)ev->event, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "from_configure=%s\n", TorF(ev->from_configure));
-}
-
-static void
-VerbCirculateRequest(XCirculateRequestEvent *ev)
-{
- fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "place=%s\n", Place(ev->place));
-}
-
-static void
-VerbConfigureRequest(XConfigureRequestEvent *ev)
-{
- fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "x=%d y=%d%s", ev->x, ev->y, sep);
- fprintf(stderr, "width=%d height=%d%s", ev->width, ev->height, sep);
- fprintf(stderr, "border_width=%d%s", ev->border_width, sep);
- fprintf(stderr, "above=%s%s", MaybeNone(ev->above), sep);
- fprintf(stderr, "detail=%s%s", ConfigureDetail(ev->detail), sep);
- fprintf(stderr, "value_mask=%s\n", ConfigureValueMask(ev->value_mask));
-}
-
-static void
-VerbMapRequest(XMapRequestEvent *ev)
-{
- fprintf(stderr, "parent=0x%x%s", (int)ev->parent, sep);
- fprintf(stderr, "window=0x%x\n", (int)ev->window);
-}
-
-static void
-VerbClient(XClientMessageEvent *ev)
-{
- int i;
-
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "message_type=%s%s", AtomName(ev->display, ev->message_type), sep);
- fprintf(stderr, "format=%d\n", ev->format);
- fprintf(stderr, "data (shown as longs)=");
- for (i = 0; i < 5; i++)
- fprintf(stderr, " 0x%08lx", ev->data.l[i]);
- fprintf(stderr, "\n");
-}
-
-static void
-VerbMapping(XMappingEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "request=%s%s", MappingRequest(ev->request), sep);
- fprintf(stderr, "first_keycode=0x%x%s", ev->first_keycode, sep);
- fprintf(stderr, "count=0x%x\n", ev->count);
-}
-
-static void
-VerbSelectionClear(XSelectionClearEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "selection=%s%s", AtomName(ev->display, ev->selection), sep);
- fprintf(stderr, "time=%s\n", ServerTime(ev->time));
-}
-
-static void
-VerbSelection(XSelectionEvent *ev)
-{
- fprintf(stderr, "requestor=0x%x%s", (int)ev->requestor, sep);
- fprintf(stderr, "selection=%s%s", AtomName(ev->display, ev->selection), sep);
- fprintf(stderr, "target=%s%s", AtomName(ev->display, ev->target), sep);
- fprintf(stderr, "property=%s%s", AtomName(ev->display, ev->property), sep);
- fprintf(stderr, "time=%s\n", ServerTime(ev->time));
-}
-
-static void
-VerbSelectionRequest(XSelectionRequestEvent *ev)
-{
- fprintf(stderr, "owner=0x%x%s", (int)ev->owner, sep);
- fprintf(stderr, "requestor=0x%x%s", (int)ev->requestor, sep);
- fprintf(stderr, "selection=%s%s", AtomName(ev->display, ev->selection), sep);
- fprintf(stderr, "target=%s%s", AtomName(ev->display, ev->target), sep);
- fprintf(stderr, "property=%s%s", AtomName(ev->display, ev->property), sep);
- fprintf(stderr, "time=%s\n", ServerTime(ev->time));
-}
-
-static void
-VerbVisibility(XVisibilityEvent *ev)
-{
- fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
- fprintf(stderr, "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;
- char *name;
-
- if(ev->window) {
- XFetchName(blz.dpy, ev->window, &name);
- if(name) {
- fprintf(stderr, "\ttitle=%s\n", name);
- XFree(name);
- }
- }
- fprintf(stderr, "%3ld %-20s ", ev->serial, eventtype(e));
- if(ev->send_event)
- fprintf(stderr, "(sendevent) ");
- if(0){
- fprintf(stderr, "type=%s%s", eventtype(e), sep);
- fprintf(stderr, "serial=%lu%s", ev->serial, sep);
- fprintf(stderr, "send_event=%s%s", TorF(ev->send_event), sep);
- fprintf(stderr, "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;
- }
-}
-
diff -r 7ce25d709bbe -r de2320e9f616 printevent.h
--- a/printevent.h Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-char *eventtype(XEvent*);
-void printevent(XEvent*);
diff -r 7ce25d709bbe -r de2320e9f616 rule.c
--- a/rule.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright ©2006 Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include "wmii.h"
-
-/* basic rule matching language /regex/ -> value
- * regex might contain POSIX regex syntax defined in regex(3) */
-enum {
- IGNORE,
- REGEX,
- VALUE
-};
-
-void
-trim(char *str, const char *chars) {
- const char *cp;
- char *sp, *sn;
-
- for(cp = chars; *cp; cp++) {
- for(sp = sn = str; *sn; sn++) {
- if(*sn != *cp)
- *(sp++) = *sn;
- }
- *sp = 0;
- }
-}
-
-void
-update_rules(Rule **rule, const char *data) {
- int mode = IGNORE;
- Rule *rul;
- char *p, *r = nil, *v = nil, regex[256], value[256];
-
- if(!data || !strlen(data))
- return;
- while((rul = *rule)) {
- *rule = rul->next;
- regfree(&rul->regex);
- free(rul);
- }
- for(p = (char *)data; *p; p++)
- switch(mode) {
- case IGNORE:
- if(*p == '/') {
- mode = REGEX;
- r = regex;
- }
- else if(*p == '>') {
- mode = VALUE;
- value[0] = 0;
- v = value;
- }
- break;
- case REGEX:
- if(*p == '/') {
- mode = IGNORE;
- *r = 0;
- }
- else {
- *r = *p;
- r++;
- }
- break;
- case VALUE:
- if(*p == '\n' || *p == 0) {
- *rule = emallocz(sizeof(Rule));
- *v = 0;
- trim(value, " \t/");
- if(!regcomp(&(*rule)->regex, regex, 0)) {
- strncpy((*rule)->value, value, sizeof(rul->value));
- rule = &(*rule)->next;
- }
- else free(*rule);
- mode = IGNORE;
- }
- else {
- *v = *p;
- v++;
- }
- break;
- }
-}
diff -r 7ce25d709bbe -r de2320e9f616 util.c
--- a/util.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/* Written by Kris Maglione <fbsdaemon at gmail dot com> */
-/* Public domain */
-#include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "wmii.h"
-
-void
-fatal(const char *fmt, ...) {
- va_list ap;
- int err;
-
- err = errno;
- fprintf(stderr, "wmii: fatal: ");
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- if(fmt[strlen(fmt)-1] == ':')
- fprintf(stderr, " %s\n", strerror(err));
- else
- fprintf(stderr, "\n");
-
- exit(1);
-}
-
-/* Can't malloc */
-void
-mfatal(char *name, uint size) {
- const char
- couldnot[] = "wmii: fatal: Could not ",
- paren[] = "() ",
- bytes[] = " bytes\n";
- char sizestr[8];
- int i;
-
- i = sizeof(sizestr);
- do {
- sizestr[--i] = '0' + (size%10);
- size /= 10;
- } while(size > 0);
-
- write(1, couldnot, sizeof(couldnot)-1);
- write(1, name, strlen(name));
- write(1, paren, sizeof(paren)-1);
- write(1, sizestr+i, sizeof(sizestr)-i);
- write(1, bytes, sizeof(bytes)-1);
-
- exit(1);
-}
-
-void *
-emalloc(uint size) {
- void *ret = malloc(size);
- if(!ret)
- mfatal("malloc", size);
- return ret;
-}
-
-void *
-emallocz(uint size) {
- void *ret = emalloc(size);
- memset(ret, 0, size);
- return ret;
-}
-
-void *
-erealloc(void *ptr, uint size) {
- void *ret = realloc(ptr, size);
- if(!ret)
- mfatal("realloc", size);
- return ret;
-}
-
-char *
-estrdup(const char *str) {
- void *ret = strdup(str);
- if(!ret)
- mfatal("strdup", strlen(str));
- return ret;
-}
-
-uint
-tokenize(char *res[], uint reslen, char *str, char delim) {
- char *s;
- uint i;
-
- i = 0;
- s = str;
- while(i < reslen && *s) {
- while(*s == delim)
- *(s++) = '\0';
- if(*s)
- res[i++] = s;
- while(*s && *s != delim)
- s++;
- }
- return i;
-}
-
-int
-max(int a, int b) {
- if(a > b)
- return a;
- return b;
-}
-
-int
-min(int a, int b) {
- if(a < b)
- return a;
- return b;
-}
-
-char *
-str_nil(char *s) {
- if(s)
- return s;
- return "<nil>";
-}
-
-uint
-strlcat(char *dst, const char *src, uint size) {
- const char *s;
- char *d;
- int n, len;
-
- d = dst;
- s = src;
- n = size;
- while(n-- > 0 && *d != '\0')
- d++;
- len = n;
-
- while(*s != '\0') {
- if(n-- > 0)
- *d++ = *s;
- s++;
- }
- if(len > 0)
- *d = '\0';
- return size - n - 1;
-}
diff -r 7ce25d709bbe -r de2320e9f616 util/compile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/util/compile Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,20 @@
+#!/bin/sh -f
+
+outfile="$1"; shift
+
+# Derived from Russ Cox's 9c in plan9port.
+
+xtmp=/tmp/cc.$$.$USER.out
+
+echo CC ${BASE}$outfile
+$CC -o $outfile $CFLAGS $@ 2>$xtmp
+status=$?
+
+cat $xtmp \
+| egrep -v ': error: .Each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: In function |: At top level:|support .long long.|In file included from| from|use of C99 long long|ISO C forbids conversion' \
+| sed 's/ .first use in this function.$//; s/\"\([^\"][^\"]*\)\", line \([0-9][0-9]*\)/\1:\2/g' \
+| uniq 1>&2
+
+rm -f $xtmp $xtmp.status
+exit $status
+
diff -r 7ce25d709bbe -r de2320e9f616 util/link
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/util/link Mon Mar 26 00:48:00 2007 -0400
@@ -0,0 +1,31 @@
+#!/bin/sh -f
+
+outfile="$1"; shift
+
+# Derived from Russ Cox's 9l in plan9port.
+ofiles=""
+args=""
+for i
+do
+ case "$i" in
+ *.[ao])
+ ofiles="$ofiles $i"
+ ;;
+ *)
+ args="$args $i"
+ ;;
+ esac
+done
+
+xtmp=/tmp/ld.$$.$USER.out
+
+echo LD ${BASE}$outfile
+$LD -o $outfile $ofiles $LDFLAGS $args >$xtmp 2>&1
+status=$?
+
+sed 's/.*: In function `[^:]*: *//' $xtmp | egrep . |
+egrep -v 'is almost always misused|is dangerous, better use'
+rm -f $xtmp
+
+exit $status
+
diff -r 7ce25d709bbe -r de2320e9f616 view.c
--- a/view.c Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,446 +0,0 @@
-/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon_AT_gmail.com>
- * See LICENSE file for license details.
- */
-#include <stdlib.h>
-#include <string.h>
-#include "wmii.h"
-
-static Bool
-is_empty(View *v) {
- Area *a;
- for(a=v->area; a; a=a->next)
- if(a->frame)
- return False;
- return True;
-}
-
-Frame *
-clientframe_of_view(View *v, Client *c) {
- Frame *f;
- for(f=c->frame; f; f=f->cnext)
- if(f->area->view == v)
- break;
- return f;
-}
-
-static void
-assign_sel_view(View *v) {
- if(screen->sel != v) {
- if(screen->sel)
- write_event("UnfocusTag %s\n",screen->sel->name);
- screen->sel = v;
- write_event("FocusTag %s\n", screen->sel->name);
- }
-}
-
-Client *
-sel_client_of_view(View *v) {
- return v->sel && v->sel->sel ? v->sel->sel->client : nil;
-}
-
-View *
-get_view(const char *name) {
- View *v;
- int cmp;
-
- for(v = view; v; v=v->next)
- if((cmp=strcmp(name, v->name)) >= 0)
- break;
- if(!v || cmp != 0)
- v = create_view(name);
- return v;
-}
-
-View *
-create_view(const char *name) {
- static ushort id = 1;
- View **i, *v = emallocz(sizeof(View));
-
- v->id = id++;
- strncpy(v->name, name, sizeof(v->name));
- create_area(v, nil, 0);
- create_area(v, v->area, 0);
- for(i=&view; *i; i=&(*i)->next)
- if(strcmp((*i)->name, name) < 0) break;
- v->next = *i;
- *i = v;
- write_event("CreateTag %s\n", v->name);
- if(!screen->sel)
- assign_sel_view(v);
- return v;
-}
-
-void
-destroy_view(View *v) {
- Area *a;
- View **i, *tv;
-
- while((a = v->area)) {
- v->area = a->next;
- destroy_area(a);
- };
- for(i=&view; *i; i=&(*i)->next)
- if(*i == v) break;
- *i = v->next;
- write_event("DestroyTag %s\n", v->name);
- if(v == screen->sel) {
- for(tv=view; tv && tv->next; tv=tv->next)
- if(tv->next == *i) break;
- if(tv)
- focus_view(screen, tv);
- }
- free(v);
-}
-
-static void
-update_frame_selectors(View *v) {
- Area *a;
- Frame *f;
-
- for(a=v->area; a; a=a->next)
- for(f=a->frame; f; f=f->anext)
- f->client->sel = f;
-}
-
-void
-focus_view(WMScreen *s, View *v) {
- View *old;
- Frame *f;
- Client *c;
-
- old = screen->sel;
- XGrabServer(blz.dpy);
- assign_sel_view(v);
- update_frame_selectors(v);
- for(c=client; c; c=c->next)
- if((f = c->sel)) {
- if(f->view == v) {
- resize_client(c, &f->rect);
- update_client_grab(c);
- } else {
- unmap_frame(c);
- unmap_client(c, IconicState);
- }
- }
- restack_view(v);
- focus_area(v->sel);
- draw_frames();
- XSync(blz.dpy, False);
- XUngrabServer(blz.dpy);
- flushevents(EnterWindowMask, False);
-}
-
-void
-select_view(const char *arg) {
- char buf[256];
-
- strncpy(buf, arg, sizeof(buf));
- trim(buf, " \t+/");
- if(!strlen(buf))
- return;
- if(!strncmp(buf, ".", 2) || !strncmp(buf, "..", 3))
- return;
- assign_sel_view(get_view(buf));
- update_views(); /* performs focus_view */
-}
-
-void
-attach_to_view(View *v, Frame *f) {
- Client *c = f->client;
-
- c->revert = nil;
- if(c->trans || c->floating || c->fixedsize || c->fullscreen)
- v->sel = v->area;
- else if(starting && v->sel->floating)
- v->sel = v->area->next;
- attach_to_area(v->sel, f, False);
-}
-
-void
-restack_view(View *v) {
- Area *a;
- Frame *f;
- Client *c;
- uint n, i;
- static Window *wins = nil;
- static uint winssz = 0;
-
- if(v != screen->sel)
- return;
-
- i = 0;
- n = 0;
-
- for(c=client; c; c=c->next)
- i++;
- if(i == 0)
- return;
- if(i >= winssz) {
- winssz = 2 * i;
- wins = erealloc(wins, sizeof(Window) * winssz);
- }
-
- for(f=v->area->stack; f; f=f->snext)
- if(f->client->fullscreen)
- wins[n++] = f->client->framewin;
- wins[n++] = screen->barwin;
- for(f=v->area->stack; f; f=f->snext)
- if(!f->client->fullscreen)
- wins[n++] = f->client->framewin;
- for(a=v->area->next; a; a=a->next) {
- if(a->frame) {
- wins[n++] = a->sel->client->framewin;
- for(f=a->frame; f; f=f->anext)
- if(f != a->sel)
- wins[n++] = f->client->framewin;
- }
- }
- if(n)
- XRestackWindows(blz.dpy, wins, n);
-}
-
-void
-scale_view(View *v, float w) {
- uint xoff, num_col;
- uint min_width;
- Area *a;
- float scale, dx = 0;
- int wdiff = 0;
-
- min_width = screen->rect.width/NCOL;
-
- if(!v->area->next)
- return;
-
- num_col = 0;
- for(a=v->area->next; a; a=a->next)
- num_col++, dx += a->rect.width;
-
- scale = w / dx;
- xoff = 0;
- for(a=v->area->next; a; a=a->next) {
- a->rect.width *= scale;
- if(!a->next)
- a->rect.width = w - xoff;
- xoff += a->rect.width;
- }
- /* min_width can only be respected when there is enough space;
- * the caller should guarantee this */
- if(num_col * min_width > w)
- return;
- xoff = 0;
- for(a=v->area->next, num_col--; a; a=a->next, num_col--) {
- if(a->rect.width < min_width)
- a->rect.width = min_width;
- else if((wdiff = xoff + a->rect.width - w + num_col * min_width) > 0)
- a->rect.width -= wdiff;
- if(!a->next)
- a->rect.width = w - xoff;
- xoff += a->rect.width;
- }
-}
-
-void
-arrange_view(View *v) {
- uint xoff = 0;
- Area *a;
-
- if(!v->area->next)
- return;
- scale_view(v, screen->rect.width);
- for(a=v->area->next; a; a=a->next) {
- a->rect.x = xoff;
- a->rect.y = 0;
- a->rect.height = screen->rect.height - screen->brect.height;
- xoff += a->rect.width;
- arrange_column(a, False);
- }
-}
-
-XRectangle *
-rects_of_view(View *v, uint *num, Frame *ignore) {
- XRectangle *result;
- Frame *f;
- int i;
-
- i = 2;
- for(f=v->area->frame; f; f=f->anext)
- i++;
- result = emallocz(i * sizeof(XRectangle));
- i = 0;
- for(f=v->area->frame; f; f=f->anext)
- if(f != ignore)
- result[i++] = f->rect;
- result[i++] = screen->rect;
- result[i++] = screen->brect;
- *num = i;
- return result;
-}
-
-/* XXX: This will need cleanup */
-uchar *
-view_index(View *v) {
- uint a_i, buf_i, n;
- int len;
- Frame *f;
- Area *a;
-
- len = BUFFER_SIZE;
- buf_i = 0;
- for((a = v->area), (a_i = 0); a && len > 0; (a=a->next), (a_i++)) {
- if(a->floating)
- n = snprintf(&buffer[buf_i], len, "# ~ %d %d\n",
- a->rect.width, a->rect.height);
- else
- n = snprintf(&buffer[buf_i], len, "# %d %d %d\n",
- a_i, a->rect.x, a->rect.width);
- buf_i += n;
- len -= n;
- for(f=a->frame; f && len > 0; f=f->anext) {
- XRectangle *r = &f->rect;
- if(a->floating)
- n = snprintf(&buffer[buf_i], len, "~ 0x%x %d %d %d %d %s\n",
- (uint)f->client->win,
- r->x, r->y, r->width, r->height,
- f->client->props);
- else
- n = snprintf(&buffer[buf_i], len, "%d 0x%x %d %d %s\n",
- a_i, (uint)f->client->win, r->y,
- r->height, f->client->props);
- if(len - n < 0)
- return (uchar*)buffer;
- buf_i += n;
- len -= n;
- }
- }
- return (uchar *)buffer;
-}
-
-Client *
-client_of_message(View *v, char *message, uint *next) {
- ulong id = 0;
- Client *c;
-
- if(!strncmp(message, "sel ", 4)) {
- *next = 4;
- return sel_client_of_view(v);
- }
- sscanf(message, "0x%lx %n", &id, next);
- if(!id)
- sscanf(message, "%lu %n", &id, next);
- if(!id)
- return nil;
- for(c=client; c && c->win!=id; c=c->next);
- return c;
-}
-
-Area *
-area_of_message(View *v, char *message, uint *next) {
- uint i;
- Area *a;
-
- if(!strncmp(message, "sel ", 4)) {
- *next = 4;
- return v->sel;
- }
- if(!strncmp(message, "~ ", 2)) {
- *next = 2;
- return v->area;
- }
- if(1 != sscanf(message, "%u %n", &i, next) || i == 0)
- return nil;
- for(a=v->area; i && a; a=a->next)
- i--;
- return a;
-}
-
-char *
-message_view(View *v, char *message) {
- uint n, i;
- Client *c;
- Frame *f;
- Area *a;
- Bool swap;
- static char Ebadvalue[] = "bad value";
-
- if(!strncmp(message, "send ", 5)) {
- message += 5;
- swap = False;
- goto send;
- }
- if(!strncmp(message, "swap ", 5)) {
- message += 5;
- swap = True;
- goto send;
- }
- if(!strncmp(message, "select ", 7)) {
- message += 7;
- return select_area(v->sel, message);
- }
- if(!strncmp(message, "colmode ", 8)) {
- message += 8;
- if(!(a = area_of_message(v, message, &n)) || a == v->area)
- return Ebadvalue;
- if((i = column_mode_of_str(&message[n])) == -1)
- return Ebadvalue;
- a->mode = i;
- arrange_column(a, True);
- restack_view(v);
- if(v == screen->sel)
- focus_view(screen, v);
- draw_frames();
- return nil;
- }
- return Ebadvalue;
-
-send:
- if(!(c = client_of_message(v, message, &n)))
- return Ebadvalue;
- if(!(f = clientframe_of_view(v, c)))
- return Ebadvalue;
- return send_client(f, &message[n], swap);
-}
-
-void
-update_views() {
- View *n, *v;
- View *old = screen->sel;
-
- for(v=view; v; v=v->next)
- update_frame_selectors(v);
- if(old && !strncmp(old->name, "nil", 4))
- old = nil;
- for((v=view) && (n=v->next); v; (v=n) && (n=v->next))
- if((v != old) && is_empty(v))
- destroy_view(v);
- if(old)
- focus_view(screen, old);
- else if(screen->sel)
- focus_view(screen, screen->sel);
-}
-
-uint
-newcolw_of_view(View *v) {
- Rule *r;
- Area *a;
- uint i, n;
- regmatch_t tmpregm;
-
- for(r=def.colrules.rule; r; r=r->next) {
- if(!regexec(&r->regex, v->name, 1, &tmpregm, 0)) {
- char buf[256];
- char *toks[16];
- strncpy(buf, r->value, sizeof(buf));
- n = tokenize(toks, 16, buf, '+');
- for(a=v->area, i=0; a; a=a->next)
- i++;
- if(n && n >= i) {
- if(sscanf(toks[i - 1], "%u", &n) == 1)
- return (screen->rect.width * n) / 100;
- }
- break;
- }
- }
- return 0;
-}
diff -r 7ce25d709bbe -r de2320e9f616 wmii.1
--- a/wmii.1 Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-.TH WMII 1 wmii-VERSION
-.SH NAME
-wmii \(em window manager improved\(emimproved
-.SH SYNOPSIS
-.B wmii
-.SH DESCRIPTION
-.SS Overview
-.B wmii
-is a dynamic window manager for X11. See
-.BR wmiiwm (1)
-for more info.
-.SS Actions
-An action is a shell script in the default setup, but it can actually be
-any executable file. It is executed usually by selecting it from the
-actions menu.
-You can customize an action by copying it from the global action
-directory CONFPREFIX/wmii-3.5 to $HOME/.wmii-3.5 and then editing the copy to
-fit your needs. Of course you can also create your own actions there; make
-sure that they are executable.
-.P
-Here is a list of the default actions:
-.TP 2
-quit
-leave the window manager nicely
-.TP 2
-status
-periodically print date and load average to the bar
-.TP 2
-welcome
-display a welcome message that contains the wmii tutorial
-.TP 2
-wmiirc
-configure wmii
-.SS Default Key Bindings
-.PD 0
-.B Moving Around
-.RS 2
-.TP 16
-.I Key
-.I Action
-.TP
-.B Mod-h
-Move to a
-.B window
-to the
-.B left
-of the one currently focused
-.TP
-.B Mod-l
-Move to a
-.B window
-to the
-.B right
-of the one currently focused
-.TP
-.B Mod-j
-Move to a
-.B window below
-the one currently focused
-.TP
-.B Mod-k
-Move to a
-.B window above
-the one currently focused
-.TP
-.B Mod-space
-.B Toggle
-between the managed and floating
-.B layer
-.TP
-.BI Mod-t \ tag
-Move to the
-.B view
-of the given
-.I tag
-.TP
-.B Mod-[0-9]
-Move to the
-.B view
-with the given number
-.PD 1
-.P
-.RE
-.B Moving Things Around
-.RS 2
-.PD 0
-.TP 16
-.I Key
-.I Action
-.TP
-.B Mod-Shift-h
-Move the current window
-.B window
-to a column on the
-.B left
-.TP
-.B Mod-Shift-l
-Move the current window
-.B window
-to a column on the
-.B right
-.TP
-.B Mod-Shift-j
-Move the current
-.B window below
-the one beneath it
-.TP
-.B Mod-Shift-k
-Move the current
-.B window above
-the one above it
-.TP
-.B Mod-Shift-space
-.B Toggle
-the current
-.B window
-between the managed and floating
-.B layer
-.TP
-.BI Mod-Shift-t \ tag
-Move the current window to the
-.B view
-of the given
-.I tag
-.TP
-.B Mod-Shift-[0-9]
-Move to the current window to the
-.B view
-with the given number
-.PD 1
-.P
-.RE
-.B Miscellaneous
-.RS 2
-.PD 0
-.TP 16
-.I Key
-.I Action
-.TP
-.B Mod-m
-Switch the current column to
-.B max mode
-.TP
-.B Mod-s
-Switch the current column to
-.B stack mode
-.TP
-.B Mod-d
-Switch the current column to
-.B default mode
-.TP
-.B Mod-Shift-c
-.B Kill
-the selected client
-.TP
-.BI Mod-p \ program
-.B Execute
-.I program
-.TP
-.BI Mod-a \ action
-Execute the
-.B named action
-.TP
-.B Mod-Enter
-Start an
-.B xterm
-
-.SS Configuration
-If you feel the need to change the default configuration, then customize (as
-described above) the
-.B wmiirc
-action. This action is executed at the end of the
-.B wmii
-script and does all the work of setting up the window manager, the key
-bindings, the bar labels, etc.
-.SH FILES
-.TP
-/tmp/ns.$USER.${DISPLAY%.0}/wmii
-The wmii socket file which provides a 9P service.
-.TP
-CONFPREFIX/wmii-3.5
-Global action directory.
-.TP
-$HOME/.wmii-3.5
-User-specific action directory. Actions are first searched here.
-.SH ENVIRONMENT
-.TP
-HOME, DISPLAY
-See the section
-.B FILES
-above.
-.P
-The following variables are set and exported within
-.B wmii
-and thus can be used in actions:
-.TP
-WMII_ADDRESS
-Socket file of
-.BR wmiiwm (1).
-Used by
-.BR wmiir (1).
-.SH SEE ALSO
-.BR wmiiwm (1),
-.BR dmenu (1),
-.BR wmiir (1)
diff -r 7ce25d709bbe -r de2320e9f616 wmii.eps
--- a/wmii.eps Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-%!PS-Adobe-2.0 EPSF-1.2
-%%BoundingBox: -1 0 51 27
-%%Creator: MetaPost
-%%CreationDate: 2007.02.27:1944
-%%Pages: 1
-%%EndProlog
-%%Page: 1 1
- 0 6.23616 dtransform truncate idtransform setlinewidth pop [] 0 setdash
- 0 setlinecap 2 setlinejoin 10 setmiterlimit
-newpath 2.83461 17.00761 moveto
-2.83461 2.83461 lineto
-14.17302 2.83461 lineto
-14.17302 17.00761 lineto
-14.17302 2.83461 lineto
-25.51143 2.83461 lineto
-25.51143 14.173 lineto
-36.84984 14.173 lineto stroke
- 0 setlinejoin
-newpath 36.84984 14.173 moveto
-36.84984 0 lineto
-36.84984 14.173 lineto
-48.18825 14.173 lineto
-48.18825 0 lineto stroke
-newpath 36.84984 20.40916 moveto
-36.84984 26.07837 lineto stroke
-newpath 48.18825 20.40916 moveto
-48.18825 26.07837 lineto stroke
-showpage
-%%EOF
diff -r 7ce25d709bbe -r de2320e9f616 wmii.h
--- a/wmii.h Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,451 +0,0 @@
-/*
- * © 2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <stdio.h>
-#include <regex.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include <ixp.h>
-
-#define nil ((void*)0)
-#define nelem(ary) (sizeof(ary) / sizeof(*ary))
-
-/* Types */
-#undef uchar
-#undef ushort
-#undef uint
-#undef ulong
-#undef uvlong
-#undef vlong
-#define uchar _wmiiuchar
-#define ushort _wmiiushort
-#define uint _wmiiuint
-#define ulong _wmiiulong
-#define vlong _wmiivlong
-#define uvlong _wmiiuvlong
-typedef unsigned char uchar;
-typedef unsigned short ushort;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-typedef unsigned long long uvlong;
-typedef long long vlong;
-
-#define BLITZ_FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
-#define BLITZ_FOCUSCOLORS "#ffffff #335577 #447799"
-#define BLITZ_NORMCOLORS "#222222 #eeeeee #666666"
-
-typedef struct Blitz Blitz;
-typedef struct BlitzColor BlitzColor;
-typedef struct BlitzFont BlitzFont;
-typedef struct BlitzBrush BlitzBrush;
-
-struct Blitz {
- Display *dpy;
- int screen;
- Window root;
-};
-
-enum BlitzAlign {
- NORTH = 0x01,
- EAST = 0x02,
- SOUTH = 0x04,
- WEST = 0x08,
- NEAST = NORTH | EAST,
- NWEST = NORTH | WEST,
- SEAST = SOUTH | EAST,
- SWEST = SOUTH | WEST,
- CENTER = NEAST | SWEST
-};
-
-typedef enum BlitzAlign BlitzAlign;
-
-struct BlitzColor {
- vlong bg;
- vlong fg;
- vlong border;
- char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
-};
-
-struct BlitzFont {
- XFontStruct *xfont;
- XFontSet set;
- int ascent;
- int descent;
- uint height;
- char *fontstr;
-};
-
-struct BlitzBrush {
- Blitz *blitz;
- Drawable drawable;
- GC gc;
- int border;
- BlitzColor color;
- BlitzAlign align;
- BlitzFont *font;
- XRectangle rect; /* relative rect */
-};
-
-enum {
-/* WM atom */
- WMState, WMProtocols, WMDelete,
-/* NET atom */
- NetSupported, NetWMName,
-/* Other */
- TagsAtom,
-/* Last atom */
- AtomLast
-};
-
-/* Column modes */
-enum { Coldefault, Colstack, Colmax };
-
-/* Cursor */
-enum { CurNormal, CurNECorner, CurNWCorner, CurSECorner, CurSWCorner,
- CurMove, CurInput, CurInvisible, CurLast };
-
-enum { NCOL = 16 };
-enum { WM_PROTOCOL_DELWIN = 1 };
-
-/* Data Structures */
-typedef struct View View;
-typedef struct Area Area;
-typedef struct Frame Frame;
-typedef struct Client Client;
-typedef struct Key Key;
-typedef struct Bar Bar;
-typedef struct Rule Rule;
-typedef struct Ruleset Ruleset;
-typedef struct WMScreen WMScreen;
-
-struct View {
- View *next;
- char name[256];
- ushort id;
- Area *area;
- Area *sel;
- Area *revert;
-};
-
-struct Area {
- Area *next;
- Frame *frame;
- Frame *stack;
- Frame *sel;
- View *view;
- Bool floating;
- ushort id;
- int mode;
- XRectangle rect;
-};
-
-struct Frame {
- Frame *cnext;
- Frame *anext;
- Frame *snext;
- View *view;
- Area *area;
- ushort id;
- XRectangle rect;
- XRectangle crect;
- XRectangle revert;
- Client *client;
- Bool collapsed;
- XRectangle grabbox;
- XRectangle titlebar;
-};
-
-struct Client {
- Client *next;
- Area *revert;
- Frame *frame;
- Frame *sel;
- char name[256];
- char tags[256];
- char props[512];
- uint border;
- int proto;
- Bool floating;
- Bool fixedsize;
- Bool fullscreen;
- Bool urgent;
- Bool mapped;
- Bool frame_mapped;
- int unmapped;
- Window win;
- Window trans;
- Window framewin;
- Cursor cursor;
- XRectangle rect;
- XSizeHints size;
- GC gc;
-};
-
-struct Key {
- Key *next;
- Key *lnext;
- Key *tnext;
- ushort id;
- char name[128];
- ulong mod;
- KeyCode key;
-};
-
-struct Bar {
- Bar *next;
- Bar *smaller;
- char buf[280];
- char text[256];
- char name[256];
- ushort id;
- BlitzBrush brush;
-};
-
-struct Rule {
- Rule *next;
- regex_t regex;
- char value[256];
-};
-
-struct Ruleset {
- Rule *rule;
- char *string;
- uint size;
-};
-
-/* global variables */
-struct {
- BlitzColor focuscolor;
- BlitzColor normcolor;
- BlitzFont font;
- uint border;
- uint snap;
- char *keys;
- uint keyssz;
- Ruleset tagrules;
- Ruleset colrules;
- char grabmod[5];
- ulong mod;
- int colmode;
-} def;
-
-enum { BarLeft, BarRight };
-
-struct WMScreen {
- Bar *bar[2];
- View *sel;
- Client *focus;
- Client *hasgrab;
- Window barwin;
-
- XRectangle rect;
- XRectangle brect;
- BlitzBrush bbrush;
-} *screens, *screen;
-
-Client *client;
-View *view;
-Key *key;
-Client c_magic;
-Client c_root;
-
-enum { BUFFER_SIZE = 8092 };
-char buffer[BUFFER_SIZE];
-
-/* IXP */
-IXPServer srv;
-P9Srv p9srv;
-
-/* X11 */
-uint num_screens;
-Blitz blz;
-GC xorgc;
-char *user;
-Atom atom[AtomLast];
-Cursor cursor[CurLast];
-uint valid_mask;
-uint num_lock_mask;
-Bool sel_screen;
-Pixmap pmap;
-void (*handler[LASTEvent]) (XEvent *);
-
-/* Misc */
-Bool starting;
-Bool verbose;
-char *execstr;
-
-/* wm.c */
-char *message_root(char *message);
-
-/* area.c */
-Area *create_area(View *v, Area *pos, uint w);
-void destroy_area(Area *a);
-Area *area_of_id(View *t, ushort id);
-void focus_area(Area *a);
-char *select_area(Area *a, char *arg);
-void send_to_area(Area *to, Frame *f);
-void attach_to_area(Area *a, Frame *f, Bool send);
-void detach_from_area(Frame *f);
-Client *sel_client_of_area(Area *a);
-
-/* bar.c */
-Bar *create_bar(Bar **b_link, char *name);
-void destroy_bar(Bar **b_link, Bar *b);
-void draw_bar(WMScreen *s);
-void draw_border(BlitzBrush *b);
-void resize_bar();
-Bar *bar_of_name(Bar *b_link, const char *name);
-
-/* client.c */
-Client *create_client(Window w, XWindowAttributes *wa);
-void destroy_client(Client *c);
-void configure_client(Client *c);
-void prop_client(Client *c, Atom a);
-void kill_client(Client *c);
-void gravitate_client(Client *c, Bool invert);
-void map_client(Client *c);
-void unmap_client(Client *c, int state);
-void map_frame(Client *c);
-void unmap_frame(Client *c);
-void set_cursor(Client *c, Cursor cur);
-void focus_frame(Frame *f, Bool restack);
-void reparent_client(Client *c, Window w, int x, int y);
-void manage_client(Client *c);
-void focus(Client *c, Bool restack);
-void focus_client(Client *c);
-void resize_client(Client *c, XRectangle *r);
-void apply_sizehints(Client *c, XRectangle *r, Bool floating, Bool frame, BlitzAlign sticky);
-char *send_client(Frame *f, char *arg, Bool swap);
-char * message_client(Client *c, char *message);
-void move_client(Client *c, char *arg);
-void size_client(Client *c, char *arg);
-Client *sel_client();
-Frame *frame_of_win(Window w);
-Client *client_of_win(Window w);
-void update_client_grab(Client *c);
-void apply_rules(Client *c);
-void apply_tags(Client *c, const char *tags);
-
-/* column.c */
-void arrange_column(Area *a, Bool dirty);
-void resize_column(Client *c, XRectangle *r);
-int column_mode_of_str(char *arg);
-char *str_of_column_mode(int mode);
-Area *new_column(View *v, Area *pos, uint w);
-
-/* draw.c */
-int loadcolor(Blitz *blitz, BlitzColor *c);
-void draw_label(BlitzBrush *b, char *text);
-void draw_tile(BlitzBrush *b);
-void draw_rect(BlitzBrush *b);
-
-void drawbg(Display *dpy, Drawable drawable, GC gc,
- XRectangle *rect, BlitzColor c, Bool fill, Bool border);
-void drawcursor(Display *dpy, Drawable drawable, GC gc,
- int x, int y, uint h, BlitzColor c);
-uint textwidth(BlitzFont *font, char *text);
-uint textwidth_l(BlitzFont *font, char *text, uint len);
-void loadfont(Blitz *blitz, BlitzFont *font);
-uint labelh(BlitzFont *font);
-char *parse_colors(char **buf, int *buflen, BlitzColor *col);
-
-/* event.c */
-void dispatch_event(XEvent *e);
-void check_x_event(IXPConn *c);
-uint flushevents(long even_mask, Bool dispatch);
-
-/* frame.c */
-Frame *create_frame(Client *c, View *v);
-void remove_frame(Frame *f);
-void insert_frame(Frame *pos, Frame *f, Bool before);
-void resize_frame(Frame *f, XRectangle *r);
-Bool frame_to_top(Frame *f);
-void set_frame_cursor(Frame *f, int x, int y);
-void swap_frames(Frame *fa, Frame *fb);
-int frame_delta_h();
-void frame2client(XRectangle *r);
-void client2frame(XRectangle *r);
-void draw_frame(Frame *f);
-void draw_frames();
-void update_frame_widget_colors(Frame *f);
-void check_frame_constraints(XRectangle *rect);
-
-/* fs.c */
-void fs_attach(P9Req *r);
-void fs_clunk(P9Req *r);
-void fs_create(P9Req *r);
-void fs_flush(P9Req *r);
-void fs_freefid(Fid *f);
-void fs_open(P9Req *r);
-void fs_read(P9Req *r);
-void fs_remove(P9Req *r);
-void fs_stat(P9Req *r);
-void fs_walk(P9Req *r);
-void fs_write(P9Req *r);
-void write_event(char *format, ...);
-
-/* geom.c */
-Bool ptinrect(int x, int y, XRectangle * r);
-BlitzAlign quadrant(XRectangle *rect, int x, int y);
-Cursor cursor_of_quad(BlitzAlign align);
-int strtorect(XRectangle *r, const char *val);
-BlitzAlign get_sticky(XRectangle *src, XRectangle *dst);
-int r_east(XRectangle *r);
-int r_south(XRectangle *r);
-
-/* key.c */
-void kpress(Window w, ulong mod, KeyCode keycode);
-void update_keys();
-void init_lock_keys();
-ulong mod_key_of_str(char *val);
-
-/* mouse.c */
-void do_mouse_resize(Client *c, Bool grabbox, BlitzAlign align);
-void grab_mouse(Window w, ulong mod, ulong button);
-void ungrab_mouse(Window w, ulong mod, uint button);
-BlitzAlign snap_rect(XRectangle *rects, int num, XRectangle *current,
- BlitzAlign *mask, int snap);
-void grab_button(Window w, uint button, ulong mod);
-
-/* rule.c */
-void update_rules(Rule **rule, const char *data);
-void trim(char *str, const char *chars);
-
-#define strlcat wmii_strlcat
-/* util.c */
-uint tokenize(char *res[], uint reslen, char *str, char delim);
-char *estrdup(const char *str);
-void *erealloc(void *ptr, uint size);
-void *emallocz(uint size);
-void *emalloc(uint size);
-void fatal(const char *fmt, ...);
-int max(int a, int b);
-int min(int a, int b);
-char *str_nil(char *s);
-uint strlcat(char *dst, const char *src, unsigned int siz);
-
-/* view.c */
-void arrange_view(View *v);
-void scale_view(View *v, float w);
-View *get_view(const char *name);
-View *create_view(const char *name);
-void focus_view(WMScreen *s, View *v);
-void update_client_views(Client *c, char **tags);
-XRectangle *rects_of_view(View *v, uint *num, Frame *ignore);
-View *view_of_id(ushort id);
-void select_view(const char *arg);
-void attach_to_view(View *v, Frame *f);
-Client *sel_client_of_view(View *v);
-char *message_view(View *v, char *message);
-void restack_view(View *v);
-uchar *view_index(View *v);
-void destroy_view(View *v);
-void update_views();
-uint newcolw_of_view(View *v);
-
-/* wm.c */
-int wmii_error_handler(Display *dpy, XErrorEvent *error);
-int win_proto(Window w);
diff -r 7ce25d709bbe -r de2320e9f616 wmii.mp
--- a/wmii.mp Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-beginfig(1)
-%u=0.6cm;
-u=0.2cm;
-h=3u;
-space=u;
-linecap:=butt;
-linejoin:=beveled;
-pickup pencircle scaled 1.1u;
-draw (.5u,h)--(.5u,.5u)--(1.5u+space,.5u)--(1.5u+space,h)--(1.5u+space,.5u)--(2.5u+2space,.5u)\
- --(2.5u+2space,h-.5u)--(3.5u+3space,h-.5u);
-linejoin:=mitered;
-draw (3.5u+3space,h-.5u)--(3.5u+3space,0)--(3.5u+3space,h-.5u)--(4.5u+4space,h-.5u)--(4.5u+4space,0);;
-
-gap=.6u;
-draw (3.5u+3space,h+gap)--(3.5u+3space,h+u+gap);
-draw (4.5u+4space,h+gap)--(4.5u+4space,h+u+gap);
-endfig
-
-end
diff -r 7ce25d709bbe -r de2320e9f616 wmii9rc
--- a/wmii9rc Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-#!/bin/sh -f
-RC=""
-for i in "$PLAN9" P9PATHS; do
- if [ -d "$i" -a -x "$i/bin/rc" ]; then
- export PLAN9="$i"
- RC="$i/bin/rc"
- break;
- fi
-done
-
-if [ ! -n "$RC" ]; then
- exit 1
-fi
-
-if [ -n "$1" ]; then
- exec $RC $@
-else
- true
-fi
diff -r 7ce25d709bbe -r de2320e9f616 wmiiloop
--- a/wmiiloop Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#!AWKPATH -f
-BEGIN {
- arg[1] = "Nop"
- body = "";
- writekeys = "wmiir write /keys"
- print "IFS=''"
-}
-
-function addevent() {
- if(arg[1] == "Key")
- keys[arg[2]] = 1;
-
- var = arg[1] "s"
- print var "=\"$" var " " arg[2] "\""
-
- gsub("[^a-zA-Z_0-9]", "_", arg[2]);
- if(body != "")
- print arg[1] "_" arg[2] "() {" body "\n}"
-}
-
-/^(Event|Key|Action)[ \t]/ {
- addevent()
- split($0, arg)
- body = ""
-}
-/^[ \t]/ {
- body = body"\n"$0
-}
-
-END {
- addevent()
- for(key in keys)
- print key | writekeys;
- close(writekeys);
-}
diff -r 7ce25d709bbe -r de2320e9f616 wmiiloop.1
--- a/wmiiloop.1 Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-.TH WMIIR 1 wmii\-VERSION
-.SH NAME
-wmiiloop \(em wmii event loop processor
-.SH SYNOPSIS
-.B cat
-.I events
-|
-.B wmiiloop
-|
-.B sh
-.br
-.SH DESCRIPTION
-.SS Overview
-.B wmiiloop
-is an awk script which preprocesses
-.BR sh (1)
-syntax to simplify writing a wmii event loop.
-
-.br
-.B eventloop
-sends any text up to the first line containing
-.I #
-.IR Events|Actions|Key ,
-and any text after any other line begining with
-.IR # ,
-directly to its standard output. Any other line is processed based
-on its first word, with every indented line after it taken as its
-.IR body .
-.TP 2
-.BI "Key " sequence
-The key sequence
-.I sequence
-is bound to its
-.IR body .
-.I sequence
-is written to
-.I /keys
-and
-.I body
-is executed, with
-.I $key
-set to
-.I sequence
-whenever the key is pressed.
-
-.TP 2
-.BI "Event " name
-Whenever an event with
-.I name
-is read from
-.IR /event ,
-.I body
-is executed, with
-.I $event
-set to
-.IR name ,
-and
-.I $[1\-9]
-set to further arguments.
-
-.TP 2
-.BI "Action " name
-A function called
-.BI Action_ name
-is created with
-.I body
-as its body, and
-.I name
-is added to the
-.I $ACTIONS
-variable.
-
-.SH SEE ALSO
-.BR wmii (1),
-.BR wmiir (1),
-.BR wmiiwm (1)
-.B PREFIX/etc/wmiirc
-
-http://www.cs.bell\-labs.com/sys/man/5/INDEX.html
diff -r 7ce25d709bbe -r de2320e9f616 wmiir
--- a/wmiir Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-#!/bin/sh -f
-exec ixpc -a "$WMII_ADDRESS" $@
diff -r 7ce25d709bbe -r de2320e9f616 wmiir.1
--- a/wmiir.1 Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-.TH WMIIR 1 wmii-VERSION
-.SH NAME
-wmiir \(em wrapper script for ixpc
-.SH SYNOPSIS
-.B wmiir
-.RB [ \-a
-.IR address ]
-.I action
-.I file
-.br
-.B wmiir
-.B \-v
-.SH DESCRIPTION
-.SS Overview
-.B wmiir
-is a wrapper script for
-.BR ixpc (1)
-to conveniently access the filesystem of
-.BR wmiiwm (1)
-from the command line or from shell
-scripts. It can be used to configure
-.BR wmii (1).
-
-.SS Options
-See the manual page of
-.BR ixpc (1) .
-.SH ENVIRONMENT
-.TP
-WMII_ADDRESS
-The address of the wmiiwm file server to which wmiir will connect.
-.SH EXAMPLES
-.TP
-.B wmiir ls /
-This prints the root directory of the wmii filesystem. For more information
-about the contents of this filesystem, see
-.BR wmiiwm (1).
-.TP
-.B echo -n quit | wmiir write /ctl
-Write 'quit' to the main control file of the wmii filesystem, effectively
-leaving wmii.
-.TP
-.B echo -n view 2 | wmiir write /ctl
-Bring into view all clients tagged '2'. To learn about clients and
-tags, see
-.BR wmii (1).
-.SH SEE ALSO
-.BR wmii (1),
-.BR ixpc (1),
-.BR wmiiwm (1)
-
-http://www.cs.bell-labs.com/sys/man/5/INDEX.html
diff -r 7ce25d709bbe -r de2320e9f616 wmiistartrc
--- a/wmiistartrc Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-#!/bin/sh -f
-# start wmiirc
-
-export WMII_CONFPATH="$HOME/.wmii-CONFVERSION:CONFPREFIX/wmii-CONFVERSION"
-
-if wmii9rc; then
- WMIIRC=`PATH="$WMII_CONFPATH:$PATH" which rc.wmii`
-else
- WMIIRC=`PATH="$WMII_CONFPATH:$PATH" which wmiirc`
-fi
-
-mkdir $HOME/.wmii-CONFVERSION 2>/dev/null && CONFPREFIX/wmii-CONFVERSION/welcome &
-exec "$WMIIRC" $@
diff -r 7ce25d709bbe -r de2320e9f616 wmiiwm.1
--- a/wmiiwm.1 Sun Mar 25 15:16:24 2007 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-.TH WMIIWM 1 wmii-VERSION
-.SH NAME
-wmiiwm \(em window manager improved\(emimproved (core)
-.SH SYNOPSIS
-.B wmiiwm
-.B \-a
-.I <address>
-.RB [ \-c ]
-.RB [ \-v ]
-.SH DESCRIPTION
-
-.PD 0
-.SS Overview
-.BR wmiiwm (1)
-is the core of window manager improved\(emimproved.
-.P
-.B wmii
-is a dynamic window manager for X11. In contrast to static window management
-the user rarely has to think about how to organize windows, no matter what he
-is doing or how many applications are used at the same time. The window manager
-adapts to the current environment and fits to the needs of the user, rather
-than forcing him to use a preset, fixed layout and trying to shoehorn all
-windows and applications into it.
-.P
-.B wmii
-supports classic and tiled window management with extended keyboard and mouse
-control. The classic window management arranges windows in a floating layer
-in which windows can be moved and resized freely. The tiled window management
-is based on columns which split up the screen horizontally. Each column handles
-arbitrary windows and arranges them vertically in a non\-overlapping way. They
-can then be moved and resized between and within columns at will.
-.P
-.B wmii
-provides a virtual filesystem which represents the internal state similar to
-the procfs of Unix operating systems. Modifying this virtual filesystem results
-in changing the state of the window manager. The virtual filesystem service can
-be accessed through 9P\-capable client programs, like
-.BR wmiir (1) .
-This allows simple and powerful remote control of the core window manager.
-.P
-.B wmii
-basically consists of clients, columns, views, and the bar, which are described
-in detail in the
-.B Terminology
-section.
-.SS Options
-.TP
-.BI \-a " address"
-Lets you specify the address which
-.B wmiiwm
-uses to listen for connections. The syntax for
-.I address
-is taken (along with many other profound ideas) from the Plan 9 operating
-system and has the form
-.B unix!/path/to/socket
-for unix socket files, and
-.B tcp!hostname!port
-for tcp sockets.
-.TP
-.B \-c
-Checks if another window manager is running. If not it exits with termination code
-0.
-.TP
-.B \-v
-Prints version information to stdout, then exits.
-.SS Terminology
-.TP 2
-Display
-A running X server instance consisting of input devices and screens.
-.TP 2
-Screen
-A physical or virtual (Xinerama or
-.BR Xnest (1))
-screen of an X display. A screen displays a bar window and a view at a time.
-.TP 2
-Window
-A (rectangular) drawable X object which is displayed on a screen, usually an
-application window.
-.TP 2
-Client
-An application window surrounded by a frame window containing a border and a
-title\-bar.
-.TP 2
-Floating layer
-A screen layer of
-.B wmii
-on top of all other layers, where clients are arranged in a classic (floating)
-way. They can be resized or moved freely.
-.TP 2
-Managed layer
-A screen layer of
-.B wmii
-behind the floating layer, where clients are arranged in a non\-overlapping
-(managed) way. Here, the window manager dynamically assigns each client a
-size and position. The managed layer consists of columns.
-.TP 2
-Tag
-Alphanumeric strings which can be assigned to a client. This provides a
-mechanism to group clients with similar properties. Clients can have one
-tag, e.g.
-.IR work ,
-or several tags, e.g.
-.IR work+mail .
-Tags are separated with the
-.I +
-character.
-.TP 2
-View
-A set of clients containing a specific tag, quite similiar to a workspace in
-other window managers. It consists of the floating and managed layers.
-.TP 2
-Column
-A column is a screen area which arranges clients vertically in a
-non\-overlapping way. Columns provide three different modes, which arrange
-clients with equal size, stacked, or maximized respectively. Clients can be
-moved and resized between and within columns freely.
-.TP 2
-Bar
-The bar at the bottom of the screen displays a label for each view and
-allows the creation of arbitrary user\-defined labels.
-.TP 2
-Event
-An event is a message which can be read from a special file in the filesystem
-of
-.BR wmiiwm ,
-such as a mouse button press, a key press, or a message written by a different
-9P\-client.
-.SS Basic window management
-Running a raw
-.B wmiiwm
-process without the
-.BR wmii (1)
-script provides basic window management capabilities already. However to use
-it effectively, remote control through its filesystem interface is necessary.
-By default it is only usable with the mouse in conjunction with the
-.I Mod1 (Alt)
-modifier key. Other interactions like customizing the style, killing or
-retagging clients, or grabbing keys cannot be achieved without accessing the
-filesystem.
-.P
-The filesystem can be accessed by connecting to the
-.I address
-of
-.B wmiiwm
-with any 9P\-capable client, like
-.BR wmiir (1).
-.SH SEE ALSO
-.BR wmii (1),
-.BR dmenu (1),
-.BR wmiir (1)
Received on Mon Mar 26 2007 - 06:52:16 UTC
This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 15:56:24 UTC