Last active
September 11, 2024 01:47
-
-
Save kui/2622504 to your computer and use it in GitHub Desktop.
get the active window on X window system.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- coding:utf-8-unix; mode:c; -*- | |
// | |
// get the active window on X window system | |
// | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <locale.h> | |
#include <X11/Xlib.h> // `apt-get install libx11-dev` | |
#include <X11/Xmu/WinUtil.h> // `apt-get install libxmu-dev` | |
Bool xerror = False; | |
Display* open_display(){ | |
printf("connecting X server ... "); | |
Display* d = XOpenDisplay(NULL); | |
if(d == NULL){ | |
printf("fail\n"); | |
exit(1); | |
}else{ | |
printf("success\n"); | |
} | |
return d; | |
} | |
int handle_error(Display* display, XErrorEvent* error){ | |
printf("ERROR: X11 error\n"); | |
xerror = True; | |
return 1; | |
} | |
Window get_focus_window(Display* d){ | |
Window w; | |
int revert_to; | |
printf("getting input focus window ... "); | |
XGetInputFocus(d, &w, &revert_to); // see man | |
if(xerror){ | |
printf("fail\n"); | |
exit(1); | |
}else if(w == None){ | |
printf("no focus window\n"); | |
exit(1); | |
}else{ | |
printf("success (window: %d)\n", (int)w); | |
} | |
return w; | |
} | |
// get the top window. | |
// a top window have the following specifications. | |
// * the start window is contained the descendent windows. | |
// * the parent window is the root window. | |
Window get_top_window(Display* d, Window start){ | |
Window w = start; | |
Window parent = start; | |
Window root = None; | |
Window *children; | |
unsigned int nchildren; | |
Status s; | |
printf("getting top window ... \n"); | |
while (parent != root) { | |
w = parent; | |
s = XQueryTree(d, w, &root, &parent, &children, &nchildren); // see man | |
if (s) | |
XFree(children); | |
if(xerror){ | |
printf("fail\n"); | |
exit(1); | |
} | |
printf(" get parent (window: %d)\n", (int)w); | |
} | |
printf("success (window: %d)\n", (int)w); | |
return w; | |
} | |
// search a named window (that has a WM_STATE prop) | |
// on the descendent windows of the argment Window. | |
Window get_named_window(Display* d, Window start){ | |
Window w; | |
printf("getting named window ... "); | |
w = XmuClientWindow(d, start); // see man | |
if(w == start) | |
printf("fail\n"); | |
printf("success (window: %d)\n", (int) w); | |
return w; | |
} | |
// (XFetchName cannot get a name with multi-byte chars) | |
void print_window_name(Display* d, Window w){ | |
XTextProperty prop; | |
Status s; | |
printf("window name:\n"); | |
s = XGetWMName(d, w, &prop); // see man | |
if(!xerror && s){ | |
int count = 0, result; | |
char **list = NULL; | |
result = XmbTextPropertyToTextList(d, &prop, &list, &count); // see man | |
if(result == Success){ | |
printf("\t%s\n", list[0]); | |
}else{ | |
printf("ERROR: XmbTextPropertyToTextList\n"); | |
} | |
}else{ | |
printf("ERROR: XGetWMName\n"); | |
} | |
} | |
void print_window_class(Display* d, Window w){ | |
Status s; | |
XClassHint* class; | |
printf("application: \n"); | |
class = XAllocClassHint(); // see man | |
if(xerror){ | |
printf("ERROR: XAllocClassHint\n"); | |
} | |
s = XGetClassHint(d, w, class); // see man | |
if(xerror || s){ | |
printf("\tname: %s\n\tclass: %s\n", class->res_name, class->res_class); | |
}else{ | |
printf("ERROR: XGetClassHint\n"); | |
} | |
} | |
void print_window_info(Display* d, Window w){ | |
printf("--\n"); | |
print_window_name(d, w); | |
print_window_class(d, w); | |
} | |
int main(void){ | |
Display* d; | |
Window w; | |
// for XmbTextPropertyToTextList | |
setlocale(LC_ALL, ""); // see man locale | |
d = open_display(); | |
XSetErrorHandler(handle_error); | |
// get active window | |
w = get_focus_window(d); | |
w = get_top_window(d, w); | |
w = get_named_window(d, w); | |
print_window_info(d, w); | |
} |
@kui Thank you for this code! What is the license?
http://k-ui.jp/blog/2012/05/07/get-active-window-on-x-window-system/ might be missed from my blog... and I can't remember it. I removed it from this gist.
@cxw42 I'm not going to claim a license for this code. Please feel free to use it.
@kui Thank you!
@kui Also giving you my thanks, I've already been using it as a base for Kinto. It looks a good deal different at this point and I am moving on to re-using xkeysnail and contributing code to that project to make it a better replacement for my own use case scenarios.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am also sad to his blog post on this having disappeared.