angelspie - X11 window management, global and more hotkeys

The name is a reference to devilspie, a similar utility. It is notable for the fact that the config is written in the Lisp dialect, despite this it has very limited capabilities. Especially for utilities like wmctl, etc.





You can do a lot more with the wnck library, and even more with gdk.





For global hotkeys, I used libkeybinder, I used to do this on "bare" xlib, but it's more convenient (and portable). However, xlib / xtest is also used - to emulate button presses. But these functions are optional.





I chose yaml as the config format. Older versions used a python config, but I decided that yaml is more convenient for end users. Moreover, you can embed code in python and sh into it.





I will not go into the details of the implementation. There is a lot of magic and metaprogramming, some of the code is generated.





I'd rather show an example of a config that uses some of the capabilities. By the way, new rules can be generated from the command line, it will take the name and class_group of the active window.





click_with_F1:
  if:
    key: F1
  then:
    click: 3

      
      



The simplest example. Pressing F1 will emulate a right mouse button click.





save_image:
  if:
    key: F2
    class_group: Google-chrome
  then:
    - click: 3
    - sleep: 0.1
    - press: v
    - enable: autosave
      
      



Pressing F2 will right-click, v (save as) and activate the autosave rule





# Would type "filename" and press alt+s to save when Save file dialog of chrome appears. But only after we pressed F2.
autosave:
  if:
    name: Save File
    class_group: Google-chrome
    enabled: false
  then:
    - press: f i l e n a m e Alt+S
# Disable autosaving every 2 secs.
timer_test:
  if:
    event: timer 2
  then:
    disable: autosave
      
      



When the Save File window appears, it will remember the file name and save it. This rule is disabled after 2 seconds. The file name will be auto-filled only when you press F2, and not for any windows.





print_debug:
  if:
      event: never
  then:
    debug:
    
win_changed:
  if:
    event: active_window_changed
  then:
    echo: "window changed {name} {class_group}"
switched_to_xterm:
  if:
    name:
      contains: mc
    class_group: XTerm
  then:
    - maximize:
    - disable: win_changed
    - trigger: print_debug
not_in_mc:
  if:
    or:
      class_group:
        ne: xterm
      name:
        contains_not: mc
  then:
    - sh: date
    - py: from datetime import datetime;print(datetime.now())

      
      



print_debug trigger, . . wnck gdk. wnck. if , sh.





- . . , . , .





, , - mpv. , .





By the way. although there is a lot of magic in the code, I think it has a good architecture. I would like to hear criticism. But here the balance between the comprehensibility of the code and its versatility / compactness is important. The emphasis is on the latter.





The code is available on github and pypi. By the way. where else to place the program? I would like to convey it to desktop users. You might need to add a gui, but there are too many features. It is more convenient to just edit the config.








All Articles