# Add-On Dev: Popup Panel Position

Is there any way to control the starting position of a popup panel / window?

I'm not familiar with the number of floating panel types in Blender, but I'm creating mine with an operator class, using bpy.context.window_manager.invoke_props_dialog(self,width=600) in invoke().

The default starting popup location seems to be related to the mouse cursor or activator button location. The problem occurs when the button to open the popup is near the bottom of the screen. The popup opens into the bottom right corner. I don't need to specify the exact location. But if possible, I would like to have it open somewhere near the vertical center of my standard side panel.

• You can set the cursor position using bpy.context.window.cursor_warp(x, y). Sep 30 '19 at 13:50
• Would that work? I would be hesitant to move the user's cursor just to set the window position, but it may work to move it temporarily, then move it back. I will give it a try and see if it works. Thanks! Sep 30 '19 at 21:19
• That is a downside, because it's unexpected for the user. Sep 30 '19 at 21:51
• My code is in a mess at the moment, so I can't easily test it. But my hope is that it won't be detectable by the user if I only move the cursor for the single frame. Move the cursor, possibly update something, spawn the window, move it back. It's a bit hacky, but if it works well enough, I could provide an option to "center pop ups". Sep 30 '19 at 22:13

Hello from the future,

If we have us some properties on our operator, like so:

from bpy.types import Operator;
from bpy.props import IntProperty;

bl_label = "Pop!";
bl_description = "Spawns a pop-up";

# using annotations for 2.8+
# change to equal signs on previous versions
first_mouse_x : IntProperty(default = 0);
first_mouse_y : IntProperty(default = 0);

target_mouse_x : IntProperty(default = 0);
target_mouse_y : IntProperty(default = 0);

mouse_snap : BoolProperty(default = False);


Then we can save the original position of the mouse during invoke.

    def invoke(self, context, event):

# assign position of the cursor at the time the operator is called
self.first_mouse_x = event.mouse_x;
self.first_mouse_y = event.mouse_y;

# probably redundant but i can't recall if props actually reset to default
self.mouse_snap = False;

# now warp the mouse to some xy coords
# here i center on the window and adjust y to approx. the height of my popup
context.window.cursor_warp(context.window.width/2, (context.window.height/2) + 60);

# now invoke
wm = context.window_manager;
return wm.invoke_props_dialog(self, width = 600);


Next thing on the list is resetting the cursor to the original coordinates. I do this on the first run of draw and haven't really noticed any jumpy motion on the cursor.

    def draw(self, context):

if not self.mouse_snap:
self.mouse_snap = True;
context.window.cursor_warp(self.first_mouse_x, self.first_mouse_y);


That gets you back where you started.

But wait, there's more! As a bonus, you can also pass the xy coords to the operator from your panel's draw.

    def draw(self, context):

layout = self.layout;
row = layout.row();

# this gets you a handle to the operator properties

• A couple of things from the present :)_ Operator properties are now (2.8+) defined using annotations eg prop_name : bpy.props.IntProperty ... and in as much as aligning with equals sign is "pretty" its not PEP8 compliant. Jan 29 at 7:02