UI blocked until a mouse event when invoking modal operator from another operator When I invoke my modal operator from my other operator (invoked from a panel button) and the modal operator finishes, Blender's UI is blocked until the mouse moves (i.e. click on the same button has no effect unless the mouse is moved or clicked first).

Also, if the modal operator is invoked from a property update function then the UI is blocked until LMB click (moving or clicking other buttons has no effect).

However, occasionally blocking does not happen.

When looking at events in modal(), event.type/event.value for the first two events are:  


UI blocked - MOUSMOVE/RELEASE, MOUSMOVE/RELEASE  
UI not blocked - MOUSMOVE/RELEASE, NONE/NOTHING


An obvious question is why are there two MOUSMOVE/RELEASE events anyway ...

I am wondering why is this happening and even more is there a way to avoid this UI blocking?

(The reason I'm doing all this is in my other question.)

Example code:

import bpy
from bpy.types import Operator

class TheModalOperator(Operator):
    bl_idname = "my.themodaloperator"
    bl_label = "TheModalOperator Operator"

    # counter of calls to modal()
    countmodal = 0

    def __del__(self):
        print("TheModalOperator End")

    def invoke(self, context, event):
        print("TheModalOperator invoke")
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def modal(self, context, event):
        self.countmodal += 1
        print("TheModalOperator modal", self.countmodal, event.type, event.value)
        if self.countmodal &gt;= 2:
            print("---TheModalOperator modal finished")
            return {'FINISHED'}
        else:
            print("---TheModalOperator modal running")
            return {'RUNNING_MODAL'}       


class MyOperator(Operator):
    """This is my operator"""
    bl_idname = "my.operator"
    bl_label = "My Operator"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        print("MyOperator execute")
        self.report({'INFO'}, "MyOperator executed")
        bpy.ops.my.themodaloperator('INVOKE_DEFAULT')
        return {'FINISHED'}


# button on the toolshelf
class MyTestPanel(bpy.types.Panel):
    bl_idname = "mytestpanel"
    bl_category = "My Stuff"
    bl_label = "My Test Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        col = layout.column(align=True)
        col.label(text="This blocks UI until a mouse event:")
        col.operator("my.operator", text="Run my operator")

def register(): 
    bpy.utils.register_module(__name__)

def unregister(): 
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()
There are two fixes needed.

1. The modal() must return PASS_THROUGH instead of RUNNING_MODAL.
That allows Blender to process mouse events, however, fixes the problem only when invoked from property update function.

2. Using a timer instead of the counter.
I'm not clear why not just changing the counter limit to 3 does not work (that just requires another mouse event, i.e. need to move or click the mouse).
Nevertheless, the modal timer does fix the problem for invoking from other operator too.

Fixed code:

import bpy
from bpy.types import Operator

class TheModalOperator(Operator):
    bl_idname = "my.themodaloperator"
    bl_label = "TheModalOperator Operator"

    timer = None

    def invoke(self, context, event):
        print("TheModalOperator invoke")
        self.timer = context.window_manager.event_timer_add(0.1, context.window)
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def modal(self, context, event):
        print("TheModalOperator modal", event.type, event.value)
        if event.type == 'TIMER':
            print("---TheModalOperator modal finished")
            context.window_manager.event_timer_remove(self.timer)
            return {'FINISHED'}
        else:
            print("---TheModalOperator modal pass-through")
            return {'PASS_THROUGH'}       


class MyOperator(Operator):
    """This is my operator"""
    bl_idname = "my.operator"
    bl_label = "My Operator"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        print("MyOperator execute")
        self.report({'INFO'}, "MyOperator executed")
        bpy.ops.my.themodaloperator('INVOKE_DEFAULT')
        return {'FINISHED'}


# button on the toolshelf
class MyTestPanel(bpy.types.Panel):
    bl_idname = "mytestpanel"
    bl_category = "My Stuff"
    bl_label = "My Test Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        col = layout.column(align=True)
        col.label(text="This blocks UI until a mouse event:")
        col.operator("my.operator", text="Run my operator")

def register(): 
    bpy.utils.register_module(__name__)

def unregister(): 
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()