Skip to content

Instantly share code, notes, and snippets.

@Lokaltog
Last active August 29, 2015 13:56
Show Gist options
  • Save Lokaltog/9191303 to your computer and use it in GitHub Desktop.
Save Lokaltog/9191303 to your computer and use it in GitHub Desktop.
Dump window manager info to JSON (for usage with wkline)
#include <fcntl.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <webkit/webkit.h>
#include <xcb/xcb.h>
#include <xcb/xcb_atom.h>
#include <xcb/xcb_ewmh.h> // dependency on xcb-util-wm
#include <jansson.h>
#ifndef MIN
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#endif
#define PROPERTY_MAX_LEN 256
#define DESKTOP_MAX_LEN 10
typedef struct desktop_t {
bool is_selected;
bool is_urgent;
bool is_valid;
int clients_len;
} desktop_t;
bool
get_active_window_name(xcb_ewmh_connection_t *ewmh, int screen_nbr, char *window_name) {
xcb_window_t active_window;
xcb_ewmh_get_utf8_strings_reply_t window_data;
size_t len;
if (! xcb_ewmh_get_active_window_reply(ewmh, xcb_ewmh_get_active_window_unchecked(ewmh, screen_nbr), &active_window, NULL)) {
fprintf(stderr, "Found no active window\n");
return false;
}
if (! xcb_ewmh_get_wm_name_reply(ewmh, xcb_ewmh_get_wm_name_unchecked(ewmh, active_window), &window_data, NULL)) {
fprintf(stderr, "Could not read WM_NAME from active window\n");
return false;
}
len = MIN(PROPERTY_MAX_LEN, window_data.strings_len + 1);
memcpy(window_name, window_data.strings, len);
window_name[len] = 0;
xcb_ewmh_get_utf8_strings_reply_wipe(&window_data);
return true;
}
bool
get_desktop_list(xcb_ewmh_connection_t *ewmh, int screen_nbr, desktop_t *desktops) {
unsigned short i;
uint32_t desktop_curr, desktop_len, client_desktop;
xcb_ewmh_get_windows_reply_t clients;
// get current desktop
if (! xcb_ewmh_get_current_desktop_reply(ewmh, xcb_ewmh_get_current_desktop_unchecked(ewmh, screen_nbr), &desktop_curr, NULL)) {
fprintf(stderr, "Could not get current desktop\n");
return false;
}
// get desktop count
if (! xcb_ewmh_get_number_of_desktops_reply(ewmh, xcb_ewmh_get_number_of_desktops_unchecked(ewmh, screen_nbr), &desktop_len, NULL)) {
fprintf(stderr, "Could not get desktop count\n");
return false;
}
for (i = 0; i < desktop_len; i++) {
desktops[i].is_selected = i == desktop_curr;
desktops[i].is_valid = true;
}
// get clients
if (! xcb_ewmh_get_client_list_reply(ewmh, xcb_ewmh_get_client_list_unchecked(ewmh, screen_nbr), &clients, NULL)) {
fprintf(stderr, "Could not get client list\n");
return false;
}
for (i = 0; i < clients.windows_len; i++) {
if (! xcb_ewmh_get_wm_desktop_reply(ewmh, xcb_ewmh_get_wm_desktop_unchecked(ewmh, clients.windows[i]), &client_desktop, NULL)) {
continue;
}
desktops[client_desktop].clients_len++;
// TODO check urgent hint and assign to desktop
}
xcb_ewmh_get_windows_reply_wipe(&clients);
return true;
}
int
main (int argc, char *argv[]) {
xcb_connection_t *conn;
int screen_nbr = 0;
conn = xcb_connect(NULL, &screen_nbr);
xcb_ewmh_connection_t ewmh;
xcb_intern_atom_cookie_t *ewmh_cookie = xcb_ewmh_init_atoms(conn, &ewmh);
xcb_ewmh_init_atoms_replies(&ewmh, ewmh_cookie, NULL);
char active_window_name[PROPERTY_MAX_LEN];
get_active_window_name(&ewmh, screen_nbr, active_window_name);
desktop_t desktops[DESKTOP_MAX_LEN] = {};
get_desktop_list(&ewmh, screen_nbr, desktops);
unsigned short i;
json_t *json_desktop_object = json_object();
json_t *json_desktops_array = json_array();
json_object_set_new(json_desktop_object, "current_window", json_string(active_window_name));
json_object_set_new(json_desktop_object, "desktops", json_desktops_array);
for (i = 0; i < DESKTOP_MAX_LEN; i++) {
if (! desktops[i].is_valid) {
break;
}
json_t *json_desktop = json_object();
json_object_set_new(json_desktop, "clients_len", json_integer(desktops[i].clients_len));
json_array_append_new(json_desktops_array, json_desktop);
if (desktops[i].is_selected) {
json_object_set_new(json_desktop_object, "current_desktop", json_integer(i));
}
}
char *json_payload = json_dumps(json_desktop_object, 0);
printf("%s", json_payload);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment