Start modal operator from a click in panel
Use the screen.
Edited Code from https://blender.stackexchange.com/a/101894/15543
Creates a modal timer operator which is invoked from the script. (Invoke is equiv of pressing button.)
While the modal timer below is running removes right click support from all areas that are not text editors nor 3d views.
Instead of using context.space_data find the space from its coordinates in the screens areas collection.
import bpy

class ModalTimerOperator(bpy.types.Operator):
    &quot;&quot;&quot;Operator which runs its self from a timer&quot;&quot;&quot;
    bl_idname = &quot;wm.modal_timer_operator&quot;
    bl_label = &quot;Modal Timer Operator&quot;

    _timer = None

    def modal(self, context, event):
        if event.type in {'RIGHTMOUSE'}:
            screen = context.screen
            x, y = event.mouse_x, event.mouse_y

            areas = [a for a in screen.areas if a.x &lt; x &lt; a.x + a.width
                    and a.y &lt; y &lt; a.y + a.height]
            
            if areas and areas[0].type not in {'VIEW_3D', 'TEXT_EDITOR'}:
                print(&quot;Right Click Taken Out&quot;)
                return {'RUNNING_MODAL'}

        if event.type in {'ESC'}:
            self.cancel(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            # change theme color, silly!
            pass
        return {'PASS_THROUGH'}

    def execute(self, context):
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.1, window=context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def cancel(self, context):
        wm = context.window_manager
        wm.event_timer_remove(self._timer)

def register():
    bpy.utils.register_class(ModalTimerOperator)

def unregister():
    bpy.utils.unregister_class(ModalTimerOperator)

if __name__ == &quot;__main__&quot;:
    register()
    # test call
    bpy.ops.wm.modal_timer_operator('INVOKE_DEFAULT')

The above is from modal timer template, will work same as a modal.
def execute(self, context):
    wm = context.window_manager
    #self._timer = wm.event_timer_add(0.1, window=context.window)
    #wm.modal_handler_add(self)
    wm.modal_handler_add(self)
    return {'RUNNING_MODAL'}

def cancel(self, context):
    wm = context.window_manager
    #wm.event_timer_remove(self._timer)

Override the context.
To run an operator with different context members, override the context. For example modify above to give the usual suspect override dictionary of area, space_data, and region
As an example, edit for above to clear the console if right clicked. Notice the override has passed the poll test of the bpy.ops.console.clear() operator.
def override(self, context, event):
    screen = context.screen
    x, y = event.mouse_x, event.mouse_y

    areas = [a for a in screen.areas if a.x &lt; x &lt; a.x + a.width
            and a.y &lt; y &lt; a.y + a.height]        
    if areas:                    
        return {
                &quot;area&quot; : areas[0],
                &quot;space_data&quot; : areas[0].spaces.active,
                &quot;region&quot;: areas[0].regions[-1],
                }
    return {}
            
def modal(self, context, event):
    if event.type in {'RIGHTMOUSE'}:
        override = self.override(context,  event)
        if bpy.ops.console.clear.poll(override):
            bpy.ops.console.clear(override)
            return {'RUNNING_MODAL'}