Skip to content

Instantly share code, notes, and snippets.

@kui
Last active February 25, 2024 19:21
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save kui/2622504 to your computer and use it in GitHub Desktop.
Save kui/2622504 to your computer and use it in GitHub Desktop.
get the active window on X window system.
// -*- 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);
}
@rr-
Copy link

rr- commented Jul 19, 2015

@fusir
Copy link

fusir commented Dec 25, 2017

Do you know what package for pkg-config will make it able to compile?

@rbreaves
Copy link

I am also sad to his blog post on this having disappeared.

@cxw42
Copy link

cxw42 commented Apr 21, 2020

@kui Thank you for this code! What is the license?

@kui
Copy link
Author

kui commented Apr 22, 2020

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.

@cxw42
Copy link

cxw42 commented Apr 22, 2020

@kui Thank you!

@rbreaves
Copy link

@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