mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-21 11:40:03 +00:00
259 lines
4.3 KiB
C
259 lines
4.3 KiB
C
|
/* 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;
|
||
|
}
|
||
|
}
|