I have a solution and it's actually very simple:
class OBJECT_OT_do_stuff(bpy.types.Operator):
bl_idname = "object.do_stuff"
bl_label = "Do Stuff"
origSel: None
@classmethod
def poll(cls, context):
return context.active_object is not None
def modal(self, context, event):
# Update selection
curSel = context.selected_objects[-1]
# On selecting new object
if curSel is not self.origSel:
print("selection was changed")
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
print("cancelled operation")
return {'CANCELLED'}
else:
return {'PASS_THROUGH'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
self.origSel = context.object
# Execute Modal Operation
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
I assigned an attribute that in the invoke function gets filled with the active object. Then the modal function keeps comparing the current selection to the previous one!
An important thing to note is that in order for that to work you need to call the function with the invoke argument :bpy.ops.object.do_stuff('INVOKE_DEFAULT')