From ebd8c2726b8caac6adc00cf15c5631e51d05ba1f Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 16 Dec 2024 02:21:38 +0100 Subject: Rewrite linux global hotkey to not depend on any libraries (also allows it to work on non-systemd systems(?)), remove unused gsr-window-name --- tools/gsr-window-name/main.c | 187 ------------------------------------------- 1 file changed, 187 deletions(-) delete mode 100644 tools/gsr-window-name/main.c (limited to 'tools/gsr-window-name') diff --git a/tools/gsr-window-name/main.c b/tools/gsr-window-name/main.c deleted file mode 100644 index 8ebf1e0..0000000 --- a/tools/gsr-window-name/main.c +++ /dev/null @@ -1,187 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include - -typedef enum { - CAPTURE_TYPE_FOCUSED, - CAPTURE_TYPE_CURSOR -} capture_type; - -static bool window_has_atom(Display *dpy, Window window, Atom atom) { - Atom type; - unsigned long len, bytes_left; - int format; - unsigned char *properties = NULL; - if(XGetWindowProperty(dpy, window, atom, 0, 1024, False, AnyPropertyType, &type, &format, &len, &bytes_left, &properties) < Success) - return false; - - if(properties) - XFree(properties); - - return type != None; -} - -static bool window_is_user_program(Display *dpy, Window window) { - const Atom net_wm_state_atom = XInternAtom(dpy, "_NET_WM_STATE", False); - const Atom wm_state_atom = XInternAtom(dpy, "WM_STATE", False); - return window_has_atom(dpy, window, net_wm_state_atom) || window_has_atom(dpy, window, wm_state_atom); -} - -static Window get_window_at_cursor_position(Display *dpy) { - Window root_window = None; - Window window = None; - int dummy_i; - unsigned int dummy_u; - int cursor_pos_x = 0; - int cursor_pos_y = 0; - XQueryPointer(dpy, DefaultRootWindow(dpy), &root_window, &window, &dummy_i, &dummy_i, &cursor_pos_x, &cursor_pos_y, &dummy_u); - return window; -} - -static Window get_focused_window(Display *dpy, capture_type cap_type) { - const Atom net_active_window_atom = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - Window focused_window = None; - - if(cap_type == CAPTURE_TYPE_FOCUSED) { - // Atom type = None; - // int format = 0; - // unsigned long num_items = 0; - // unsigned long bytes_left = 0; - // unsigned char *data = NULL; - // XGetWindowProperty(dpy, DefaultRootWindow(dpy), net_active_window_atom, 0, 1, False, XA_WINDOW, &type, &format, &num_items, &bytes_left, &data); - - // fprintf(stderr, "focused window: %p\n", (void*)data); - - // if(type == XA_WINDOW && num_items == 1 && data) - // return *(Window*)data; - - int revert_to = 0; - XGetInputFocus(dpy, &focused_window, &revert_to); - if(focused_window && focused_window != DefaultRootWindow(dpy) && window_is_user_program(dpy, focused_window)) - return focused_window; - } - - focused_window = get_window_at_cursor_position(dpy); - if(focused_window && focused_window != DefaultRootWindow(dpy) && window_is_user_program(dpy, focused_window)) - return focused_window; - - return None; -} - -static char* get_window_title(Display *dpy, Window window) { - const Atom net_wm_name_atom = XInternAtom(dpy, "_NET_WM_NAME", False); - const Atom wm_name_atom = XInternAtom(dpy, "_NET_WM_NAME", False); - const Atom utf8_string_atom = XInternAtom(dpy, "UTF8_STRING", False); - - Atom type = None; - int format = 0; - unsigned long num_items = 0; - unsigned long bytes_left = 0; - unsigned char *data = NULL; - XGetWindowProperty(dpy, window, net_wm_name_atom, 0, 1024, False, utf8_string_atom, &type, &format, &num_items, &bytes_left, &data); - - if(type == utf8_string_atom && format == 8 && data) - return (char*)data; - - type = None; - format = 0; - num_items = 0; - bytes_left = 0; - data = NULL; - XGetWindowProperty(dpy, window, wm_name_atom, 0, 1024, False, 0, &type, &format, &num_items, &bytes_left, &data); - - if((type == XA_STRING || type == utf8_string_atom) && data) - return (char*)data; - - return NULL; -} - -static const char* strip(const char *str, int *len) { - int str_len = strlen(str); - for(int i = 0; i < str_len; ++i) { - if(str[i] != ' ') { - str += i; - str_len -= i; - break; - } - } - - for(int i = str_len - 1; i >= 0; --i) { - if(str[i] != ' ') { - str_len = i + 1; - break; - } - } - - *len = str_len; - return str; -} - -static void print_str_strip(const char *str) { - int len = 0; - str = strip(str, &len); - printf("%.*s", len, str); -} - -static int x11_ignore_error(Display *dpy, XErrorEvent *error_event) { - (void)dpy; - (void)error_event; - return 0; -} - -static void usage(void) { - fprintf(stderr, "usage: gsr-window-name \n"); - fprintf(stderr, "options:\n"); - fprintf(stderr, " focused The class/name of the focused window is returned. If no window is focused then the window beneath the cursor is returned instead\n"); - fprintf(stderr, " cursor The class/name of the window beneath the cursor is returned\n"); - exit(1); -} - -int main(int argc, char **argv) { - if(argc != 2) - usage(); - - const char *cap_type_str = argv[1]; - capture_type cap_type = CAPTURE_TYPE_FOCUSED; - if(strcmp(cap_type_str, "focused") == 0) { - cap_type = CAPTURE_TYPE_FOCUSED; - } else if(strcmp(cap_type_str, "cursor") == 0) { - cap_type = CAPTURE_TYPE_CURSOR; - } else { - fprintf(stderr, "error: invalid option '%s', expected either 'focused' or 'cursor'\n", cap_type_str); - usage(); - } - - Display *dpy = XOpenDisplay(NULL); - if(!dpy) { - fprintf(stderr, "Error: failed to connect to the X11 server\n"); - exit(1); - } - - XSetErrorHandler(x11_ignore_error); - - const Window focused_window = get_focused_window(dpy, cap_type); - if(focused_window == None) - exit(2); - - // Window title is not always ideal (for example for a browser), but for games its pretty much required - char *window_title = get_window_title(dpy, focused_window); - if(window_title) { - print_str_strip(window_title); - exit(0); - } - - XClassHint class_hint = {0}; - XGetClassHint(dpy, focused_window, &class_hint); - if(class_hint.res_class) { - print_str_strip(class_hint.res_class); - exit(0); - } - - return 2; -} -- cgit v1.2.3