swim.git
func.c
/* swim - window manager
* Copyright (C) 2022-2023 ArcNyxx
* see LICENCE file for licensing information */
#include <signal.h>
#include <stdbool.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "bar.h"
#include "func.h"
#include "grab.h"
#include "swim.h"
#include "tile.h"
#include "util.h"
extern mon_t *sel;
extern XColor xclrs[CLR_LST];
void
focus(cli_t *cli)
{
if (cli == NULL || !VIS(cli))
if ((cli = next(sel->cli)) == NULL)
for (cli = sel->cli; cli != NULL && !VIS(cli);
cli = cli->next);
if (sel->sel != NULL && sel->sel != cli)
unfocus(sel->sel, false);
if (cli != NULL) {
if (cli->mon != sel)
sel = cli->mon;
if (cli->urg)
seturg(cli, false);
grabbuttons(cli, true);
XSetWindowBorder(dpy, cli->win, xclrs[CLR_SEL].pixel);
}
XSetInputFocus(dpy, cli != NULL && !cli->nfc ? cli->win : ROOT,
RevertToPointerRoot, CurrentTime);
XChangeProperty(dpy, ROOT, atom[NET_ACTIVE], XA_WINDOW, 32,
PropModeReplace, (void *)(cli != NULL && !cli->nfc ?
(Window *)&cli->win : &(Window){ 0 }), 1);
if (cli != NULL)
sendevent(cli, atom[CC_TAKE_FOCUS]);
sel->sel = cli;
drawbars();
}
void
unfocus(cli_t *cli, bool fcs)
{
if (cli != NULL) {
grabbuttons(cli, false);
XSetWindowBorder(dpy, cli->win, xclrs[CLR_NRM].pixel);
if (fcs) {
XSetInputFocus(dpy, ROOT, RevertToPointerRoot,
CurrentTime);
XDeleteProperty(dpy, ROOT, atom[NET_ACTIVE]);
}
}
}
bool
sendevent(cli_t *cli, Atom prop)
{
int num; Atom *props; bool supp = false;
if (XGetWMProtocols(dpy, cli->win, &props, &num)) {
while (!supp && --num)
supp = props[num] == prop;
XFree(props);
}
if (supp) {
XEvent ev = { .type = ClientMessage };
ev.xclient = (XClientMessageEvent){ .format = 32, .window =
cli->win, .message_type = atom[CC_PROTOCOLS],
.data.l[0] = prop, .data.l[1] = CurrentTime };
XSendEvent(dpy, cli->win, false, NoEventMask, &ev);
}
return supp;
}
void
seturg(cli_t *cli, bool urg)
{
XWMHints *wmh;
if ((wmh = XGetWMHints(dpy, cli->win)) != NULL) {
wmh->flags = (cli->urg = urg) ? wmh->flags | XUrgencyHint :
wmh->flags & ~XUrgencyHint;
XSetWMHints(dpy, cli->win, wmh);
XFree(wmh);
}
}
void
spawn(long arg)
{
if (fork() == 0) {
close(ConnectionNumber(dpy)); setsid();
struct sigaction act = { .sa_handler = SIG_DFL };
sigemptyset(&act.sa_mask); sigaction(SIGCHLD, &act, NULL);
execvp(((char *const *)arg)[0], (char *const *)arg);
die("swim: unable to run %s: ", ((char *const *)arg)[0]);
}
}