Skip to content

Instantly share code, notes, and snippets.

@Tucos
Created August 4, 2014 19:17
Show Gist options
  • Save Tucos/1de965f11403954d410e to your computer and use it in GitHub Desktop.
Save Tucos/1de965f11403954d410e to your computer and use it in GitHub Desktop.
Clickable conky thingies
/* Compile with `make CFLAGS='-std=c99' LOADLIBES='-lX11' buttonpress` */
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
Window GetWindowFromID(Display *display, Window start, int targetid, int level) {
Window root, parent, *children;
unsigned int nchildren;
//for (int i = 0; i < level; ++i) printf(" ");
//printf("0x%lx", start);
int status = XQueryTree(display, start, &root, &parent, &children, &nchildren);
if (!status) {
fprintf(stderr, "Failed to query tree\n");
return 0;
}
//printf(" %d\n", nchildren);
//fflush(stdout);
for (int i = 0; i < nchildren; ++i) {
if (children[i] == targetid) return children[i];
}
++level;
// Nothing matched, try for each child
for (int i = 0; i < nchildren; ++i) {
Window w = GetWindowFromID(display, children[i], targetid, level);
if (w) return w;
}
return 0;
}
int main(int argc, char **argv) {
if (argc < 2) return 1;
Display *display = XOpenDisplay(NULL);
int id = strtol(argv[1], NULL, 0);
if (!id) return 3;
//printf("Looking for window with id 0x%x\n", id);
Window win = GetWindowFromID(display, DefaultRootWindow(display), id, 0);
if (!win) return 2;
XSelectInput(display, win, ButtonReleaseMask);
bool quit = false;
XEvent ev;
while (!quit) {
XNextEvent(display, &ev);
switch (ev.type) {
case ButtonRelease: {
XButtonEvent bev = ev.xbutton;
printf("win: %d,%d; root: %d,%d; state: %d; button: %d\n",
bev.x, bev.y,
bev.x_root, bev.y_root,
bev.state, bev.button);
fflush(stdout);
break;
}
}
}
XCloseDisplay(display);
return 0;
}
require 'cairo'
local initialized = false
local clickfile
local clickcommand
local hotspots = {}
local function context()
if conky_window == nil then return nil end
local surface = cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, conky_window.width, conky_window.height)
local context = cairo_create(surface)
return context
end
local function initialize()
if initialized or conky_window == nil then return end
local runtimedir = os.getenv("XDG_RUNTIME_DIR")
if runtimedir == nil then runtimedir = "/tmp" end
if runtimedir:sub(#runtimedir,#runtimedir) ~= "/" then
runtimedir = runtimedir .. "/"
end
clickfile = string.format("%sconky_%d", runtimedir, conky_window.window)
clickcommand = string.format("buttonpress 0x%x >>%s 2>&1 &", conky_window.window, clickfile)
os.execute(clickcommand)
clickcommand = string.format("buttonpress 0x%x", conky_window.window)
table.insert(hotspots, { x1 = 10, y1 = 0, x2 = 30, y2 = 30, click = false})
initialized = true
end
function conky_shutdown()
local pidcmd = string.format("ps a | grep '%s' | grep -v grep | awk '{print $1}'", clickcommand)
local ps = io.popen(pidcmd)
local pid = ps:read("*l")
if not pid == nil then
print(string.format("killing pid %s", pid))
os.execute(string.format("kill -s 15 %s", pid))
end
os.remove(clickfile)
end
local function read_clicks()
local trunc = false
local points = {}
local f = io.open(clickfile, "r")
for line in f:lines() do
--print(line)
-- win: 6,10; root: 6,29; state: 272; button: 1
local x,y = line:match("win: (%d+),(%d+)")
x = tonumber(x)
y = tonumber(y)
table.insert(points, {x = x, y = y})
end
f:close()
-- trim the file
f = io.open(clickfile, "w")
f:close()
--TODO see if repeated clicks should be ignored
for i,p in ipairs(points) do
--print(string.format("point: %d,%d", p.x, p.y))
for j,h in ipairs(hotspots) do
if p.x > h.x1 and p.x < h.x2 and
p.y > h.y1 and p.y < h.y2 then
--print("clicked")
h.click = not h.click
end
end
end
points = {}
end
function conky_draw_pre()
if conky_window == nil then return end
if not initialized then initialize() end
local c = context()
if c == nil then return end
read_clicks()
if hotspots[1].click then
cairo_set_source_rgb(c, 1, 0, 0)
else
cairo_set_source_rgb(c, 0, 1, 0)
end
cairo_rectangle(c, 10, 0, 20, 20)
cairo_fill(c)
end
own_window yes
own_window_type panel
alignment tl
minimum_size 1366 10
lua_load dock.lua
lua_draw_hook_pre draw_pre
lua_shutdown_hook shutdown
TEXT
$updates
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment