/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include #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; }