src/tint2-send/tint2-send.c (raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
#include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <stdio.h> #include <stdlib.h> #include <string.h> static Display *display = 0; /* From wmctrl */ char *get_property(Window window, Atom xa_prop_type, const char *prop_name) { Atom xa_prop_name = XInternAtom(display, prop_name, False); Atom xa_ret_type; int ret_format; unsigned long ret_nitems; unsigned long ret_bytes_after; unsigned long tmp_size; unsigned char *ret_prop; if (XGetWindowProperty(display, window, xa_prop_name, 0, 1024, False, xa_prop_type, &xa_ret_type, &ret_format, &ret_nitems, &ret_bytes_after, &ret_prop) != Success) { return NULL; } if (xa_ret_type != xa_prop_type) { XFree(ret_prop); return NULL; } /* Correct 64 Architecture implementation of 32 bit data */ tmp_size = (ret_format / 8) * ret_nitems; if (ret_format == 32) tmp_size *= sizeof(long) / 4; char *ret = (char *)calloc(1, tmp_size + 1); memcpy(ret, ret_prop, tmp_size); XFree(ret_prop); return ret; } int is_tint2(Window window) { XWindowAttributes attr = {}; if (!XGetWindowAttributes(display, window, &attr)) return 0; // if (attr.map_state != IsViewable) // return 0; char *wm_class = get_property(window, XA_STRING, "WM_NAME"); if (!wm_class) { return 0; } int class_match = 0; if (strcmp(wm_class, "tint2") == 0) { class_match = 1; } free(wm_class); return class_match; } void handle_tint2_window(Window window, char *action, char **args) { if (!is_tint2(window)) return; if (strcmp(action, "show") == 0) { fprintf(stderr, "Showing tint2 window: %lx\n", window); XEvent event = {}; event.xcrossing.type = EnterNotify; event.xcrossing.window = window; event.xcrossing.mode = NotifyNormal; event.xcrossing.detail = NotifyVirtual; event.xcrossing.same_screen = True; XSendEvent(display, window, False, 0, &event); XFlush(display); } else if (strcmp(action, "hide") == 0) { fprintf(stderr, "Hiding tint2 window: %lx\n", window); XEvent event = {}; event.xcrossing.type = LeaveNotify; event.xcrossing.window = window; event.xcrossing.mode = NotifyNormal; event.xcrossing.detail = NotifyVirtual; event.xcrossing.same_screen = True; XSendEvent(display, window, False, 0, &event); XFlush(display); } else if (strcmp(action, "refresh-execp") == 0) { XEvent event = {}; char *name = args[0]; if (!name) { fprintf(stderr, "Error: missing execp name\n"); return; } if (!name[0]) { fprintf(stderr, "Error: empty execp name\n"); return; } if (strlen(name) > sizeof(event.xclient.data.b)) { fprintf(stderr, "Error: execp name bigger than %ld bytes\n", sizeof(event.xclient.data.b)); return; } fprintf(stderr, "Refreshing execp '%s' for window: %lx\n", name, window); event.xclient.type = ClientMessage; event.xclient.window = window; event.xclient.send_event = True; event.xclient.message_type = XInternAtom(display, "_TINT2_REFRESH_EXECP", False); event.xclient.format = 8; strncpy(event.xclient.data.b, name, sizeof(event.xclient.data.b)); XSendEvent(display, window, False, 0, &event); XFlush(display); } else { fprintf(stderr, "Error: unknown action %s\n", action); } } typedef void window_callback_t(Window window, char *action, char **args); void walk_windows(Window node, window_callback_t *callback, char *action, char **args) { callback(node, action, args); Window root = 0; Window parent = 0; Window *children = 0; unsigned int nchildren = 0; if (!XQueryTree(display, node, &root, &parent, &children, &nchildren)) { return; } for (unsigned int i = 0; i < nchildren; i++) { walk_windows(children[i], callback, action, args); } } int main(int argc, char **argv) { display = XOpenDisplay(NULL); if (!display ) { fprintf(stderr, "Failed to open X11 connection\n"); exit(1); } argc--, argv++; if (!argc) { fprintf(stderr, "Usage: tint2-send [show|hide|refresh-execp]\n"); exit(1); } char *action = argv[0]; char **args = argv + 1; walk_windows(DefaultRootWindow(display), handle_tint2_window, action, args); return 0; } |