Stop modal operator by calling another one

Hey guys.

I have two modal operators (let it be OP1 and OP2), each one assigned to the hotkey. I want to achieve behavior when each one stops if other one has been called.
So, for e.g. when the OP1 was running and OP2 called - the OP1 should stop and the OP2 should start. And vice versa.
It would be very convenient to switch really quickly between them, without ESC or RIGHTMOUSE.

I have released it in the next way: OP1 in a modal mode can catch the event of pressing OP2 hotkey. Then OP1 return {'CANCELLED'} and run the OP2 in its __del__ function.

The problem is that user can change the hotkeys and this trick will not work. I have tried to get the actual operator’s hotkey inside the script, but I got only the old one that had stored by register function.

Can I do better to achieve such behavior? Or how I can get access to addon hotkeys that may have been changed by user?

the user can’t change keys that you are monitoring inside your modal though, unless you have written code specifically to allow them to do this (in which case you also have access to whatever they changed the key to and can just write your code accordingly)

total off the top of my head untested pseudo-ish code:

should_cancel_b = False

# ... later, in operator A
def modal(self, context, event):
    global should_cancel_b

    if event.type=='A' and event.value=='PRESS':
        should_cancel_b = True
    return {'PASS_THROUGH'}

# ... later, in operator B
def modal(self, context, event):
    if should_cancel_b:
        should_cancel_b = False
        return {'CANCELLED'}
    return {'PASS_THROUGH'}

Thanks, a lot!
I have already done it in the exactly same way that you described, with global variable.

I mean that user can change the operator hotkey in the Preferences → Keymap.
For e.g. from ‘A’, Press to ‘B’, Press. And therefore I will not catch this event anymore.
So the hotkey in if statement should always match with actual assigned.

But when I’m getting operators hotkey form bpy.context.window_manager.keyconfigs.addon - It returns the hotkey not a one that user reasign, but the one that was in register function.

the only way to find a hotkey that a user may have changed is by manually searching for it:

for kmi in wm.keyconfigs.user.keymaps['Mesh']:
    if kmi.idname == 'mesh.my_operator':
        print(f"Found my operator, the hotkey is {kmi.type}")
        break
else:
    print("Didn't find my operator, it must still be on the default binding")

Thank you so much!
The keyconfigs.user is what I am looking for.

I have modified code a bit:

import bpy

wm = bpy.context.window_manager
kmi = wm.keyconfigs.user.keymaps['3D View'].keymap_items.get('my_operator')

print (kmi.type, kmi.value)

Or more general approach:

import bpy

wm = bpy.context.window_manager
for km in wm.keyconfigs.user.keymaps:
    kmi = km.keymap_items.get('my_operator')
    if kmi:
        print(kmi.type, kmi.value)
        break

One more off-topic question :slight_smile:

Is there essential difference in my case to use global variables like global should_cancel_b or blender properties instead?

accessing another operator’s blender properties while it’s running is not particularly straightforward- i would honestly opt for using a global

I got it, thanks!