xkeysnail icon indicating copy to clipboard operation
xkeysnail copied to clipboard

Permit keymap conditions to test against wm_name

Open Lenbok opened this issue 3 years ago • 5 comments

This allows bindings such as:

define_keymap(lambda wm_class, device_name, wm_name: "Google Docs" in wm_name, {
    # Google Docs uses M-slash as an execute-extended-command binding, let's make it more emacsish
    K("M-x"): K("M-slash")
})

Notes:

  • Xlib built-in get_wm_name function doesn't support UTF-8 window names, so we use a custom function. Thanks to https://github.com/yoshinari-nomura/xkeysnail/commit/2a74e002a5c43fd757b91fee753d02b38782df36

  • Keymap condition testing still looks at the number of args expected, and additionally passes wm_name if the number of args is 3 respectively. It's a bit ugly, but maintains backward compatibility for anyone already using the two argument version. This signature based condition testing was previously only used in the conditional modmap testing, now it is in global keymap testing in transform, so conditions using device and window name should also work there.

Fixes #122

Lenbok avatar Apr 09 '21 04:04 Lenbok

BTW, I haven't tried using global keymap conditions that use device name - it seems to me that some calls to on_key don't directly originate from on_event and wouldn't have a device name assigned since they are synthetic presses. I'm not really familiar with when those would occur, but the situation with this PR is no worse than currently anyway.

Lenbok avatar Apr 09 '21 04:04 Lenbok

I've been using this feature for months. Really useful for me. I hope it could be merged to main line.

yoshinari-nomura avatar Oct 26 '21 02:10 yoshinari-nomura

Going to see about merging this into my dev branch on my fork. I have completely forgotten about this PR. Thanks @Lenbok!

rbreaves avatar Jan 17 '22 01:01 rbreaves

Just to note I had issues when merging this into my fork, the merge appeared to go ok though. Perhaps it was just my specific config file was too complicated in general or it is not as backwards compatible as it might seem. I am not sure. I will have to explore this more.

One thing that I think would be better though would be to nest it.. so instead of

define_keymap(lambda wm_class, device_name, wm_name: "Google Docs" in wm_name, {
    # Google Docs uses M-slash as an execute-extended-command binding, let's make it more emacsish
    K("M-x"): K("M-slash")
})

You'd write it like

define_keymap(re.compile("Firefox", re.IGNORECASE),{
  # some hotkey sequence that only makes since on a window with this title
  define_keymap(lambda  wm_name: "Google Docs" in wm_name, {
      # Google Docs uses M-slash as an execute-extended-command binding, let's make it more emacsish
      K("M-x"): K("M-slash")
  }
  # some hotkey sequence that only makes since on a window with this title
  define_keymap(lambda  wm_name: "Preferences" in wm_name, {
      K("M-p"): K("M-j")
  }
})

At least this was the use case I had mind - and maybe I can write it that way already lol. I have not tried to do so.

rbreaves avatar Jan 24 '22 05:01 rbreaves

I couldn't get the branch to work for me, running window.get_full_text_property returned the error 'Window' object has no attribute 'get_full_text_property' which I imagine is either due to library versions of xlib, Cinnamon (Linux Mint) not being supported, or something else. If anyone has the same issue, I got around it by changing line 22 of transform.py to

from subprocess import run
(...)
wmname = run("xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME", 
                 capture_output=True, shell=True).stdout

BrunoGomesCoelho avatar Mar 17 '22 18:03 BrunoGomesCoelho