master ohmu/wmutils / src / core / atomx.c
ohmu  ·  2026-07-25
  1/* See LICENSE file for copyright and license details. */
  2
  3#include <err.h>
  4#include <stdio.h>
  5#include <stdlib.h>
  6#include <string.h>
  7#include <xcb/xcb.h>
  8#include <xcb/xcb_aux.h>
  9
 10#include "util.h"
 11#include "arg.h"
 12
 13#define MAXLEN 512
 14
 15static xcb_connection_t *conn;
 16
 17void
 18usage(char *name)
 19{
 20	fprintf(stderr, "%s [-d] atom[=value] wid\n", name);
 21}
 22
 23xcb_atom_t
 24add_atom(xcb_atom_t type, char *name, size_t len)
 25{
 26	xcb_atom_t atom;
 27	xcb_intern_atom_cookie_t c;
 28	xcb_intern_atom_reply_t *r;
 29
 30	c = xcb_intern_atom(conn, 0, len, name);
 31	r = xcb_intern_atom_reply(conn, c, NULL);
 32	if (!r)
 33		return 0;
 34
 35	atom = r->atom;
 36	free(r);
 37
 38	return atom;
 39}
 40
 41int
 42set_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t len, void *data)
 43{
 44	int errcode;
 45	xcb_void_cookie_t c;
 46	xcb_generic_error_t *e;
 47
 48	c = xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE,
 49		wid, atom, type, 8, len, data);
 50	e = xcb_request_check(conn, c);
 51	if (!e)
 52		return 0;
 53
 54	errcode = e->error_code;
 55	free(e);
 56
 57	return errcode;
 58}
 59
 60int
 61get_atom(xcb_window_t wid, xcb_atom_t atom, char *data, xcb_atom_t *type)
 62{
 63	size_t n;
 64	xcb_get_property_cookie_t c;
 65	xcb_get_property_reply_t *r;
 66
 67	c = xcb_get_property(conn, 0, wid, atom, XCB_ATOM_ANY, 0, MAXLEN);
 68	r = xcb_get_property_reply(conn, c, NULL);
 69	if (!r)
 70		return -1;
 71
 72	if (!(n = xcb_get_property_value_length(r))) {
 73		free(r);
 74		return -1;
 75	}
 76
 77	strncpy(data, xcb_get_property_value(r), n);
 78	data[n] = 0;
 79
 80	*type = r->type;
 81
 82	free(r);
 83
 84	return 0;
 85}
 86
 87
 88int
 89main(int argc, char **argv)
 90{
 91	int i, dflag = 0;
 92	char *key, *val, *argv0;
 93	char data[MAXLEN];
 94	xcb_window_t wid;
 95	xcb_atom_t atom;
 96
 97	ARGBEGIN {
 98	case 'd':
 99		dflag = 1;
100		break;
101	default:
102		usage(argv0);
103		return -1;
104	} ARGEND;
105
106	if (argc < 1)
107		return -1;
108
109	key = strtok(argv[0], "=");
110	val = strtok(NULL, "=");
111
112	init_xcb(&conn);
113
114	for (i = 0; i < argc - 1; i++) {
115		wid = strtoul(argv[i+1], NULL, 16);
116
117		/* retrieve atom ID from server */
118		atom = add_atom(XCB_ATOM_STRING, key, strlen(key));
119		if (!atom)
120			return -1;
121
122		/* set property on window (must be a string) */
123		if (val)
124			set_atom(wid, atom, XCB_ATOM_STRING, strlen(val), val);
125
126		/* remove property from window */
127		if (dflag)
128			xcb_delete_property(conn, wid, atom);
129
130		/* retrieve and print atom value to stdout */
131		xcb_atom_t type;
132		if (!get_atom(wid, atom, data, &type))
133			switch (type) {
134				case XCB_ATOM_INTEGER:
135					printf("%d\n", *data);
136					break;
137				default:
138					printf("%s\n", data);
139			}
140	}
141
142	kill_xcb(&conn);
143
144	return 0;
145}