Change 9wm to look like rio.

This commit is contained in:
rsc 2004-03-21 04:27:28 +00:00
parent ba9ffa53c4
commit 038e9089b3
14 changed files with 3458 additions and 0 deletions

118
src/cmd/rio/9wm.man Normal file
View file

@ -0,0 +1,118 @@
.if t .ds 85 8\(12
.if n .ds 85 8-1/2
.TH 9wm 1
.SH NAME
9wm \- \*(85-like Window Manager for X
.SH SYNOPSIS
.B 9wm
[
.B \-grey
] [
.B \-version
] [
.B \-font
.I fname
] [
.B \-term
.I termprog
] [
.BR exit | restart
]
.SH DESCRIPTION
.I 9wm
is a window manager for X which attempts to emulate the window management
policies of Plan 9's
.I \*(85
window manager.
.PP
The
.B \-grey
option makes the background light grey, as does \*(85.
Use this option for maximum authenticity.
.B \-font
.I fname
sets the font in
.IR 9wm 's
menu to
.IR fname ,
overriding the default.
.B \-term
.I termprog
specifies an alternative program to run when the
.I New
menu item is selected.
.B \-version
prints the current version on standard error, then exits.
.PP
To make
.I 9wm
exit, you have to run
.B "9wm exit"
on the command line. There is no ``exit'' menu item.
.PP
.I 9wm
is click-to-type: it has a notion of the current window,
which is usually on top, and always has its border darkened.
Characters typed at the keyboard go to the current window,
and mouse clicks outside the current window are swallowed up
by
.IR 9wm .
To make another window the current one, click on it with button 1.
Unlike other X window managers, 9wm implements `mouse focus': mouse events
are sent only to the current window.
.PP
A menu of window operations is available by pressing button 3
outside the current window.
The first of these,
.IR New ,
attempts to spawn a
.I 9term
process (or
.I xterm
if
.I 9term
is not available).
The new
.I 9term
will request that its outline be swept using button 3
of the mouse, by changing the cursor.
.RI ( xterm
defaults to a fixed size, and thus wants to be dragged; pressing
button 3 places it.)
.PP
The next four menu items are
.IR Reshape ,
.IR Move ,
.IR Delete ,
and
.IR Hide .
All of the operations change the cursor into a target, prompting the user
to click button 3 on one of the windows to select it for the operation.
At this stage, clicking button 1 or 2 will abort the operation.
Otherwise, if the operation was
.IR Resize ,
the user is prompted to sweep out the new outline with button 3.
If it was
.IR Move ,
the user should keep the button held down after the initial click that selected
the window, and drag the window to the right place before releasing.
In either case, button 1 or 2 will abort the operation.
.PP
If the
.I Delete
operation is selected, the window will be deleted when the button is released.
This typically kills the client that owns the window.
The
.I Hide
operation just makes the window invisible. While hidden, the window's
name appears on the bottom of the button 3 menu. Selecting that item
brings the window back (unhides it).
This operation replaces the iconification feature provided by other
window managers.
.SH BUGS
Is not completely compatible with \*(85.
.PP
There is a currently a compiled-in limit of 32 hidden windows.
.SH "SEE ALSO"
.IR 9term (1),
.IR xterm (1).

203
src/cmd/rio/README Normal file
View file

@ -0,0 +1,203 @@
This is David Hogan's 9wm updated to behave more like
Plan 9's rio. Since I cannot get approval for the changes
and I'd prefer not to resort to patches, I have renamed it "rio".
Current incompatibilities that would be nice to fix:
- Rio uses X11 fonts for the menu, and there aren't any good ones!
I'm tempted to hard-code the Plan 9 default font bitmap.
- The command-line options should be made more like Plan 9.
- Should work out a protocol between 9term and rio so that:
* 9term can tell rio to blue its border during hold mode
* rio can tell 9term to fade its text when it loses focus
* rio can tell 9term to unfade its text when it regains focus
- Should change window focus on b2/b3 clicks and then
pass along the click event to the now-focused window.
- Should change 9term to redirect b3 clicks to rio so that rio
can put up the usual b3 menu.
The original README is below.
- russ cox
rsc@swtch.com
20 march 2004
9wm Version 1.2
Copyright 1994-1996 David Hogan.
What is 9wm?
============
9wm is an X window manager which attempts to emulate the Plan 9 window
manager 8-1/2 as far as possible within the constraints imposed by X.
It provides a simple yet comfortable user interface, without garish
decorations or title-bars. Or icons. And it's click-to-type. This
will not appeal to everybody, but if you're not put off yet then read
on. (And don't knock it until you've tried it.)
One major difference between 9wm and 8-1/2 is that the latter provides
windows of text with a typescript interface, and doesn't need to run a
separate program to emulate a terminal. 9wm, as an X window manager,
does require a separate program. For better 8-1/2 emulation, you should
obtain Matthew Farrow's "9term" program (ftp://ftp.cs.su.oz.au/matty/unicode),
version 1.6 or later (earlier versions don't cooperate with 9wm in
implementing "hold mode"). Of course, you can run xterm under 9wm as well.
What is 9wm not?
================
9wm is not a virtual window manager. It is not customisable to any
great extent. It is not large and unwieldy, and doesn't use the X
toolkit. Requests to make it any of these things will be silently
ignored (or flamed if I have had a bad day :-) If you want tvtwm
or mwm, you know where to get them...
Where do I get it?
==================
The latest version of 9wm is held at ftp://ftp.cs.su.oz.au/dhog/9wm
Author
======
9wm was written by David Hogan (dhog@cs.su.oz.au), a postgraduate
student at the Basser Department of Computer Science, University
of Sydney (http://www.cs.su.oz.au/~dhog/).
Licence
=======
9wm is free software, and is Copyright (c) 1994-1996 by David Hogan.
Permission is granted to all sentient beings to use this software,
to make copies of it, and to distribute those copies, provided
that:
(1) the copyright and licence notices are left intact
(2) the recipients are aware that it is free software
(3) any unapproved changes in functionality are either
(i) only distributed as patches
or (ii) distributed as a new program which is not called 9wm
and whose documentation gives credit where it is due
(4) the author is not held responsible for any defects
or shortcomings in the software, or damages caused by it.
There is no warranty for this software. Have a nice day.
How do I compile/install it?
============================
Assuming your system is correctly configured, you should only need to
run xmkmf to generate the Makefile, and then run make or make install.
make install.man should copy the manpage (9wm.man) to the appropriate
directory.
If the make fails, complaining that the function _XShapeQueryExtension
does not exist, try removing the "-DSHAPE" from the Imakefile, and
run xmkmf and make again.
If you don't have imake, or it is misconfigured, or you would prefer
not to use it, try copying the file "Makefile.no-imake" to "Makefile",
then edit the definitions in this Makefile to suit your system. This
may require defining suitable compilation flags for your system
(normally imake does this for you). For instance, on AIX you must
include "-DBSD_INCLUDES" in CFLAGS.
How do I use it?
================
See the manual page for details. You should probably read the
man page for 9term as well.
What if I find a bug?
=====================
Please mail all bug reports to 9wm-bugs@plan9.cs.su.oz.au, so
that I can incorporate fixes into the next release. If you can
tell me how to fix it, all the better.
Known Problems/Bugs
===================
9wm tries hard to emulate 8-1/2, but isn't 100% compatible. If
you are an experienced 8-1/2 user, please be patient with it.
One intentional difference between 9wm and 8-1/2 is in the behaviour
of the menu when the last hidden item is unhidden. Under 8-1/2, when
the menu is next used, it pops up with "New" selected. Under 9wm,
the (new) last menu item will be selected. This is a feature. It
may be confusing if you frequently switch between 9wm and 8-1/2.
If you don't like this feature, email me for the one line fix.
There have been some problems encountered when resizing 9term on
some platforms. This turns out to be a problem in 9term (actually
in libXg, to be precise). Newer versions of 9term should be
immune to this, see matty@cs.su.oz.au if your 9term needs fixing.
Some client programs do weird things. One of these is Frame Maker.
It appears that if it has a modal dialog on the screen, then if any
of its windows are current, all keypresses are redirected to the
modal dialog. This is not 9wm's fault -- Frame Maker is doing this.
Programs like Netscape Navigator like to put riddiculously long
icon name properties on their windows, of the form "Netscape: blah blah".
There is no way that I know of to stop netscape from doing this. For this
reason, 9wm truncates labels at the first colon it finds. This keeps the
button 3 menu from becoming excessively wide. Note that with same
applications, you can use an iconName resource to set the label; this
works well for "xman", whose default icon name of "Manual Browser"
is a tad too long.
See Also
========
http://www.cs.su.oz.au/~dhog/
The 9wm Home Page
ftp://ftp.cs.su.oz.au/matty/unicode/
for source to 9term (get README first)
ftp://plan9.att.com/plan9/unixsrc/sam/
for source && info on Rob Pike's editor "sam"
ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/shell/rc
for information on a publically available implementation
of the Plan 9 shell "rc" for unix (or look in comp.unix.shell).
ftp://viz.tamu.edu/pub/rc
for source to the abovementioned implementation of rc.
http://plan9.att.com/plan9/
http://plan9.att.com/magic/man2html/1/8%c2%bd
for information on Plan 9 (including the 8-1/2 manual entry)
Acknowledgements
================
Thanks to Rob Pike for writing the original 8-1/2 program (and
before that, mux) which inspired the writing of 9wm.
Thanks to John Mackin, whose gwm "wool code" for emulating mux
was also an inspiration: I used it (and hacked it) until I got
too frustrated with gwm's large memory requirements and lack of
speed (sorry Colas!), and decided to write a dedicated program.
Thanks to Matthew Farrow for writing 9term.
A big thanks to Dave Edmondson for adding support for
multi-screen displays.
The following people helped beta test 9wm:
John Mackin
Noel Hunt
Fred Curtis
James Matthew Farrow
Danny Yee
Arnold Robbins
Byron Rakitzis
micro@cooper.edu

242
src/cmd/rio/client.c Normal file
View file

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

44
src/cmd/rio/color.c Normal file
View file

@ -0,0 +1,44 @@
/* Copyright (c) 2004 Russ Cox, see README for licence details */
#include <stdio.h>
#include <signal.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "dat.h"
#include "fns.h"
unsigned long
colorpixel(Display *dpy, int depth, ulong rgb)
{
int r, g, b;
r = rgb>>16;
g = (rgb>>8)&0xFF;
b = rgb&0xFF;
switch(depth){
case 1:
case 2:
case 4:
case 8:
default:
/* not going to waste color map entries */
if(rgb == 0xFFFFFF)
return WhitePixel(dpy, DefaultScreen(dpy));
return BlackPixel(dpy, DefaultScreen(dpy));
case 15:
r >>= 3;
g >>= 3;
b >>= 3;
return (r<<10) | (g<<5) | b;
case 16:
r >>= 3;
g >>= 2;
b >>= 3;
return (r<<11) | (g<<5) | b;
case 24:
case 32:
return rgb;
}
}

368
src/cmd/rio/cursor.c Normal file
View file

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

148
src/cmd/rio/dat.h Normal file
View file

@ -0,0 +1,148 @@
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#define BORDER _border
#define INSET _inset
#define MAXHIDDEN 32
#define B3FIXED 5
#define AllButtonMask (Button1Mask|Button2Mask|Button3Mask \
|Button4Mask|Button5Mask)
#define ButtonMask (ButtonPressMask|ButtonReleaseMask)
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask)
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask)
#ifdef Plan9
#define DEFSHELL "/bin/rc"
#else
#define DEFSHELL "/bin/sh"
#endif
typedef struct Client Client;
typedef struct Menu Menu;
typedef struct ScreenInfo ScreenInfo;
struct Client {
Window window;
Window parent;
Window trans;
Client *next;
Client *revert;
int x;
int y;
int dx;
int dy;
int border;
XSizeHints size;
int min_dx;
int min_dy;
int state;
int init;
int reparenting;
int is9term;
int hold;
int proto;
char *label;
char *instance;
char *class;
char *name;
char *iconname;
Colormap cmap;
int ncmapwins;
Window *cmapwins;
Colormap *wmcmaps;
ScreenInfo *screen;
};
#define hidden(c) ((c)->state == IconicState)
#define withdrawn(c) ((c)->state == WithdrawnState)
#define normal(c) ((c)->state == NormalState)
/* c->proto */
#define Pdelete 1
#define Ptakefocus 2
struct Menu {
char **item;
char *(*gen)();
int lasthit;
};
struct ScreenInfo {
int num;
int depth;
int width;
int height;
Window root;
Window menuwin;
Window sweepwin;
Colormap def_cmap;
GC gc;
GC gccopy;
GC gcred;
GC gcsweep;
GC gcmenubg;
GC gcmenubgs;
GC gcmenufg;
GC gcmenufgs;
unsigned long black;
unsigned long white;
unsigned long activeholdborder;
unsigned long inactiveholdborder;
unsigned long activeborder;
unsigned long inactiveborder;
unsigned long red;
Pixmap bkup[2];
int min_cmaps;
Cursor target;
Cursor sweep0;
Cursor boxcurs;
Cursor arrow;
Pixmap root_pixmap;
char display[256]; /* arbitrary limit */
};
/* main.c */
extern Display *dpy;
extern ScreenInfo *screens;
extern int num_screens;
extern int initting;
extern XFontStruct *font;
extern int nostalgia;
extern char **myargv;
extern Bool shape;
extern char *termprog;
extern char *shell;
extern char *version[];
extern int _border;
extern int _inset;
extern int curtime;
extern int debug;
extern int solidsweep;
extern Atom exit_9wm;
extern Atom restart_9wm;
extern Atom wm_state;
extern Atom wm_change_state;
extern Atom _9wm_hold_mode;
extern Atom wm_protocols;
extern Atom wm_delete;
extern Atom wm_take_focus;
extern Atom wm_colormaps;
/* client.c */
extern Client *clients;
extern Client *current;
/* menu.c */
extern Client *hiddenc[];
extern int numhidden;
extern char *b3items[];
extern Menu b3menu;
/* error.c */
extern int ignore_badwindow;

98
src/cmd/rio/error.c Normal file
View file

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

465
src/cmd/rio/event.c Normal file
View file

@ -0,0 +1,465 @@
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>
#include "dat.h"
#include "fns.h"
#include "patchlevel.h"
void
mainloop(int shape_event)
{
XEvent ev;
for (;;) {
getevent(&ev);
#ifdef DEBUG_EV
if (debug) {
ShowEvent(&ev);
printf("\n");
}
#endif
switch (ev.type) {
default:
#ifdef SHAPE
if (shape && ev.type == shape_event)
shapenotify((XShapeEvent *)&ev);
else
#endif
fprintf(stderr, "9wm: unknown ev.type %d\n", ev.type);
break;
case ButtonPress:
button(&ev.xbutton);
break;
case ButtonRelease:
break;
case MapRequest:
mapreq(&ev.xmaprequest);
break;
case ConfigureRequest:
configurereq(&ev.xconfigurerequest);
break;
case CirculateRequest:
circulatereq(&ev.xcirculaterequest);
break;
case UnmapNotify:
unmap(&ev.xunmap);
break;
case CreateNotify:
newwindow(&ev.xcreatewindow);
break;
case DestroyNotify:
destroy(ev.xdestroywindow.window);
break;
case ClientMessage:
clientmesg(&ev.xclient);
break;
case ColormapNotify:
cmap(&ev.xcolormap);
break;
case PropertyNotify:
property(&ev.xproperty);
break;
case SelectionClear:
fprintf(stderr, "9wm: SelectionClear (this should not happen)\n");
break;
case SelectionNotify:
fprintf(stderr, "9wm: SelectionNotify (this should not happen)\n");
break;
case SelectionRequest:
fprintf(stderr, "9wm: SelectionRequest (this should not happen)\n");
break;
case EnterNotify:
enter(&ev.xcrossing);
break;
case ReparentNotify:
reparent(&ev.xreparent);
break;
case FocusIn:
focusin(&ev.xfocus);
break;
case MotionNotify:
case Expose:
case NoExpose:
case FocusOut:
case ConfigureNotify:
case MapNotify:
case MappingNotify:
/* not interested */
trace("ignore", 0, &ev);
break;
}
}
}
void
configurereq(XConfigureRequestEvent *e)
{
XWindowChanges wc;
Client *c;
/* we don't set curtime as nothing here uses it */
c = getclient(e->window, 0);
trace("configurereq", c, e);
e->value_mask &= ~CWSibling;
if (c) {
gravitate(c, 1);
if (e->value_mask & CWX)
c->x = e->x;
if (e->value_mask & CWY)
c->y = e->y;
if (e->value_mask & CWWidth)
c->dx = e->width;
if (e->value_mask & CWHeight)
c->dy = e->height;
if (e->value_mask & CWBorderWidth)
c->border = e->border_width;
gravitate(c, 0);
if (e->value_mask & CWStackMode) {
if (wc.stack_mode == Above)
top(c);
else
e->value_mask &= ~CWStackMode;
}
if (c->parent != c->screen->root && c->window == e->window) {
wc.x = c->x-BORDER;
wc.y = c->y-BORDER;
wc.width = c->dx+2*BORDER;
wc.height = c->dy+2*BORDER;
wc.border_width = 1;
wc.sibling = None;
wc.stack_mode = e->detail;
XConfigureWindow(dpy, c->parent, e->value_mask, &wc);
sendconfig(c);
}
}
if (c && c->init) {
wc.x = BORDER;
wc.y = BORDER;
}
else {
wc.x = e->x;
wc.y = e->y;
}
wc.width = e->width;
wc.height = e->height;
wc.border_width = 0;
wc.sibling = None;
wc.stack_mode = Above;
e->value_mask &= ~CWStackMode;
e->value_mask |= CWBorderWidth;
XConfigureWindow(dpy, e->window, e->value_mask, &wc);
}
void
mapreq(XMapRequestEvent *e)
{
Client *c;
int i;
curtime = CurrentTime;
c = getclient(e->window, 0);
trace("mapreq", c, e);
if (c == 0 || c->window != e->window) {
/* workaround for stupid NCDware */
fprintf(stderr, "9wm: bad mapreq c %x w %x, rescanning\n",
c, e->window);
for (i = 0; i < num_screens; i++)
scanwins(&screens[i]);
c = getclient(e->window, 0);
if (c == 0 || c->window != e->window) {
fprintf(stderr, "9wm: window not found after rescan\n");
return;
}
}
switch (c->state) {
case WithdrawnState:
if (c->parent == c->screen->root) {
if (!manage(c, 0))
return;
break;
}
XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1);
XAddToSaveSet(dpy, c->window);
/* fall through... */
case NormalState:
XMapWindow(dpy, c->window);
XMapRaised(dpy, c->parent);
top(c);
setstate(c, NormalState);
if (c->trans != None && current && c->trans == current->window)
active(c);
break;
case IconicState:
unhidec(c, 1);
break;
}
}
void
unmap(XUnmapEvent *e)
{
Client *c;
curtime = CurrentTime;
c = getclient(e->window, 0);
if (c) {
switch (c->state) {
case IconicState:
if (e->send_event) {
unhidec(c, 0);
withdraw(c);
}
break;
case NormalState:
if (c == current)
nofocus();
if (!c->reparenting)
withdraw(c);
break;
}
c->reparenting = 0;
}
}
void
circulatereq(XCirculateRequestEvent *e)
{
fprintf(stderr, "It must be the warlock Krill!\n"); /* ☺ */
}
void
newwindow(XCreateWindowEvent *e)
{
Client *c;
ScreenInfo *s;
/* we don't set curtime as nothing here uses it */
if (e->override_redirect)
return;
c = getclient(e->window, 1);
if (c && c->window == e->window && (s = getscreen(e->parent))) {
c->x = e->x;
c->y = e->y;
c->dx = e->width;
c->dy = e->height;
c->border = e->border_width;
c->screen = s;
if (c->parent == None)
c->parent = c->screen->root;
}
}
void
destroy(Window w)
{
Client *c;
curtime = CurrentTime;
c = getclient(w, 0);
if (c == 0)
return;
rmclient(c);
/* flush any errors generated by the window's sudden demise */
ignore_badwindow = 1;
XSync(dpy, False);
ignore_badwindow = 0;
}
void
clientmesg(XClientMessageEvent *e)
{
Client *c;
curtime = CurrentTime;
if (e->message_type == exit_9wm) {
cleanup();
exit(0);
}
if (e->message_type == restart_9wm) {
fprintf(stderr, "*** 9wm restarting ***\n");
cleanup();
execvp(myargv[0], myargv);
perror("9wm: exec failed");
exit(1);
}
if (e->message_type == wm_change_state) {
c = getclient(e->window, 0);
if (e->format == 32 && e->data.l[0] == IconicState && c != 0) {
if (normal(c))
hide(c);
}
else
fprintf(stderr, "9wm: WM_CHANGE_STATE: format %d data %d w 0x%x\n",
e->format, e->data.l[0], e->window);
return;
}
fprintf(stderr, "9wm: strange ClientMessage, type 0x%x window 0x%x\n",
e->message_type, e->window);
}
void
cmap(XColormapEvent *e)
{
Client *c;
int i;
/* we don't set curtime as nothing here uses it */
if (e->new) {
c = getclient(e->window, 0);
if (c) {
c->cmap = e->colormap;
if (c == current)
cmapfocus(c);
}
else
for (c = clients; c; c = c->next) {
for (i = 0; i < c->ncmapwins; i++)
if (c->cmapwins[i] == e->window) {
c->wmcmaps[i] = e->colormap;
if (c == current)
cmapfocus(c);
return;
}
}
}
}
void
property(XPropertyEvent *e)
{
Atom a;
int delete;
Client *c;
/* we don't set curtime as nothing here uses it */
a = e->atom;
delete = (e->state == PropertyDelete);
c = getclient(e->window, 0);
if (c == 0)
return;
switch (a) {
case XA_WM_ICON_NAME:
if (c->iconname != 0)
XFree((char*) c->iconname);
c->iconname = delete ? 0 : getprop(c->window, a);
setlabel(c);
renamec(c, c->label);
return;
case XA_WM_NAME:
if (c->name != 0)
XFree((char*) c->name);
c->name = delete ? 0 : getprop(c->window, a);
setlabel(c);
renamec(c, c->label);
return;
case XA_WM_TRANSIENT_FOR:
gettrans(c);
return;
}
if (a == _9wm_hold_mode) {
c->hold = getiprop(c->window, _9wm_hold_mode);
if (c == current)
draw_border(c, 1);
}
else if (a == wm_colormaps) {
getcmaps(c);
if (c == current)
cmapfocus(c);
}
}
void
reparent(XReparentEvent *e)
{
Client *c;
XWindowAttributes attr;
ScreenInfo *s;
/* we don't set curtime as nothing here uses it */
if (!getscreen(e->event) || e->override_redirect)
return;
if ((s = getscreen(e->parent)) != 0) {
c = getclient(e->window, 1);
if (c != 0 && (c->dx == 0 || c->dy == 0)) {
XGetWindowAttributes(dpy, c->window, &attr);
c->x = attr.x;
c->y = attr.y;
c->dx = attr.width;
c->dy = attr.height;
c->border = attr.border_width;
c->screen = s;
if (c->parent == None)
c->parent = c->screen->root;
}
}
else {
c = getclient(e->window, 0);
if (c != 0 && (c->parent == c->screen->root || withdrawn(c)))
rmclient(c);
}
}
#ifdef SHAPE
void
shapenotify(XShapeEvent *e)
{
Client *c;
/* we don't set curtime as nothing here uses it */
c = getclient(e->window, 0);
if (c == 0)
return;
setshape(c);
}
#endif
void
enter(XCrossingEvent *e)
{
Client *c;
curtime = e->time;
if (e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual)
return;
c = getclient(e->window, 0);
if (c != 0 && c != current) {
/* someone grabbed the pointer; make them current */
XMapRaised(dpy, c->parent);
top(c);
active(c);
}
}
void
focusin(XFocusChangeEvent *e)
{
Client *c;
curtime = CurrentTime;
if (e->detail != NotifyNonlinearVirtual)
return;
c = getclient(e->window, 0);
if (c != 0 && c->window == e->window && c != current) {
/* someone grabbed keyboard or seized focus; make them current */
XMapRaised(dpy, c->parent);
top(c);
active(c);
}
}

96
src/cmd/rio/fns.h Normal file
View file

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

498
src/cmd/rio/grab.c Normal file
View file

@ -0,0 +1,498 @@
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "dat.h"
#include "fns.h"
int
nobuttons(XButtonEvent *e) /* Einstuerzende */
{
int state;
state = (e->state & AllButtonMask);
return (e->type == ButtonRelease) && (state & (state - 1)) == 0;
}
int
grab(Window w, Window constrain, int mask, Cursor curs, int t)
{
int status;
if (t == 0)
t = timestamp();
status = XGrabPointer(dpy, w, False, mask,
GrabModeAsync, GrabModeAsync, constrain, curs, t);
return status;
}
void
ungrab(XButtonEvent *e)
{
XEvent ev;
if (!nobuttons(e))
for (;;) {
XMaskEvent(dpy, ButtonMask | ButtonMotionMask, &ev);
if (ev.type == MotionNotify)
continue;
e = &ev.xbutton;
if (nobuttons(e))
break;
}
XUngrabPointer(dpy, e->time);
curtime = e->time;
}
static void
drawstring(Display *dpy, ScreenInfo *s, Menu *m, int wide, int high, int i, int selected)
{
int tx, ty;
tx = (wide - XTextWidth(font, m->item[i], strlen(m->item[i])))/2;
ty = i*high + font->ascent + 1;
XFillRectangle(dpy, s->menuwin, selected ? s->gcmenubgs : s->gcmenubg, 0, i*high, wide, high);
XDrawString(dpy, s->menuwin, selected ? s->gcmenufgs : s->gcmenufg, tx, ty, m->item[i], strlen(m->item[i]));
}
int
menuhit(XButtonEvent *e, Menu *m)
{
XEvent ev;
int i, n, cur, old, wide, high, status, drawn, warp;
int x, y, dx, dy, xmax, ymax;
int tx, ty;
ScreenInfo *s;
if (font == 0)
return -1;
s = getscreen(e->root);
if (s == 0 || e->window == s->menuwin) /* ugly event mangling */
return -1;
dx = 0;
for (n = 0; m->item[n]; n++) {
wide = XTextWidth(font, m->item[n], strlen(m->item[n])) + 4;
if (wide > dx)
dx = wide;
}
wide = dx;
cur = m->lasthit;
if (cur >= n)
cur = n - 1;
high = font->ascent + font->descent + 1;
dy = n*high;
x = e->x - wide/2;
y = e->y - cur*high - high/2;
warp = 0;
xmax = DisplayWidth(dpy, s->num);
ymax = DisplayHeight(dpy, s->num);
if (x < 0) {
e->x -= x;
x = 0;
warp++;
}
if (x+wide >= xmax) {
e->x -= x+wide-xmax;
x = xmax-wide;
warp++;
}
if (y < 0) {
e->y -= y;
y = 0;
warp++;
}
if (y+dy >= ymax) {
e->y -= y+dy-ymax;
y = ymax-dy;
warp++;
}
if (warp)
setmouse(e->x, e->y, s);
XMoveResizeWindow(dpy, s->menuwin, x, y, dx, dy);
XSelectInput(dpy, s->menuwin, MenuMask);
XMapRaised(dpy, s->menuwin);
status = grab(s->menuwin, None, MenuGrabMask, None, e->time);
if (status != GrabSuccess) {
/* graberror("menuhit", status); */
XUnmapWindow(dpy, s->menuwin);
return -1;
}
drawn = 0;
for (;;) {
XMaskEvent(dpy, MenuMask, &ev);
switch (ev.type) {
default:
fprintf(stderr, "9wm: menuhit: unknown ev.type %d\n", ev.type);
break;
case ButtonPress:
break;
case ButtonRelease:
if (ev.xbutton.button != e->button)
break;
x = ev.xbutton.x;
y = ev.xbutton.y;
i = y/high;
if (cur >= 0 && y >= cur*high-3 && y < (cur+1)*high+3)
i = cur;
if (x < 0 || x > wide || y < -3)
i = -1;
else if (i < 0 || i >= n)
i = -1;
else
m->lasthit = i;
if (!nobuttons(&ev.xbutton))
i = -1;
ungrab(&ev.xbutton);
XUnmapWindow(dpy, s->menuwin);
return i;
case MotionNotify:
if (!drawn)
break;
x = ev.xbutton.x;
y = ev.xbutton.y;
old = cur;
cur = y/high;
if (old >= 0 && y >= old*high-3 && y < (old+1)*high+3)
cur = old;
if (x < 0 || x > wide || y < -3)
cur = -1;
else if (cur < 0 || cur >= n)
cur = -1;
if (cur == old)
break;
if (old >= 0 && old < n)
drawstring(dpy, s, m, wide, high, old, 0);
if (cur >= 0 && cur < n)
drawstring(dpy, s, m, wide, high, cur, 1);
break;
case Expose:
XClearWindow(dpy, s->menuwin);
for (i = 0; i < n; i++)
drawstring(dpy, s, m, wide, high, i, cur==i);
drawn = 1;
}
}
}
Client *
selectwin(int release, int *shift, ScreenInfo *s)
{
XEvent ev;
XButtonEvent *e;
int status;
Window w;
Client *c;
status = grab(s->root, s->root, ButtonMask, s->target, 0);
if (status != GrabSuccess) {
graberror("selectwin", status); /* */
return 0;
}
w = None;
for (;;) {
XMaskEvent(dpy, ButtonMask, &ev);
e = &ev.xbutton;
switch (ev.type) {
case ButtonPress:
if (e->button != Button3) {
ungrab(e);
return 0;
}
w = e->subwindow;
if (!release) {
c = getclient(w, 0);
if (c == 0)
ungrab(e);
if (shift != 0)
*shift = (e->state&ShiftMask) != 0;
return c;
}
break;
case ButtonRelease:
ungrab(e);
if (e->button != Button3 || e->subwindow != w)
return 0;
if (shift != 0)
*shift = (e->state&ShiftMask) != 0;
return getclient(w, 0);
}
}
}
void
sweepcalc(Client *c, int x, int y)
{
int dx, dy, sx, sy;
dx = x - c->x;
dy = y - c->y;
sx = sy = 1;
if (dx < 0) {
dx = -dx;
sx = -1;
}
if (dy < 0) {
dy = -dy;
sy = -1;
}
dx -= 2*BORDER;
dy -= 2*BORDER;
if (!c->is9term) {
if (dx < c->min_dx)
dx = c->min_dx;
if (dy < c->min_dy)
dy = c->min_dy;
}
if (c->size.flags & PResizeInc) {
dx = c->min_dx + (dx-c->min_dx)/c->size.width_inc*c->size.width_inc;
dy = c->min_dy + (dy-c->min_dy)/c->size.height_inc*c->size.height_inc;
}
if (c->size.flags & PMaxSize) {
if (dx > c->size.max_width)
dx = c->size.max_width;
if (dy > c->size.max_height)
dy = c->size.max_height;
}
c->dx = sx*(dx + 2*BORDER);
c->dy = sy*(dy + 2*BORDER);
}
void
dragcalc(Client *c, int x, int y)
{
c->x = x;
c->y = y;
}
static void
xcopy(int fwd, Display *dpy, Drawable src, Drawable dst, GC gc, int x, int y, int dx, int dy, int x1, int y1)
{
if(fwd)
XCopyArea(dpy, src, dst, gc, x, y, dx, dy, x1, y1);
else
XCopyArea(dpy, dst, src, gc, x1, y1, dx, dy, x, y);
}
void
drawbound(Client *c, int drawing)
{
int x, y, dx, dy;
ScreenInfo *s;
s = c->screen;
x = c->x;
y = c->y;
dx = c->dx;
dy = c->dy;
if (dx < 0) {
x += dx;
dx = -dx;
}
if (dy < 0) {
y += dy;
dy = -dy;
}
if (dx <= 2 || dy <= 2)
return;
if(solidsweep){
if(drawing == -1){
XUnmapWindow(dpy, s->sweepwin);
return;
}
x += BORDER;
y += BORDER;
dx -= 2*BORDER;
dy -= 2*BORDER;
if(drawing){
XMoveResizeWindow(dpy, s->sweepwin, x, y, dx, dy);
XSelectInput(dpy, s->sweepwin, MenuMask);
XMapRaised(dpy, s->sweepwin);
}
return;
}
if(drawing == -1)
return;
xcopy(drawing, dpy, s->root, s->bkup[0], s->gccopy, x, y, dx, BORDER, 0, 0);
xcopy(drawing, dpy, s->root, s->bkup[0], s->gccopy, x, y+dy-BORDER, dx, BORDER, dx, 0);
xcopy(drawing, dpy, s->root, s->bkup[1], s->gccopy, x, y, BORDER, dy, 0, 0);
xcopy(drawing, dpy, s->root, s->bkup[1], s->gccopy, x+dx-BORDER, y, BORDER, dy, 0, dy);
if(drawing){
XFillRectangle(dpy, s->root, s->gcred, x, y, dx, BORDER);
XFillRectangle(dpy, s->root, s->gcred, x, y+dy-BORDER, dx, BORDER);
XFillRectangle(dpy, s->root, s->gcred, x, y, BORDER, dy);
XFillRectangle(dpy, s->root, s->gcred, x+dx-BORDER, y, BORDER, dy);
}
}
void
misleep(int msec)
{
struct timeval t;
t.tv_sec = msec/1000;
t.tv_usec = (msec%1000)*1000;
select(0, 0, 0, 0, &t);
}
int
sweepdrag(Client *c, XButtonEvent *e0, void (*recalc)(Client*, int, int))
{
XEvent ev;
int idle;
int cx, cy, rx, ry;
int ox, oy, odx, ody;
XButtonEvent *e;
ox = c->x;
oy = c->y;
odx = c->dx;
ody = c->dy;
c->x -= BORDER;
c->y -= BORDER;
c->dx += 2*BORDER;
c->dy += 2*BORDER;
if (e0) {
c->x = cx = e0->x;
c->y = cy = e0->y;
recalc(c, e0->x, e0->y);
}
else
getmouse(&cx, &cy, c->screen);
XGrabServer(dpy);
drawbound(c, 1);
idle = 0;
for (;;) {
if (XCheckMaskEvent(dpy, ButtonMask, &ev) == 0) {
getmouse(&rx, &ry, c->screen);
if (rx != cx || ry != cy || ++idle > 300) {
drawbound(c, 0);
if (rx == cx && ry == cy) {
XUngrabServer(dpy);
XFlush(dpy);
misleep(500);
XGrabServer(dpy);
idle = 0;
}
recalc(c, rx, ry);
cx = rx;
cy = ry;
drawbound(c, 1);
XFlush(dpy);
}
misleep(50);
continue;
}
e = &ev.xbutton;
switch (ev.type) {
case ButtonPress:
case ButtonRelease:
drawbound(c, 0);
ungrab(e);
XUngrabServer(dpy);
if (e->button != Button3 && c->init)
goto bad;
recalc(c, ev.xbutton.x, ev.xbutton.y);
if (c->dx < 0) {
c->x += c->dx;
c->dx = -c->dx;
}
if (c->dy < 0) {
c->y += c->dy;
c->dy = -c->dy;
}
c->x += BORDER;
c->y += BORDER;
c->dx -= 2*BORDER;
c->dy -= 2*BORDER;
if (c->dx < 4 || c->dy < 4 || c->dx < c->min_dx || c->dy < c->min_dy)
goto bad;
return 1;
}
}
bad:
c->x = ox;
c->y = oy;
c->dx = odx;
c->dy = ody;
drawbound(c, -1);
return 0;
}
int
sweep(Client *c)
{
XEvent ev;
int status;
XButtonEvent *e;
ScreenInfo *s;
s = c->screen;
status = grab(s->root, s->root, ButtonMask, s->sweep0, 0);
if (status != GrabSuccess) {
graberror("sweep", status); /* */
return 0;
}
XMaskEvent(dpy, ButtonMask, &ev);
e = &ev.xbutton;
if (e->button != Button3) {
ungrab(e);
return 0;
}
if (c->size.flags & (PMinSize|PBaseSize))
setmouse(e->x+c->min_dx, e->y+c->min_dy, s);
XChangeActivePointerGrab(dpy, ButtonMask, s->boxcurs, e->time);
return sweepdrag(c, e, sweepcalc);
}
int
drag(Client *c)
{
int status;
ScreenInfo *s;
s = c->screen;
if (c->init)
setmouse(c->x-BORDER, c->y-BORDER, s);
else {
getmouse(&c->x, &c->y, s); /* start at current mouse pos */
c->x += BORDER;
c->y += BORDER;
}
status = grab(s->root, s->root, ButtonMask, s->boxcurs, 0);
if (status != GrabSuccess) {
graberror("drag", status); /* */
return 0;
}
return sweepdrag(c, 0, dragcalc);
}
void
getmouse(int *x, int *y, ScreenInfo *s)
{
Window dw1, dw2;
int t1, t2;
unsigned int t3;
XQueryPointer(dpy, s->root, &dw1, &dw2, x, y, &t1, &t2, &t3);
}
void
setmouse(int x, int y, ScreenInfo *s)
{
XWarpPointer(dpy, None, s->root, None, None, None, None, x, y);
}

437
src/cmd/rio/main.c Normal file
View file

@ -0,0 +1,437 @@
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include "dat.h"
#include "fns.h"
#include "patchlevel.h"
char *version[] =
{
"rio version 1.0, Copyright (c) 1994-1996 David Hogan, (c) 2004 Russ Cox", 0,
};
Display *dpy;
ScreenInfo *screens;
int initting;
XFontStruct *font;
int nostalgia;
char **myargv;
char *termprog;
char *shell;
Bool shape;
int _border = 4;
int _inset = 1;
int curtime;
int debug;
int signalled;
int num_screens;
int solidsweep = 0;
Atom exit_9wm;
Atom restart_9wm;
Atom wm_state;
Atom wm_change_state;
Atom wm_protocols;
Atom wm_delete;
Atom wm_take_focus;
Atom wm_colormaps;
Atom _9wm_running;
Atom _9wm_hold_mode;
char *fontlist[] = {
"lucm.latin1.9",
"blit",
"lucidasanstypewriter-bold-10",
"9x15bold",
"fixed",
"*",
0,
};
void
usage(void)
{
fprintf(stderr, "usage: rio [-grey] [-version] [-font fname] [-term prog] [exit|restart]\n");
exit(1);
}
int
main(int argc, char *argv[])
{
int i, background, do_exit, do_restart;
char *fname;
int shape_event, dummy;
myargv = argv; /* for restart */
do_exit = do_restart = 0;
background = 1;
font = 0;
fname = 0;
for (i = 1; i < argc; i++)
if (strcmp(argv[i], "-nostalgia") == 0)
nostalgia++;
else if (strcmp(argv[i], "-grey") == 0)
background = 1;
else if (strcmp(argv[i], "-debug") == 0)
debug++;
else if (strcmp(argv[i], "-font") == 0 && i+1<argc) {
i++;
fname = argv[i];
}
else if (strcmp(argv[i], "-term") == 0 && i+1<argc)
termprog = argv[++i];
else if (strcmp(argv[i], "-version") == 0) {
fprintf(stderr, "%s", version[0]);
if (PATCHLEVEL > 0)
fprintf(stderr, "; patch level %d", PATCHLEVEL);
fprintf(stderr, "\n");
exit(0);
}
else if (argv[i][0] == '-')
usage();
else
break;
for (; i < argc; i++)
if (strcmp(argv[i], "exit") == 0)
do_exit++;
else if (strcmp(argv[i], "restart") == 0)
do_restart++;
else
usage();
if (do_exit && do_restart)
usage();
shell = (char *)getenv("SHELL");
if (shell == NULL)
shell = DEFSHELL;
dpy = XOpenDisplay("");
if (dpy == 0)
fatal("can't open display");
initting = 1;
XSetErrorHandler(handler);
if (signal(SIGTERM, sighandler) == SIG_IGN)
signal(SIGTERM, SIG_IGN);
if (signal(SIGINT, sighandler) == SIG_IGN)
signal(SIGINT, SIG_IGN);
if (signal(SIGHUP, sighandler) == SIG_IGN)
signal(SIGHUP, SIG_IGN);
exit_9wm = XInternAtom(dpy, "9WM_EXIT", False);
restart_9wm = XInternAtom(dpy, "9WM_RESTART", False);
curtime = -1; /* don't care */
if (do_exit) {
sendcmessage(DefaultRootWindow(dpy), exit_9wm, 0L, 1);
XSync(dpy, False);
exit(0);
}
if (do_restart) {
sendcmessage(DefaultRootWindow(dpy), restart_9wm, 0L, 1);
XSync(dpy, False);
exit(0);
}
wm_state = XInternAtom(dpy, "WM_STATE", False);
wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
_9wm_running = XInternAtom(dpy, "_9WM_RUNNING", False);
_9wm_hold_mode = XInternAtom(dpy, "_9WM_HOLD_MODE", False);
if (fname != 0)
if ((font = XLoadQueryFont(dpy, fname)) == 0)
fprintf(stderr, "9wm: warning: can't load font %s\n", fname);
if (font == 0) {
i = 0;
for (;;) {
fname = fontlist[i++];
if (fname == 0) {
fprintf(stderr, "9wm: warning: can't find a font\n");
break;
}
font = XLoadQueryFont(dpy, fname);
if (font != 0)
break;
}
}
if (nostalgia) {
_border--;
_inset--;
}
#ifdef SHAPE
shape = XShapeQueryExtension(dpy, &shape_event, &dummy);
#endif
num_screens = ScreenCount(dpy);
screens = (ScreenInfo *)malloc(sizeof(ScreenInfo) * num_screens);
for (i = 0; i < num_screens; i++)
initscreen(&screens[i], i, background);
/* set selection so that 9term knows we're running */
curtime = CurrentTime;
XSetSelectionOwner(dpy, _9wm_running, screens[0].menuwin, timestamp());
XSync(dpy, False);
initting = 0;
nofocus();
for (i = 0; i < num_screens; i++)
scanwins(&screens[i]);
mainloop(shape_event);
}
void
initscreen(ScreenInfo *s, int i, int background)
{
char *ds, *colon, *dot1;
unsigned long mask;
XGCValues gv;
XSetWindowAttributes attr;
s->num = i;
s->root = RootWindow(dpy, i);
s->def_cmap = DefaultColormap(dpy, i);
s->min_cmaps = MinCmapsOfScreen(ScreenOfDisplay(dpy, i));
s->depth = DefaultDepth(dpy, i);
ds = DisplayString(dpy);
colon = rindex(ds, ':');
if (colon && num_screens > 1) {
strcpy(s->display, "DISPLAY=");
strcat(s->display, ds);
colon = s->display + 8 + (colon - ds); /* use version in buf */
dot1 = index(colon, '.'); /* first period after colon */
if (!dot1)
dot1 = colon + strlen(colon); /* if not there, append */
sprintf(dot1, ".%d", i);
}
else
s->display[0] = '\0';
s->activeholdborder = colorpixel(dpy, s->depth, 0x000099);
s->inactiveholdborder = colorpixel(dpy, s->depth, 0x005DBB);
s->activeborder = colorpixel(dpy, s->depth ,0x55AAAA);
s->inactiveborder = colorpixel(dpy, s->depth, 0x9EEEEE);
s->red = colorpixel(dpy, s->depth, 0xDD0000);
s->black = BlackPixel(dpy, i);
s->white = WhitePixel(dpy, i);
s->width = WidthOfScreen(ScreenOfDisplay(dpy, i));
s->height = HeightOfScreen(ScreenOfDisplay(dpy, i));
s->bkup[0] = XCreatePixmap(dpy, s->root, 2*s->width, BORDER, DefaultDepth(dpy, i));
s->bkup[1] = XCreatePixmap(dpy, s->root, BORDER, 2*s->height, DefaultDepth(dpy, i));
gv.foreground = s->black^s->white;
gv.background = s->white;
gv.function = GXxor;
gv.line_width = 0;
gv.subwindow_mode = IncludeInferiors;
mask = GCForeground | GCBackground | GCFunction | GCLineWidth
| GCSubwindowMode;
if (font != 0) {
gv.font = font->fid;
mask |= GCFont;
}
s->gc = XCreateGC(dpy, s->root, mask, &gv);
gv.function = GXcopy;
s->gccopy = XCreateGC(dpy, s->root, mask, &gv);
gv.foreground = s->red;
s->gcred = XCreateGC(dpy, s->root, mask, &gv);
gv.foreground = colorpixel(dpy, s->depth, 0xEEEEEE);
s->gcsweep = XCreateGC(dpy, s->root, mask, &gv);
gv.foreground = colorpixel(dpy, s->depth, 0xE9FFE9);
s->gcmenubg = XCreateGC(dpy, s->root, mask, &gv);
gv.foreground = colorpixel(dpy, s->depth, 0x448844);
s->gcmenubgs = XCreateGC(dpy, s->root, mask, &gv);
gv.foreground = s->black;
gv.background = colorpixel(dpy, s->depth, 0xE9FFE9);
s->gcmenufg = XCreateGC(dpy, s->root, mask, &gv);
gv.foreground = colorpixel(dpy, s->depth, 0xE9FFE9);
gv.background = colorpixel(dpy, s->depth, 0x448844);
s->gcmenufgs = XCreateGC(dpy, s->root, mask, &gv);
initcurs(s);
attr.cursor = s->arrow;
attr.event_mask = SubstructureRedirectMask
| SubstructureNotifyMask | ColormapChangeMask
| ButtonPressMask | ButtonReleaseMask | PropertyChangeMask;
mask = CWCursor|CWEventMask;
XChangeWindowAttributes(dpy, s->root, mask, &attr);
XSync(dpy, False);
if (background) {
/*
XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap);
XClearWindow(dpy, s->root);
*/
system("xsetroot -solid grey30");
}
s->menuwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 2, colorpixel(dpy, s->depth, 0xAAFFAA), colorpixel(dpy, s->depth, 0xE9FFE9));
s->sweepwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 4, s->red, colorpixel(dpy, s->depth, 0xEEEEEE));
}
ScreenInfo*
getscreen(Window w)
{
int i;
for (i = 0; i < num_screens; i++)
if (screens[i].root == w)
return &screens[i];
return 0;
}
Time
timestamp(void)
{
XEvent ev;
if (curtime == CurrentTime) {
XChangeProperty(dpy, screens[0].root, _9wm_running, _9wm_running, 8,
PropModeAppend, (unsigned char *)"", 0);
XMaskEvent(dpy, PropertyChangeMask, &ev);
curtime = ev.xproperty.time;
}
return curtime;
}
void
sendcmessage(Window w, Atom a, long x, int isroot)
{
XEvent ev;
int status;
long mask;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = w;
ev.xclient.message_type = a;
ev.xclient.format = 32;
ev.xclient.data.l[0] = x;
ev.xclient.data.l[1] = timestamp();
mask = 0L;
if (isroot)
mask = SubstructureRedirectMask; /* magic! */
status = XSendEvent(dpy, w, False, mask, &ev);
if (status == 0)
fprintf(stderr, "9wm: sendcmessage failed\n");
}
void
sendconfig(Client *c)
{
XConfigureEvent ce;
ce.type = ConfigureNotify;
ce.event = c->window;
ce.window = c->window;
ce.x = c->x;
ce.y = c->y;
ce.width = c->dx;
ce.height = c->dy;
ce.border_width = c->border;
ce.above = None;
ce.override_redirect = 0;
XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent*)&ce);
}
void
sighandler(void)
{
signalled = 1;
}
void
getevent(XEvent *e)
{
int fd;
fd_set rfds;
struct timeval t;
if (!signalled) {
if (QLength(dpy) > 0) {
XNextEvent(dpy, e);
return;
}
fd = ConnectionNumber(dpy);
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
t.tv_sec = t.tv_usec = 0;
if (select(fd+1, &rfds, NULL, NULL, &t) == 1) {
XNextEvent(dpy, e);
return;
}
XFlush(dpy);
FD_SET(fd, &rfds);
if (select(fd+1, &rfds, NULL, NULL, NULL) == 1) {
XNextEvent(dpy, e);
return;
}
if (errno != EINTR || !signalled) {
perror("9wm: select failed");
exit(1);
}
}
fprintf(stderr, "9wm: exiting on signal\n");
cleanup();
exit(1);
}
void
cleanup(void)
{
Client *c, *cc[2], *next;
XWindowChanges wc;
int i;
/* order of un-reparenting determines final stacking order... */
cc[0] = cc[1] = 0;
for (c = clients; c; c = next) {
next = c->next;
i = normal(c);
c->next = cc[i];
cc[i] = c;
}
for (i = 0; i < 2; i++) {
for (c = cc[i]; c; c = c->next) {
if (!withdrawn(c)) {
gravitate(c, 1);
XReparentWindow(dpy, c->window, c->screen->root,
c->x, c->y);
}
wc.border_width = c->border;
XConfigureWindow(dpy, c->window, CWBorderWidth, &wc);
}
}
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, timestamp());
for (i = 0; i < num_screens; i++)
cmapnofocus(&screens[i]);
XCloseDisplay(dpy);
}

482
src/cmd/rio/manage.c Normal file
View file

@ -0,0 +1,482 @@
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>
#include "dat.h"
#include "fns.h"
int
manage(Client *c, int mapped)
{
int fixsize, dohide, doreshape, state;
long msize;
XClassHint class;
XWMHints *hints;
trace("manage", c, 0);
XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask);
/* Get loads of hints */
if (XGetClassHint(dpy, c->window, &class) != 0) { /* ``Success'' */
c->instance = class.res_name;
c->class = class.res_class;
c->is9term = (strcmp(c->class, "9term") == 0);
}
else {
c->instance = 0;
c->class = 0;
c->is9term = 0;
}
c->iconname = getprop(c->window, XA_WM_ICON_NAME);
c->name = getprop(c->window, XA_WM_NAME);
setlabel(c);
hints = XGetWMHints(dpy, c->window);
if (XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
c->size.flags = PSize; /* not specified - punt */
getcmaps(c);
getproto(c);
gettrans(c);
if (c->is9term)
c->hold = getiprop(c->window, _9wm_hold_mode);
/* Figure out what to do with the window from hints */
if (!getstate(c->window, &state))
state = hints ? hints->initial_state : NormalState;
dohide = (state == IconicState);
fixsize = 0;
if ((c->size.flags & (USSize|PSize)))
fixsize = 1;
if ((c->size.flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize) && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height)
fixsize = 1;
doreshape = !mapped;
if (fixsize) {
if (c->size.flags & USPosition)
doreshape = 0;
if (dohide && (c->size.flags & PPosition))
doreshape = 0;
if (c->trans != None)
doreshape = 0;
}
if (c->is9term)
fixsize = 0;
if (c->size.flags & PBaseSize) {
c->min_dx = c->size.base_width;
c->min_dy = c->size.base_height;
}
else if (c->size.flags & PMinSize) {
c->min_dx = c->size.min_width;
c->min_dy = c->size.min_height;
}
else if (c->is9term) {
c->min_dx = 100;
c->min_dy = 50;
}
else
c->min_dx = c->min_dy = 0;
if (hints)
XFree(hints);
/* Now do it!!! */
if (doreshape) {
if (current && current->screen == c->screen)
cmapnofocus(c->screen);
if (!c->is9term && c->x==0 && c->y==0) {
static int nwin;
c->x = 20*nwin+BORDER;
c->y = 20*nwin+BORDER;
nwin++;
nwin %= 10;
}
if (c->is9term && !(fixsize ? drag(c) : sweep(c))) {
XKillClient(dpy, c->window);
rmclient(c);
if (current && current->screen == c->screen)
cmapfocus(current);
return 0;
}
}
else
gravitate(c, 0);
c->parent = XCreateSimpleWindow(dpy, c->screen->root,
c->x - BORDER, c->y - BORDER,
c->dx + 2*BORDER, c->dy + 2*BORDER,
0, c->screen->black, c->screen->white);
XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask);
if (mapped)
c->reparenting = 1;
if (doreshape && !fixsize)
XResizeWindow(dpy, c->window, c->dx, c->dy);
XSetWindowBorderWidth(dpy, c->window, 0);
XReparentWindow(dpy, c->window, c->parent, BORDER, BORDER);
#ifdef SHAPE
if (shape) {
XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
ignore_badwindow = 1; /* magic */
setshape(c);
ignore_badwindow = 0;
}
#endif
XAddToSaveSet(dpy, c->window);
if (dohide)
hide(c);
else {
XMapWindow(dpy, c->window);
XMapWindow(dpy, c->parent);
XUnmapWindow(dpy, c->screen->sweepwin);
if (nostalgia || doreshape)
active(c);
else if (c->trans != None && current && current->window == c->trans)
active(c);
else
setactive(c, 0);
setstate(c, NormalState);
}
if (current && (current != c))
cmapfocus(current);
c->init = 1;
return 1;
}
void
scanwins(ScreenInfo *s)
{
unsigned int i, nwins;
Client *c;
Window dw1, dw2, *wins;
XWindowAttributes attr;
XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins);
for (i = 0; i < nwins; i++) {
XGetWindowAttributes(dpy, wins[i], &attr);
if (attr.override_redirect || wins[i] == s->menuwin)
continue;
c = getclient(wins[i], 1);
if (c != 0 && c->window == wins[i] && !c->init) {
c->x = attr.x;
c->y = attr.y;
c->dx = attr.width;
c->dy = attr.height;
c->border = attr.border_width;
c->screen = s;
c->parent = s->root;
if (attr.map_state == IsViewable)
manage(c, 1);
}
}
XFree((void *) wins); /* cast is to shut stoopid compiler up */
}
void
gettrans(Client *c)
{
Window trans;
trans = None;
if (XGetTransientForHint(dpy, c->window, &trans) != 0)
c->trans = trans;
else
c->trans = None;
}
void
withdraw(Client *c)
{
XUnmapWindow(dpy, c->parent);
gravitate(c, 1);
XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y);
gravitate(c, 0);
XRemoveFromSaveSet(dpy, c->window);
setstate(c, WithdrawnState);
/* flush any errors */
ignore_badwindow = 1;
XSync(dpy, False);
ignore_badwindow = 0;
}
void
gravitate(Client *c, int invert)
{
int gravity, dx, dy, delta;
gravity = NorthWestGravity;
if (c->size.flags & PWinGravity)
gravity = c->size.win_gravity;
delta = c->border-BORDER;
switch (gravity) {
case NorthWestGravity:
dx = 0;
dy = 0;
break;
case NorthGravity:
dx = delta;
dy = 0;
break;
case NorthEastGravity:
dx = 2*delta;
dy = 0;
break;
case WestGravity:
dx = 0;
dy = delta;
break;
case CenterGravity:
case StaticGravity:
dx = delta;
dy = delta;
break;
case EastGravity:
dx = 2*delta;
dy = delta;
break;
case SouthWestGravity:
dx = 0;
dy = 2*delta;
break;
case SouthGravity:
dx = delta;
dy = 2*delta;
break;
case SouthEastGravity:
dx = 2*delta;
dy = 2*delta;
break;
default:
fprintf(stderr, "9wm: bad window gravity %d for 0x%x\n", gravity, c->window);
return;
}
dx += BORDER;
dy += BORDER;
if (invert) {
dx = -dx;
dy = -dy;
}
c->x += dx;
c->y += dy;
}
static void
installcmap(ScreenInfo *s, Colormap cmap)
{
if (cmap == None)
XInstallColormap(dpy, s->def_cmap);
else
XInstallColormap(dpy, cmap);
}
void
cmapfocus(Client *c)
{
int i, found;
Client *cc;
if (c == 0)
return;
else if (c->ncmapwins != 0) {
found = 0;
for (i = c->ncmapwins-1; i >= 0; i--) {
installcmap(c->screen, c->wmcmaps[i]);
if (c->cmapwins[i] == c->window)
found++;
}
if (!found)
installcmap(c->screen, c->cmap);
}
else if (c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0)
cmapfocus(cc);
else
installcmap(c->screen, c->cmap);
}
void
cmapnofocus(ScreenInfo *s)
{
installcmap(s, None);
}
void
getcmaps(Client *c)
{
int n, i;
Window *cw;
XWindowAttributes attr;
if (!c->init) {
XGetWindowAttributes(dpy, c->window, &attr);
c->cmap = attr.colormap;
}
n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (unsigned char **)&cw);
if (c->ncmapwins != 0) {
XFree((char *)c->cmapwins);
free((char *)c->wmcmaps);
}
if (n <= 0) {
c->ncmapwins = 0;
return;
}
c->ncmapwins = n;
c->cmapwins = cw;
c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap));
for (i = 0; i < n; i++) {
if (cw[i] == c->window)
c->wmcmaps[i] = c->cmap;
else {
XSelectInput(dpy, cw[i], ColormapChangeMask);
XGetWindowAttributes(dpy, cw[i], &attr);
c->wmcmaps[i] = attr.colormap;
}
}
}
void
setlabel(Client *c)
{
char *label, *p;
if (c->iconname != 0)
label = c->iconname;
else if (c->name != 0)
label = c->name;
else if (c->instance != 0)
label = c->instance;
else if (c->class != 0)
label = c->class;
else
label = "no label";
if ((p = index(label, ':')) != 0)
*p = '\0';
c->label = label;
}
#ifdef SHAPE
void
setshape(Client *c)
{
int n, order;
XRectangle *rect;
/* don't try to add a border if the window is non-rectangular */
rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
if (n > 1)
XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER, BORDER,
c->window, ShapeBounding, ShapeSet);
XFree((void*)rect);
}
#endif
int
_getprop(Window w, Atom a, Atom type, long len, unsigned char **p)
{
Atom real_type;
int format;
unsigned long n, extra;
int status;
status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
if (status != Success || *p == 0)
return -1;
if (n == 0)
XFree((void*) *p);
/* could check real_type, format, extra here... */
return n;
}
char *
getprop(Window w, Atom a)
{
unsigned char *p;
if (_getprop(w, a, XA_STRING, 100L, &p) <= 0)
return 0;
return (char *)p;
}
int
get1prop(Window w, Atom a, Atom type)
{
char **p, *x;
if (_getprop(w, a, type, 1L, (unsigned char**)&p) <= 0)
return 0;
x = *p;
XFree((void*) p);
return (int)x;
}
Window
getwprop(Window w, Atom a)
{
return get1prop(w, a, XA_WINDOW);
}
int
getiprop(Window w, Atom a)
{
return get1prop(w, a, XA_INTEGER);
}
void
setstate(Client *c, int state)
{
long data[2];
data[0] = (long) state;
data[1] = (long) None;
c->state = state;
XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
PropModeReplace, (unsigned char *)data, 2);
}
int
getstate(Window w, int *state)
{
long *p = 0;
if (_getprop(w, wm_state, wm_state, 2L, (unsigned char**)&p) <= 0)
return 0;
*state = (int) *p;
XFree((char *) p);
return 1;
}
void
getproto(Client *c)
{
Atom *p;
int i;
long n;
Window w;
w = c->window;
c->proto = 0;
if ((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (unsigned char**)&p)) <= 0)
return;
for (i = 0; i < n; i++)
if (p[i] == wm_delete)
c->proto |= Pdelete;
else if (p[i] == wm_take_focus)
c->proto |= Ptakefocus;
XFree((char *) p);
}

258
src/cmd/rio/menu.c Normal file
View file

@ -0,0 +1,258 @@
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <signal.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "dat.h"
#include "fns.h"
Client *hiddenc[MAXHIDDEN];
int numhidden;
char *b3items[B3FIXED+MAXHIDDEN+1] =
{
"New",
"Reshape",
"Move",
"Delete",
"Hide",
0,
};
Menu b3menu =
{
b3items,
};
Menu egg =
{
version,
};
void
button(XButtonEvent *e)
{
int n, shift;
Client *c;
Window dw;
ScreenInfo *s;
curtime = e->time;
s = getscreen(e->root);
if (s == 0)
return;
c = getclient(e->window, 0);
if (c) {
e->x += c->x - BORDER;
e->y += c->y - BORDER;
}
else if (e->window != e->root)
XTranslateCoordinates(dpy, e->window, s->root, e->x, e->y,
&e->x, &e->y, &dw);
switch (e->button) {
case Button1:
if (c) {
XMapRaised(dpy, c->parent);
top(c);
active(c);
}
return;
case Button2:
if ((e->state&(ShiftMask|ControlMask))==(ShiftMask|ControlMask))
menuhit(e, &egg);
return;
default:
return;
case Button3:
break;
}
if (current && current->screen == s)
cmapnofocus(s);
switch (n = menuhit(e, &b3menu)) {
case 0: /* New */
spawn(s);
break;
case 1: /* Reshape */
reshape(selectwin(1, 0, s));
break;
case 2: /* Move */
move(selectwin(0, 0, s));
break;
case 3: /* Delete */
shift = 0;
c = selectwin(1, &shift, s);
delete(c, shift);
break;
case 4: /* Hide */
hide(selectwin(1, 0, s));
break;
default: /* unhide window */
unhide(n - B3FIXED, 1);
break;
case -1: /* nothing */
break;
}
if (current && current->screen == s)
cmapfocus(current);
}
void
spawn(ScreenInfo *s)
{
/*
* ugly dance to avoid leaving zombies. Could use SIGCHLD,
* but it's not very portable.
*/
if (fork() == 0) {
if (fork() == 0) {
close(ConnectionNumber(dpy));
if (s->display[0] != '\0')
putenv(s->display);
if (termprog != NULL) {
execl(shell, shell, "-c", termprog, 0);
fprintf(stderr, "9wm: exec %s", shell);
perror(" failed");
}
execlp("9term", "9term", "-w", 0);
execlp("xterm", "xterm", "-ut", 0);
perror("9wm: exec 9term/xterm failed");
exit(1);
}
exit(0);
}
wait((int *) 0);
}
void
reshape(Client *c)
{
int odx, ody;
if (c == 0)
return;
odx = c->dx;
ody = c->dy;
if (sweep(c) == 0)
return;
active(c);
top(c);
XRaiseWindow(dpy, c->parent);
XMoveResizeWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER,
c->dx+2*BORDER, c->dy+2*BORDER);
if (c->dx == odx && c->dy == ody)
sendconfig(c);
else
XMoveResizeWindow(dpy, c->window, BORDER, BORDER, c->dx, c->dy);
}
void
move(Client *c)
{
if (c == 0)
return;
if (drag(c) == 0)
return;
active(c);
top(c);
XRaiseWindow(dpy, c->parent);
XMoveWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER);
sendconfig(c);
}
void
delete(Client *c, int shift)
{
if (c == 0)
return;
if ((c->proto & Pdelete) && !shift)
sendcmessage(c->window, wm_protocols, wm_delete, 0);
else
XKillClient(dpy, c->window); /* let event clean up */
}
void
hide(Client *c)
{
if (c == 0 || numhidden == MAXHIDDEN)
return;
if (hidden(c)) {
fprintf(stderr, "9wm: already hidden: %s\n", c->label);
return;
}
XUnmapWindow(dpy, c->parent);
XUnmapWindow(dpy, c->window);
setstate(c, IconicState);
if (c == current)
nofocus();
hiddenc[numhidden] = c;
b3items[B3FIXED+numhidden] = c->label;
numhidden++;
b3items[B3FIXED+numhidden] = 0;
}
void
unhide(int n, int map)
{
Client *c;
int i;
if (n >= numhidden) {
fprintf(stderr, "9wm: unhide: n %d numhidden %d\n", n, numhidden);
return;
}
c = hiddenc[n];
if (!hidden(c)) {
fprintf(stderr, "9wm: unhide: not hidden: %s(0x%x)\n",
c->label, c->window);
return;
}
if (map) {
XMapWindow(dpy, c->window);
XMapRaised(dpy, c->parent);
setstate(c, NormalState);
active(c);
top(c);
}
numhidden--;
for (i = n; i < numhidden; i ++) {
hiddenc[i] = hiddenc[i+1];
b3items[B3FIXED+i] = b3items[B3FIXED+i+1];
}
b3items[B3FIXED+numhidden] = 0;
}
void
unhidec(Client *c, int map)
{
int i;
for (i = 0; i < numhidden; i++)
if (c == hiddenc[i]) {
unhide(i, map);
return;
}
fprintf(stderr, "9wm: unhidec: not hidden: %s(0x%x)\n",
c->label, c->window);
}
void
renamec(Client *c, char *name)
{
int i;
if (name == 0)
name = "???";
c->label = name;
if (!hidden(c))
return;
for (i = 0; i < numhidden; i++)
if (c == hiddenc[i]) {
b3items[B3FIXED+i] = name;
return;
}
}

1
src/cmd/rio/patchlevel.h Normal file
View file

@ -0,0 +1 @@
#define PATCHLEVEL 0