Can the WorkSpaceTool be used to start a modal Operator which responds to mouse events?

I came across the script for WorkSpaceTool in the Python Templates and thought it would be a good starting point for developing a tool. My end goal is to have a tool which when selected will allow the user to click and drag with the mouse to create a cube. Unforunately, I am finding that WorkSpaceTool just creates a new instance of my operator for every mouse event and then calls the invoke() method - even for mouse move events and event if my operator is returning RUNNING_MODAL. modal() never gets called. No error messages are printed to the console.

I can find no information about how WorkSpaceTool is supposed to be used. Is it possible to use this to start a modal operator running which then interactively handle mouse input?

import bpy



class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    def __init__(self):
        print("construct SimpleOperator")

    def __del__(self):
        print("destruct SimpleOperator")

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def modal(self, context, event):
        print("modal evTyp:%s evVal:%s" % (str(event.type), str(event.value)))

        if event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
            # allow navigation
            return {'PASS_THROUGH'}
        
        elif event.type == 'MOUSEMOVE':
            
            return {'RUNNING_MODAL'}

        elif event.type == 'LEFTMOUSE':
            mouse_pos = (event.mouse_region_x, event.mouse_region_y)
            print("  pos %s" % str(mouse_pos))
            
            return {'RUNNING_MODAL'}

        elif event.type == 'RIGHTMOUSE':
            mouse_pos = (event.mouse_region_x, event.mouse_region_y)
            print("  pos %s" % str(mouse_pos))
            
            return {'FINISHED'}

    def execute(self, context):
        print("execute SimpleOperator")
        return {'FINISHED'}

    def invoke(self, context, event):
        print("invoke evTyp:%s evVal:%s" % (str(event.type), str(event.value)))
        
        
        return {'RUNNING_MODAL'}


#-------------------------------------


class MyTool(bpy.types.WorkSpaceTool):
    bl_space_type = 'VIEW_3D'
    bl_context_mode = 'OBJECT'

    # The prefix of the idname should be your add-on name.
    bl_idname = "my_template.my_circle_select"
    bl_label = "My Circle Select"
    bl_description = (
        "This is a tooltip\n"
        "with multiple lines"
    )
    bl_icon = "ops.generic.select_circle"
    bl_widget = None
    bl_keymap = (
        ("object.simple_operator", {"type": 'LEFTMOUSE', "value": 'PRESS'},
         {"properties": []}),
    )

    def draw_settings(context, layout, tool):
        props = tool.operator_properties("view3d.select_circle")
        layout.prop(props, "mode")
        layout.prop(props, "radius")

#---------------------------


def register():
    bpy.utils.register_class(SimpleOperator)
    bpy.utils.register_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True)
    

def unregister():
    bpy.utils.unregister_class(SimpleOperator)
    bpy.utils.unregister_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True)

if __name__ == "__main__":
    register()

Hi man,
Yes you can ,
This is the Tool part of my custom tool it calls a modal operator (" view3d.qsurf_mainmodal" )

class QSurfacerTool(WorkSpaceTool):  
    bl_space_type = 'VIEW_3D'
    bl_context_mode = 'OBJECT'
    bl_idname = "qs_addon.qsurfacer_tool"
    bl_label = "Q Surfacer "
    bl_description = (" create Q surfaces ")
    bl_icon =  "ops.gpencil.draw.poly"
    bl_widget = None
    bl_keymap = (
        ("view3d.qsurf_mainmodal", {"type": 'LEFTMOUSE', "value": 'PRESS'},
         {"properties": [("wait_for_input", False)]}),
        ("view3d.qsurf_mainmodal", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
         {"properties": [("mode", 'SUB'), ("wait_for_input", False)]}),
    )
     

you may also take a look at the script i posted here

Since between tool and modal there are some blind spots !
Look in the code for the comment “” THIS WILL NOT BE CALLED “”
Since that part of the operator will never run, because the first click is absorbed by the tool.

Hope this help you XD