Inconsistent GeDialog::Open position



  • Hi,
    After the weird mouse position and screen dimensions stuff (see appropriate topic), I once more got side tracked by inconsistent behaviour I simply cannot explain.

    Here is some simple code to demonstrate the problem. All you need extra is an icon file "Test.png".
    The purpose of this testing plugin is to open a dialog. As you may notice I am using -1 for x and y position to let the dialog open at the current mouse position ...

    // Main.cpp
    
    #include "c4d.h"
    
    #define TEST_COMMAND_PLUGIN_ID	1000001
    
    
    // ====================================
    // GeDialog
    // ====================================
    
    class MyDialog : public GeDialog
    {
    public:
    	virtual Bool CreateLayout(void);
    };
    
    Bool MyDialog::CreateLayout()
    {
    	Bool res = GeDialog::CreateLayout();
    
    	GroupBegin(0, BFH_SCALEFIT | BFV_SCALEFIT, 1, 0, ""_s, 0);
    
    	// .. TODO
    
    	GroupEnd();
    
    	return res;
    }
    
    // ====================================
    // CommandData
    // ====================================
    
    class MyCommand : public CommandData
    {
    	INSTANCEOF(MyCommand, CommandData)
    
    public:
    
    	virtual Bool Execute(BaseDocument* doc, GeDialog* parentManager);
    	virtual Bool RestoreLayout(void* secret);
    
    	MyDialog mDlg;
    };
    
    Bool MyCommand::Execute(BaseDocument* doc, GeDialog* parentManager)
    {
    	if (mDlg.IsOpen())
    	{
    		mDlg.Close();
    		return true;
    	}
    
    	BaseContainer bc;
    	if (GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT, bc))
    	{
    		const Int32 x = -1;
    		const Int32 y = -1;
    		const Int32 w = 50;
    		const Int32 h = 50;
    		mDlg.Open(DLG_TYPE::ASYNC_POPUPEDIT, TEST_COMMAND_PLUGIN_ID, x, y, w, h, 0);
    	}
    
    	return true;
    }
    
    Bool MyCommand::RestoreLayout(void* secret)
    {
    	const Int32 subid = ((RestoreLayoutSecret*)secret)->subid;
    	return mDlg.RestoreLayout(TEST_COMMAND_PLUGIN_ID, subid, secret);
    }
    
    // ====================================
    // Plugin Main 
    // ====================================
    
    Bool PluginStart(void)
    {
    	ApplicationOutput("Test"_s);
    
    	if (!RegisterCommandPlugin(TEST_COMMAND_PLUGIN_ID, "Test"_s, 0, AutoBitmap("Test.png"_s), "Test"_s, NewObjClear(MyCommand)))
    		ApplicationOutput("Test - failed registering CommandData");
    
    	return true;
    }
    void PluginEnd(void)
    {
    }
    Bool PluginMessage(Int32 id, void * data)
    {
    	switch (id) {
    	case C4DPL_INIT_SYS:
    		if (!g_resource.Init())
    			return false;
    		return true;
    	case C4DMSG_PRIORITY:
    		return true;
    	case C4DPL_BUILDMENU:
    		break;
    	case C4DPL_ENDACTIVITY:
    		return true;
    	}
    	return false;
    }
    

    I have assigned a shortcut ( CTRL-T ) to the plugin, allowing me to execute the CommandData which will open the GeDialog using the current mouse position.
    An additional press of the shortcut will close the GeDialog, etc ...

    The first time the dialog is opened it is positioned centered at the current mouse position. Then all subsequent opening of the dialog gets it positioned with the topleft corner at the mouse position.
    Happens in R20 and R21. Why this inconsistency?

    Demonstration:
    https://youtu.be/jxPZ-CSQcDo



  • Hi,

    have you tried populating your dialog with some gadgets? My suspicion would be that the dialog is somehow initialised ignoring its minimum width and height arguments (500 in your case) and positioned with a height and width of zero under your cursor and only after that 'snaps' to its minimum height and width. Since you store a reference to the dialog and just reopen the dialog on subsequent executions of your plugin, the height and width are initialised then and the placement therefor correct.

    That all is pure speculation though.

    Cheers,
    zipit



  • Hi @C4DS, thanks for reaching out us.

    I confirm that the behavior you've reported is a bug and, as anticipated by @zipit, it's due to the fact that when the dialog is opened for the second time, an object then exists and the code follows a different path resulting in a different position of the dialog compared to the mouse position.

    You can mitigate the issue by using effective pointer position

    	if (GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT, bc))
    	{
    		Int32 xpos = bc.GetInt32(BFM_INPUT_X);
    		Int32 ypos = bc.GetInt32(BFM_INPUT_Y);
    		
    		const Int32 w = 50;
    		const Int32 h = 50;
    		mDlg.Open(DLG_TYPE::ASYNC_POPUPEDIT, TEST_COMMAND_PLUGIN_ID, xpos, ypos + h, w, h, 0);
    	}
    

    Best,



  • @r_gigante
    Thanks for the reply Riccardo.

    I was afraid the answer would be to use specific coordinates to position the GeDialog.
    From this other topic it was kind of clear that the mouse position is rather an ambiguous piece of information in a multi monitor setup.

    Nevertheless, thank you for your answer. Yet another mystery cleared.



  • Extra info!

    While I had set this topic as solved, without an actual WORKING solution being provided, I simply wanted to point out for future reference that R16 - R19 has a slight different behaviour.
    As with R20 and R21 the first time the dialog is opened it gets positioned centered on the current mouse position. On all subsequent opening it gets positioned with its upper left corner at 0,0.

    Something got "fixed" between R19 and R20, but not "fixed enough".