#!/usr/bin/python import subprocess import time import Xlib import Xlib.display import sys # note that http://tperl.blogspot.com/2007/09/x11-idle-time-and-focused-window-in.html # suggests focus instead... # # Window Name and Class for the focused window # # import Xlib.display # display = Xlib.display.Display() # focus = display.get_input_focus() # print "WM Class: %s" % ( focus.focus.get_wm_class(), ) # print "WM Name: %s" % ( focus.focus.get_wm_name(), ) import xidle def topwin(xdisp=[]): """get the windowid of the top window""" if not xdisp: xdisp.append(Xlib.display.Display()) rootwin = xdisp[0].screen().root # -> Xlib.display.Window for child in reversed(rootwin.query_tree().children): try: # specifically look for screensaver *regardless* of override-redirect... wm_class = child.get_wm_class() if not wm_class: continue # print "OK:", repr(wm_class) if "xscreensaver" in wm_class: # print "screensaver override_redirect:", child.get_attributes().override_redirect return child if "chbg" in wm_class: # print "chbg override_redirect:", child.get_attributes().override_redirect return child if wm_class and child.get_wm_name() and not child.get_attributes().override_redirect: return child except Xlib.error.BadWindow: print "BUG: child transient?", child # return rootwin.query_tree().children[-1] titled_apps = set([ 'XTerm', # XTERM 'URxvt', # URXVT 'emacs', # EMACS 'Kpdf', # KPDF 'Firefox-bin', # FIREFOX ]) def fmt_line(classes, name): """dump the output into a string so we can uniquify it""" classfmt = ", ".join([one.strip('"') for one in classes]) # simple things in titlebars if titled_apps & set(classes): # pick the shortest name, or at least the one we matched? return classes[0].upper() + ":" + name else: # or just do this always and hope? # pick the shortest leading name, here? return classfmt + ":" + (name or "None") if __name__ == "__main__": logfile = open(sys.argv[1], "a") lastline = None while True: # topid = ratpoison_topwin() topid = topwin() # hmmm. should we instead keep the max-recent-idle and display that? idle_ms = xidle.XScreenSaverQueryInfo().contents.idle try: classes = topid.get_wm_class() topname = topid.get_wm_name() except Xlib.error.BadWindow: print "BUG: topwin transient?", topid continue except Xlib.error.BadValue: # Xlib.error.BadValue: Xlib.error.BadValue: # code = 2, resource_id = 10, # sequence_number = 8180, major_opcode = 20, minor_opcode = 0 print "BUG: topwin get misfire?", topid continue if not classes: continue line = fmt_line(classes, topname) if line != lastline: print time.time(), idle_ms, line print >> logfile, time.time(), idle_ms, line logfile.flush() lastline = line time.sleep(0.3) # emacs hackery: # # (setq frame-title-format "%b") # vs. original (multiple-frames "%b" ("" invocation-name "@" system-name)) # but this breaks c-t e! # that's "bind e select emacs" # change it to "bind e select 1" for now?" # possibly use "set winname class" instead, and keep "emacs"? # -- no, that changes display too. or just fix c-t w too? # # per email, how about having a daemon that conkeror actually talks to? # # ahh, # xprop -notype -spy -id 0x1000060 WM_NAME # and my buffer function changes are plenty... # hmm, still seems a little unreliable about what's on top # but only a little; see if there's an explicit stacking-depth query # (Turns out that ignoring OverrideRedirect windows is good enough...) # can we directly measure idle time? with xkb? # xscreensaver or chbg are the titles I get, but they're gone now... override redirect? # chbg isn't, xscreensaver is. neither have wm_name, though, which is the problem... # 1176962097.03 chbg, Chbg:None # chbg override_redirect: 0 # 1176962100.1 xscreensaver, XScreenSaver:screensaver # screensaver override_redirect: 1