How to add the "Services" menu to my custom contextual menus?

I like to let users make use of installed “Service” plugins within my app.

For instance, when I list files in a Listbox, the user shall be able to right-click on a row, and I’ll present the Contextual menu that includes the available file-related Services.

How do I do that? I searched around, but since the term “services” is so generic, I cannot find any docs on this so far on the Apple dev site.

I’d also make use of MBS functions but even there is nothing in there for this purpose yet, it seems.
(There’s only a demo for providing new services, and the link it includes to Apple’s docs is dead now.)

Hi Thomas,

is this link helpful?

Thanks, Thomas. I found this under “Using Services”: If you need to construct menus programmatically, you simply designate the NSMenu object that you want as your Services menu with the setServicesMenu: method of NSApplication.

And it seems I’ll have to also invoke registerServicesMenuSendTypes:returnTypes:

I’ll report back once I have a working solution

Okay, here’s what makes this difficult:

In order to make this work, the Listbox or some other object in the NSResponder chain needs to implement three additional methods for handling events send to it. Without them, the Services won’t appear in the menu.

Now, how to I best accomplish that?

Has someone done this before, i.e. fiddle with the responder chain or add handler to one of Xojo’s internal UIKit sub classes?

I guess the cleanest way would be to insert my own NSResponder to the chain. I just have no idea how to do that, yet.

Yes this is possible. You will have to use declares into the objective c runtime in order to associate the method handlers with Xojo shared methods. I posted a project that does this in iOS a few months ago and the declares will be exactly the same. Search for my improved iOS application project and it shows how to do this with application delegate methods.

Jason, you mean to use class_AddMethod, right? I’ve done that myself before as well (macoslib uses that to install delegates, for instance). The question is rather where I add these methods. After all, I don’t want to mess with Xojo’s own classes in a way that I may cause them to misbehave.

I’m currently adding them to the window. Not sure if that’s always safe, though.

I’ve inserted objc runtime created classes into the responder chain and didn’t have any problems. However I didn’t get a clear answer if this was safe. I don’t see why it wouldn’t be but there’s no guarantee Xojo won’t reset the chain.
https://forum.xojo.com/12534-safe-to-relink-nextresponder/0

Will, the discussed solutions in your thread suggest to add a new subview to the hierarchy. But if you do that, how do you ensure it becomes part of the responder chain? You’d not want to insert your view between Xojo’s views, because that could confuse Xojo as it may have certain expectations about the view hircharchy.

My own solution, which works now, does simply add the methods to the window’s class (in my case to RBNSWindow). That way, I do not mess with the views at all, and my code would only stop working if Xojo suddenly would implement these Services handlers themselves. But if they did that, they’re probably solve my problem anyway, so that won’t be so bad. And my code can handle this gracefully because class_AddMethod would then simply return false (because the class has already these methods implemented), so it would not break anything in that case, either.

Yeah, it went off topic. Those solutions didn’t work for me.

Is RBNSWindow the Xojo Window? I thought that was XOJWindow. Oh I see, that’s in RealStudio. Isn’t modifying those classes unsafe? I’ve experimented with that but left it as hacks. If it’s sanctioned then I can get some notifications I haven’t been able to. Anyways, glad you got it working. :slight_smile:

That’s what I tried explaining in the previous post above: You do not modify the window or its data at all. All you do is add a method to the class. That changes no data. Now, if Cocoa calls down the responder chain, and no higher level takes the call, then it ends up with the added methods in XOJWindow, which are my custom methods. Should Xojo ever add their own methods to XOJWindow, then my calls to add my own will simply be ignored and I get “false” returned from the class_AddMethod call for that. When this happens (which can only happen when Xojo creates a new version, so it can never happen just because you run your once-built app on a new system), you simply either use the new APIs Xojo has then probably added for us, or you find some other point in the responder chain where you can add these methods, e.g. in NSApplication or in the top view’s class of XOJWindow. Since these methods are only meant for support of the Services menu, there’s also no other reason for Xojo to accidentally add their own methods. If they add them, it’ll be to support Services.
Therefore, nothing can go wrong.

I was looking around at a point to implement it and thought that Applescript would be helpful to do it.
I did not find a proper way to do it from Xojo but may be some Applescript Gurus will succeed ?

No, you certainly cannot do this through AppleScript, as the Services API requires that you run code when the user opens the menu, and you cannot use Applescript for that.

Thanks Thomas. I’ll stop looking at this solution then…