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):
"""Operator which runs its self from a timer"""
bl_idname = "wm.modal_timer_operator"
bl_label = "Modal Timer Operator"
_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 < x < a.x + a.width
and a.y < y < a.y + a.height]
if areas and areas[0].type not in {'VIEW_3D', 'TEXT_EDITOR'}:
print("Right Click Taken Out")
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__ == "__main__":
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 < x < a.x + a.width
and a.y < y < a.y + a.height]
if areas:
return {
"area" : areas[0],
"space_data" : areas[0].spaces.active,
"region": 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'}