/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.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"
Client *hiddenc[MAXHIDDEN];
int numhidden = 0;
void
button (XButtonEvent * e)
{
Client *c;
ScreenInfo *s;
Window dw;
s = getscreen (e->root);
if (s == 0)
return;
if (e->window == s->barwin)
{
if (current && current->screen == s)
cmapnofocus (s);
switch (e->button)
{
case Button1:
if ((e->state & (ShiftMask | ControlMask | Mod1Mask)) ==
(ShiftMask | ControlMask | Mod1Mask))
{
if (current && current->isnotile && (current->screen == s))
resize_opaque (current);
}
else if ((e->state & (ControlMask | ShiftMask)) ==
(ControlMask | ShiftMask))
grow (current, DIM_VERT | DIM_HORIZ, -1);
else if ((e->state & (ControlMask | Mod1Mask)) ==
(ControlMask | Mod1Mask))
move_aside (s, (Client *) 0);
else if ((e->state & (ShiftMask | Mod1Mask)) ==
(ShiftMask | Mod1Mask))
{
if (current && current->isnotile && (current->screen == s))
move_opaque (current);
}
else if ((e->state & ControlMask) == ControlMask)
prev_menu ();
else if ((e->state & Mod1Mask) == Mod1Mask)
prev_hidden ();
else
prev_desktop (s);
break;
case Button2:
if ((e->state & (ShiftMask | ControlMask | Mod1Mask)) ==
(ShiftMask | ControlMask | Mod1Mask))
{
if (current && (current->screen == s))
XLowerWindow (dpy, current->parent);
}
else if ((e->state & (ControlMask | Mod1Mask)) ==
(ControlMask | Mod1Mask))
move_aside (s, current);
else if ((e->state & (ControlMask | ShiftMask)) ==
(ControlMask | ShiftMask))
move_select (current, 0);
else if ((e->state & ControlMask) == ControlMask)
do_menu (s);
else if ((e->state & Mod1Mask) == Mod1Mask)
show_hidden ();
else
toggle_notile (s);
break;
case Button3:
if ((e->state & (ShiftMask | ControlMask | Mod1Mask)) ==
(ShiftMask | ControlMask | Mod1Mask))
zoom (current, (DIM_VERT | DIM_HORIZ));
else if ((e->state & (ControlMask | ShiftMask)) ==
(ControlMask | ShiftMask))
grow (current, DIM_VERT | DIM_HORIZ, 1);
else if ((e->state & (ControlMask | Mod1Mask)) ==
(ControlMask | Mod1Mask))
move_aside_clear (s, current);
else if ((e->state & ControlMask) == ControlMask)
next_menu ();
else if ((e->state & Mod1Mask) == Mod1Mask)
next_hidden ();
else
next_desktop (s);
break;
case Button4:
if ((e->state & (ControlMask | ShiftMask | Mod1Mask)) ==
(ControlMask | ShiftMask | Mod1Mask))
move_up (current);
else if ((e->state & (ControlMask | Mod1Mask)) ==
(ControlMask | Mod1Mask))
move_aside (s, (Client *) 0);
else if ((e->state & (Mod1Mask | ShiftMask)) ==
(Mod1Mask | ShiftMask))
move_left (current);
else if ((e->state & (ControlMask | ShiftMask)) ==
(ControlMask | ShiftMask))
grow (current, DIM_VERT | DIM_HORIZ, -1);
else if ((e->state & ControlMask) == ControlMask)
prev_menu ();
else if ((e->state & Mod1Mask) == Mod1Mask)
prev_hidden ();
else if ((e->state & ShiftMask) == ShiftMask)
prev_window (s);
else
prev_desktop (s);
break;
case Button5:
if ((e->state & (ControlMask | ShiftMask | Mod1Mask)) ==
(ControlMask | ShiftMask | Mod1Mask))
move_down (current);
else if ((e->state & (ControlMask | Mod1Mask)) ==
(ControlMask | Mod1Mask))
move_aside_clear (s, current);
else if ((e->state & (Mod1Mask | ShiftMask)) ==
(Mod1Mask | ShiftMask))
move_right (current);
else if ((e->state & (ControlMask | ShiftMask)) ==
(ControlMask | ShiftMask))
grow (current, DIM_VERT | DIM_HORIZ, 1);
else if ((e->state & ControlMask) == ControlMask)
next_menu ();
else if ((e->state & Mod1Mask) == Mod1Mask)
next_hidden ();
else if ((e->state & ShiftMask) == ShiftMask)
next_window (s);
else
next_desktop (s);
break;
}
if (current && current->screen == s)
cmapfocus (current);
return;
}
/* don't let clicks that "bleed" through clients look like they were on the root window. */
if (!(c = getclient (e->window, 0)) && (e->subwindow != None)
&& (c = getclient (e->subwindow, 0)))
XTranslateCoordinates (dpy, e->root, e->subwindow, e->x, e->y, &e->x,
&e->y, &dw);
if (current && current->screen == s)
cmapnofocus (s);
switch (e->button)
{
case Button1:
if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER))
&& (e->y >= BORDER) && (e->y < (c->dy + BORDER)))
{
int wasleft = c->isleft;
int wasaside = c->isaside;
int ctrl = (e->state & ControlMask) == ControlMask;
int skip = s->skip_focus[s->desktop];
if (ctrl && !c->isnotile)
skip = !skip;
if (c->isnotile != s->notile_raised[s->desktop])
{
if (c->isnotile || s->skip_focus[s->desktop])
skip = 1;
if (!ctrl)
toggle_notile (s);
}
if ((!skip && !c->isnotile) || (!ctrl && c->isnotile))
{
raise_tbar (c->screen);
XMapRaised (dpy, c->parent);
top (c);
}
active (c);
if (wasaside)
{
move_aside (c->screen, c);
if (ctrl)
move_aside_other (c->screen);
}
else if (!skip && !c->isnotile)
tile_all (s);
if ((skip || wasleft || c->isnotile) && !ctrl && !wasaside &&
s->clickthru[s->desktop] && (c->istool || c->isfloat
|| (c->isnotile ==
s->notile_raised[s->desktop])))
XAllowEvents (dpy, ReplayPointer, e->time);
}
else if (prefs.btnapplication[0])
spawn (s, prefs.btnapplication[0]);
break;
case Button2:
if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER))
&& (e->y >= BORDER) && (e->y < (c->dy + BORDER)))
{
if (s->clickthru[s->desktop] && !c->isaside &&
(c->istool || c->isfloat
|| (c->isnotile == s->notile_raised[s->desktop])))
{
active (c);
XAllowEvents (dpy, ReplayPointer, e->time);
}
}
else if (prefs.btnapplication[1])
spawn (s, prefs.btnapplication[1]);
break;
case Button3:
if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER))
&& (e->y >= BORDER) && (e->y < (c->dy + BORDER)))
{
if (s->clickthru[s->desktop] && !c->isaside &&
(c->istool || c->isfloat
|| (c->isnotile == s->notile_raised[s->desktop])))
{
active (c);
XAllowEvents (dpy, ReplayPointer, e->time);
}
}
else if (prefs.btnapplication[2])
spawn (s, prefs.btnapplication[2]);
break;
case Button4:
if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER))
&& (e->y >= BORDER) && (e->y < (c->dy + BORDER)))
{
if (s->clickthru[s->desktop] && !c->isaside &&
(c->istool || c->isfloat
|| (c->isnotile == s->notile_raised[s->desktop])))
{
active (c);
XAllowEvents (dpy, ReplayPointer, e->time);
}
}
break;
case Button5:
if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER))
&& (e->y >= BORDER) && (e->y < (c->dy + BORDER)))
{
if (s->clickthru[s->desktop] && !c->isaside &&
(c->istool || c->isfloat
|| (c->isnotile == s->notile_raised[s->desktop])))
{
active (c);
XAllowEvents (dpy, ReplayPointer, e->time);
}
}
break;
}
if (current && current->screen == s)
cmapfocus (current);
}
void
spawn (ScreenInfo * s, char *p)
{
/*
* 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 (p)
{
execl (shell, shell, "-c", p, 0);
fprintf (stderr, "larswm: execl %s", shell);
perror (" failed");
}
else
{
execlp ("xterm", "xterm", 0);
fatal ("execlp xterm");
}
}
exit (0);
}
wait ((int *) 0);
}
void
wmdelete (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))
return;
XUnmapWindow (dpy, c->parent);
XUnmapWindow (dpy, c->window);
wmsetstate (c, IconicState);
if (c == current)
{
revert_window (c->screen);
}
hiddenc[numhidden] = c;
numhidden++;
c->hidden = 1;
bar_hidden = numhidden;
update_tbar ();
}
void
unhide (int n, int map)
{
Client *c;
int i;
if (n >= numhidden)
return;
c = hiddenc[n];
if (!hidden (c))
return;
if (map)
{
c->desktop = c->screen->desktop;
raise_tbar (c->screen);
XMapWindow (dpy, c->window);
XMapRaised (dpy, c->parent);
wmsetstate (c, NormalState);
top (c);
active (c);
}
numhidden--;
for (i = n; i < numhidden; i++)
hiddenc[i] = hiddenc[i + 1];
c->hidden = 0;
bar_hidden = numhidden;
if (map && (c->isnotile != c->screen->notile_raised[c->screen->desktop]))
toggle_notile (c->screen);
update_tbar ();
}
void
unhidec (Client * c, int map)
{
int i;
if (!c->hidden)
return;
for (i = 0; i < numhidden; i++)
if (c == hiddenc[i])
{
unhide (i, map);
return;
}
}
void
renamec (Client * c, char *name)
{
if (name == 0)
name = "???";
c->label = name;
}
syntax highlighted by Code2HTML, v. 0.9.1