Ok, now I got it.
I was missing two important things.
One is that you actually have to create a new keymap inside keyconfig addons, so instead of
km = wm.keyconfigs.active.keymaps["Window"]
It should be
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY')
Otherwise it will only work as long as the addon loads on the Blender startup.
The second important thing I was missing is that the keymap must have the name of an already existing keymap.
I was taking as a reference the built-in addons and I was under the impression that they were defining new keymap categories (like ‘3D View Generic’, for example), but nope, they are all already defined in bpy_extras\keyconfig_utils.py.
And after that you have to take into account the priorities between different keymaps too.
So the final, actually working snippet looks like this:
bl_info = {
'name': 'Shortcut Test',
'version': (1, 0, 0),
'blender': (2, 79, 0),
'category': 'Test'
}
import bpy
class OT_Shortcut_Test(bpy.types.Operator):
bl_idname = "wm.shortcut_test"
bl_label = "Shortcut Test"
def execute(self, context):
self.report({'INFO'}, 'SHORTCUT TEST')
return {'FINISHED'}
classes=[OT_Shortcut_Test]
addon_keymaps = []
def register():
for cls in classes:
bpy.utils.register_class(cls)
wm = bpy.context.window_manager
if wm.keyconfigs.addon:
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY')
kmi = km.keymap_items.new('wm.shortcut_test', 'SPACE', 'PRESS')
addon_keymaps.append((km, kmi))
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
wm = bpy.context.window_manager
kc = wm.keyconfigs.addon
if kc:
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
if __name__ == "__main__":
register()