master ohmu/wmutils / scripts / killwa / killwa.c
ohmu  ·  2026-07-25
 1// Created by https://github.com/onodera-punpun
 2
 3#include <string.h>
 4#include <stdbool.h>
 5#include <stdio.h>
 6#include <stdlib.h>
 7#include <err.h>
 8#include <xcb/xcb.h>
 9#include <xcb/xcb_icccm.h>
10
11#include "util.h"
12
13static xcb_connection_t *conn;
14
15static void usage(char *);
16
17static void
18usage (char *name)
19{
20	fprintf(stderr, "usage: %s <wid> [wid...]\n", name);
21	exit(1);
22}
23
24static
25xcb_atom_t xcb_atom_get(xcb_connection_t *conn, char *name)
26{
27	xcb_intern_atom_cookie_t cookie = xcb_intern_atom(conn ,0, strlen(name), name);
28	xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, cookie, NULL);
29
30	if (!reply)
31		return XCB_ATOM_STRING;
32
33	return reply->atom;
34}
35
36void
37delete_window(xcb_window_t win)
38{
39	xcb_client_message_event_t ev;
40
41	ev.response_type = XCB_CLIENT_MESSAGE;
42	ev.sequence = 0;
43	ev.format = 32;
44	ev.window = win;
45	ev.type = xcb_atom_get(conn, "WM_PROTOCOLS");
46	ev.data.data32[0] = xcb_atom_get(conn, "WM_DELETE_WINDOW");
47	ev.data.data32[1] = XCB_CURRENT_TIME;
48
49	xcb_send_event(conn, 0, win, XCB_EVENT_MASK_NO_EVENT, (char *)&ev);
50}
51
52int
53main(int argc, char **argv)
54{	
55	xcb_window_t win = 0;
56
57	if (argc < 2)
58		usage(argv[0]);
59
60	init_xcb(&conn);
61
62	/* assume remaining arguments are windows */
63	while (*argv)
64		win = strtoul(*argv++, NULL, 16);
65
66		xcb_icccm_get_wm_protocols_reply_t reply;
67		unsigned int i = 0;
68		bool got = false;
69
70		if (xcb_icccm_get_wm_protocols_reply(conn, xcb_icccm_get_wm_protocols(conn, win, xcb_atom_get(conn, "WM_PROTOCOLS")), &reply, NULL)) {
71			for (; i != reply.atoms_len; ++i)
72				if ((got = reply.atoms[i] == xcb_atom_get(conn, "WM_DELETE_WINDOW")))
73					break;
74
75			xcb_icccm_get_wm_protocols_reply_wipe(&reply);
76		}
77		
78		if (got)
79			delete_window(win);
80		else
81			xcb_kill_client(conn, win);
82
83	xcb_flush(conn);
84
85	kill_xcb(&conn);
86
87	return 0;
88}