mousedown and REALCocoaViewCallbacks?

HI,

I client is missing mouseDown event for my cocoa controls.
And I don’t see it myself, too.

Where is it?
REALCocoaViewCallbacks forwards the mouseDown event as far as I see in code.

Greetings
Christian

Any progress on this?

No. Today again I miss it.

<https://xojo.com/issue/46895>

reported.

I like to add that “EnableMenuItems” is also missing. If a control handles Focus correctly, it should get a EnableMenuItems event as well, but that’s missing, too.

subclassing is the way to go, see another thread from Christian.

what do I miss?

Xojo adds events like MouseUp or MouseEnter.
But they miss MouseDown for some unknown reason :frowning:

@Alfred Van Hoek Well, yes, I can subclass a plugin control and implement EnableMenuItems there - but that doesn’t help me to actually CALL that event at the right time. How shall the subclass know when it needs to invoke that event, please? The call is made from the Xojo framework, and it calls first the focused control(s), then the window, and finally the app’s Event. But how shall a subclass know when this happens? I’d need to have a hook into that framework function, and that doesn’t exists AFAIK.

There is a callback function too for this, right? In LexingControl it appropriately gets called when the editor gets the focus. Not sure what type of control we are talking about. In my view, but I might be wrong, enable menu items are focus dependent. You need to set the REALcontrolAcceptFocus flag, or implement the AcceptFocus callback. Then you get the functionality.

Yes, the focus handling works already. But that only takes care of calls to GotFocus (and LostFocus). But EnableMenuItems is not to be called when a control gets the focus but when the user clicks into a menu, doesn’t it?

It should when it gets the focus. Gotfocus follows.

EnableMenuItems should be called when the user clicks on the menu, so we can update it just in time.

Alfred, just test this yourself. I wrote a test in less than a minute. It usually (with Xojo controls like Listbox) behaves like I and Christian said: A focused control’s EnableMenuItems is called when the user clicked into the menu bar, not when it gets the focus.

So, the plugin would need to know when that happens, and it can’t, without the framework’s help.

Look, you need to actually register the { “EnableMenuItems” }, and if you want handle it further { “MenuItemAction(item as MenuItem) as Boolean” }. Implement the callback functions, provide these events, use debugging strings and see what happens. That’s all I can say for the moment.

The plugin knows: Download the Lexing plugin.

Well, I can add a EnableMenuItems to my control, but nobody will call it.

So what did you do?

I know I can make menu item subclasses and put them on the menu and handle it there.
But Xojo controls have a EnableMenuItems handler and I am not sure how to get one for mine.

Could someone from Xojo Inc. maybe comment?

PS: Reported on feedback my wish: <https://xojo.com/issue/46915>

I said earlier “You need to set the REALcontrolAcceptFocus flag, or implement the AcceptFocus callback. Then you get the functionality.” This means:
Don’t set the REALcontrolAcceptFocus, to implement callbacks,

If you set REALcontrolAcceptFocus then the Xojo framework attaches the default enable menuItems. If you don’t then you provide the events and the callbacks become available.

RBBoolean Lexing_AcceptFocus(REALcontrolInstance instance)
{
	XLOG2("Lexing_AcceptFocus", 0, 0);
#ifdef WIN32
	CScintillaView* editor = (CScintillaView *)LexGetView(instance);
//	editor->setGeneralProperty(SCI_SETFOCUS, 1, 0); 
#endif
	return true;
}

void Lexing_EnableMenuItems(REALcontrolInstance instance)
{
//	LOG("Lexing_EnableMenuItems");

    bool hasfocus = DirectAccess(instance, SCI_GETFOCUS, 0, 0);
	
	if (hasfocus) {
        
#if _USE_DEPRECATED_SDK_
		XWindow xwin = REALGetControlWindow((REALcontrolInstance)instance);
#else
        XRectControl xc = instance;
        XWindow xwin = xc.window();
#endif
		XMenuItem		windowmenubar;
		if (xwin)
			windowmenubar = xwin.menubar();
        
		if (windowmenubar) {
			XString editString = "EditMenu";
            
			for (int i = 0; i < windowmenubar.count(); i++) {
                
				XMenuItem theItem = windowmenubar.item(i);
				XString name = theItem.name();
                
				if (editString.compare(name, 1) == 0) {
                    
					// Found the Edit menu
					for (int j = 0; j < theItem.count(); j++) {
						
						// Go down the list and search 
						XMenuItem menu = theItem.item(j);
                        XString xname = menu.name();
                        XString compareS;
#ifdef WIN32
                        compareS = "EditCut";
                        if (compareS.compare(xname, 1) == 0)
                        {
                            if (!DirectAccess(instance, SCI_GETSELECTIONEMPTY, 0, 0))
                                menu.enable();
                        }
                        compareS.unlock();		

                        
                        compareS = "EditCopy";
                        if (compareS.compare(xname, 1) == 0)
                        {
                            if (!DirectAccess(instance, SCI_GETSELECTIONEMPTY, 0, 0))
                                menu.enable();
                        }
                        compareS.unlock();

                        compareS = "EditPaste";
                        if (compareS.compare(xname, 1) == 0)
                        {
                            if (DirectAccess(instance, SCI_CANPASTE, 0, 0))
                                menu.enable();
                        }
                        compareS.unlock();
#endif
                        // need this for COCOA because this is a private Xojo menuItem
                        compareS = "EditClear";
                        if (compareS.compare(xname, 1) == 0)
                        {
                            if (!DirectAccess(instance, SCI_GETSELECTIONEMPTY, 0, 0))
                                menu.enable();
                        }
                        compareS.unlock();		
#ifdef WIN32
                        compareS = "EditSelectAll";
                        if (compareS.compare(xname, 1) == 0)
                        {
                            menu.enable();
                        }
                        compareS.unlock();		
                        
                        compareS = "EditUndo";
                        if (compareS.compare(xname, 1) == 0)
                        {
                            if (DirectAccess(instance, SCI_CANUNDO, 0, 0)) {
                                menu.enable();
                            }
                        }
                        compareS.unlock();		
                        
                        compareS = "EditRedo";
                        if (compareS.compare(xname, 1) == 0)
                        {
                            if (DirectAccess(instance, SCI_CANREDO, 0, 0)) {
                                menu.enable();
                            }
                        }
                        compareS.unlock();
#endif
                        xname.unlock();
						menu.unlock();
					}
				}
				name.unlock();
			}
			editString.unlock();
			windowmenubar.unlock();		
		}		
	}

#ifdef WIN32	
	CScintillaDelegate* delegate = (CScintillaDelegate*) LexGetDelegate(instance);
	if (delegate) {
		delegate->EnableMenuItems();
	}
#else
	LexingViewDelegate *delegate = LexGetDelegate(instance);
	if (delegate) {
		[delegate EnableMenuItems];
	}	
#endif
}

RBBoolean Lexing_MenuItemAction(REALcontrolInstance instance, REALobject menuitem)
{
//	LOG("Lexing_MenuItemAction");

	XMenuItem mItem = menuitem;
	XString xname = mItem.name();
	XString compareS;
    
#ifdef WIN32
	compareS = "EditCut";
	if (compareS.compare(xname, 1) == 0)
	{
		DirectAccess(instance, SCI_CUT, 0, 0);
        compareS.unlock();
        xname.unlock();
        return true;
	}
	compareS.unlock();		

	compareS = "EditCopy";
	if (compareS.compare(xname, 1) == 0)
	{
		DirectAccess(instance, SCI_COPY, 0, 0);
        compareS.unlock();
        xname.unlock();
        return true;
	}
	compareS.unlock();		
	
	compareS = "EditPaste";
	if (compareS.compare(xname, 1) == 0)
	{
		DirectAccess(instance, SCI_PASTE, 0, 0);
        compareS.unlock();
        xname.unlock();
        return true;
	}
	compareS.unlock();		
#endif
    
	compareS = "EditClear";
	if (compareS.compare(xname, 1) == 0)
	{
		DirectAccess(instance, SCI_DELETEBACK, 0, 0);
        compareS.unlock();
        xname.unlock();
        return true;
	}
	compareS.unlock();		

#ifdef WIN32
	compareS = "EditSelectAll";
	if (compareS.compare(xname, 1) == 0)
	{
		DirectAccess(instance, SCI_SELECTALL, 0, 0);
        compareS.unlock();
        xname.unlock();
        return true;
	}
	compareS.unlock();		

	compareS = "EditUndo";
	if (compareS.compare(xname, 1) == 0)
	{
        DirectAccess(instance, SCI_UNDO, 0, 0);
        compareS.unlock();
        xname.unlock();
        return true;
	}
	compareS.unlock();		

	compareS = "EditRedo";
	if (compareS.compare(xname, 1) == 0)
	{
		DirectAccess(instance, SCI_REDO, 0, 0);
        compareS.unlock();
        xname.unlock();
        return true;
	}
	compareS.unlock();
#endif
	xname.unlock();
    
#ifdef WIN32
    CScintillaDelegate* delegate = (CScintillaDelegate*) LexGetDelegate(instance);
    if (delegate) {
        return delegate->MenuItemAction(menuitem);
    }

#else
	LexingViewDelegate *delegate = LexGetDelegate(instance);
	if (delegate) {
		return [delegate MenuItemAction:menuitem];
	}

#endif
	return false;
}

Just test these with debugging strings by implementing similar callbacks .

Thanks.
I forgot to look into the behavior structure.

Perhaps there’s a bit of misunderstanding going on here. REALCocoaViewCallbacks is a mechanism for plugins to call back into the Xojo framework from a plugin’s NSView-based control. The “HostedPluginExample” example in the plugins SDK demonstrates how this works (see also REAL_VIEW_MIXINS).

And with REALCocoaViewCallbacks I provide mouseDown to the framework. But I miss the framework providing me the MouseDown event for the user of my plugin class.

So should I add my own MouseDown/MouseUP or is that a bug?