What is the proper way to disable keymap items in the user keyconfig via addon?

The addon I’m working on uses a lot of complex keybinds, as such I handle keybinding through the addon keyconfig to make it as painless as possible for the user. However, I’m finding a lot of downstream conflicts, or value conflicts where the input event is being consumed before it gets to my addon. Long story short, I need to rebind, and sometimes even deactivate hotkeys that are in the user keyconfig. What is the proper way to do this? Simply searching through wm.keyconfigs.user is effective for disabling the keymap items in question, but storing the KMI in a list to be re-activated when the addon is unregistered is not working as I would have expected… it’s reactivating completely unrelated keymap items, so I’m guessing the keymap items I stored in a list are getting shifted around (pointers changing, whatever under the hood nonsense you want to use to describe it). How do I get around this?

And to stave off the inevitable “bubububut you shouldn’t disable user keymap items”, let me give you an example: Currently, the default keymap has the right click context menu in 3D View triggering on PRESS, which is obnoxious because CLICK does the exact same thing and doesn’t consume the event for literally every other downstream action (TWEAK, DRAG, etc). Another example- My addon makes heavy use of the top-row number keys, which up until 3 days ago was perfectly fine, I grabbed the latest nightly and now there are default keys bound all over the place. Mesh, Object Mode, you name it.

You didn’t mention it, but based on the way you’re saying things I’m assuming your add-on has a modal operator. I strongly believe these key conflicts would not be a problem if add-on devs had access to modal keymaps in the same way that the Knife Topology Tool (mesh.knife_tool), the Edge Bevel (mesh.bevel) and other built-in operators have.

All Python modal operator demos suggest that we react to raw key events (‘LEFTMOUSE’, ‘BACKSPACE’, ‘LEFT_CTRL’ etc.), but the built-in modal operators handle it way better.
Essentially, you don’t care what key combo is being pressed, you only care what action it translates to – ‘CANCEL’, ‘CONFIRM’, ‘NEW_CUT’, ‘INCREASE’ etc.

So here’s an appeal to @ideasman42 to please consider adding modal keymaps to Python operators. If your modal operator is running and the users presses a key combo to an action of that operator, even if that same key combo is also used by other operators, the event goes to you first since you’re the one that’s running. That’s how you get priority, you won’t need to worry about disabling other keymap items.

All the tech needed for this already exists, but it needs to be exposed to Python.
We’re talking about…

  1. a way to define a bpy.props.EnumProperty with all the modal items,
  2. a way of associating them with your operator,
  3. for the event loop to include the action identifier in some attribute of the Event object sent to the Python operator’s .modal() function.
    (I can’t use a 3rd link in my post because I’m a recent user, the relevant source is this: https://developer.blender.org/diffusion/B/browse/master/source/blender/editors/mesh/editmesh_bevel.c$656-802)

This would let the Input preferences screen show your add-on modal keymap and the user can decide what key combo they want to use for each action, like they already do for the built-in modal operators:

And here’s another annoying example… I don’t even know if this is a bug or not because the current keymap priority is so bizzarre to me.

In this example, the wm.call_menu operator will never get called because object.hide_collection is modified with “any”, which I guess also includes “no modifier at all”. So pressing “3” will hide collection, and the number 3 can’t be used for ANY other hotkey ever unless the user first unbinds this one. What is the point of this decision? If you wanted the hotkey to be 3 just make it 3 and let us bind Shift+3, Alt+3 etc to whatever we want. Seems kind of greedy to squat on a high priority left-hand key like that and not ever be able to overload it in the default keymap.

I can’t help but think that this wouldn’t be an issue if we had additive keymap loading. Addon developers could supply their own keymap config for their addon and blender would allow those keymaps to take priority over anything that was loaded previously. Users could go into preferences and filter to that addon’s keymap and make whatever changes they wanted to without damaging the base config. If the addon is ever unloaded, that particular keymap layer is ‘popped off’ and blender is back to normal pre-addon.

for addon devs like me who are not making a pie or panel based addon, it’s really discouraging to have to jump through all of these hoops. addon keymaps are clearly neglected and in desperate need of some redesign.

2 Likes

Sounds like a “resolve keymap conflicts” add-on would be a nice idea (you can already do that manually by filtering keymaps with the “Key-Binding” mode, but having a wizard / manager-like add-on for that would save time).

1 Like