Adding Cut/Copy/Paste menu items on OSX

Hello,

I’m trying to implement cut/copy/paste on my OSX GLFW app, but it’s not being straightforward.
Most examples suggest adding entries to the app’s mainmenu.nib file, but GLFW apps don’t have this.
Instead the menus seem to be manually constructed.
Does anyone have an example of adding the usual edit cut/copy/paste menus and wiring them up to the keyboard shortcuts?
I’m quite surprised it doesn’t just work, which it seems to on Windows and Linux.

Thanks,

Confused

Hi @Tunbridge (as in ‘disgusted of’ I’m guessing), welcome to the GLFW forums!

I’m not quite sure what you’re trying to achieve here, as GLFW does not have functionality for adding menus. However you can create your own cut/copy/paste with the clipboard functions using glfwGetClipboardString and glfwSetClipboardString.

Cheers, Doug.

GLFW on Mac has a function createMenuBar() in cocoa_init.m which makes the app menu.
It’s got Minimize, Zoom, Hide, Quit and so on.
It’s also got an alarming comment about using nasty and undocumented things.
I’m not a Mac programmer so I’m not sure how (if?) to add copy & paste to these options.
I don’t want to manage the clipboard myself, unfortunately, because I could do that with those useful functions.
I just want the user to be able to paste some text into a WKWebview, without any involvement from my app, and as I say I’m quite surprised that the structure of macOS means that I have to wire up some menus to get a standard keyboard shortcut to work. I’m used to these things just working by default.

This sounds like the kind of problem lots of people must have run into, and I was hoping one of them might be able to help me!

I’ll have a look around and see if anything leaps out in the code.

Perplexed

The normal approach to using copy/cut/paste in a GLFW app is to implement this via the Key Callback and glfwSetClipboardString / glfwGetClipboardString.

After much trial and a little error, this did the job I actually wanted (shortcut keys) without needing to involve the menu. in cocoa_init.m I replaced the original:

 if ([event modifierFlags] & NSEventModifierFlagCommand)
     [[NSApp keyWindow] sendEvent:event];

with:

if ([event modifierFlags] & NSEventModifierFlagCommand)
{
    bool processed = false;
    NSString* lowerString = [[event charactersIgnoringModifiers] lowercaseString];
    unichar character = [lowerString characterAtIndex:0];
    switch(character)
    {
        case 'x': processed = [NSApp sendAction:@selector(cut:)       to:nil from:nil]; break;
        case 'c': processed = [NSApp sendAction:@selector(copy:)      to:nil from:nil]; break;
        case 'v': processed = [NSApp sendAction:@selector(paste:)     to:nil from:nil]; break;
        case 'z': processed = [NSApp sendAction:@selector(undo:)      to:nil from:nil]; break;
        case 'a': processed = [NSApp sendAction:@selector(selectAll:) to:nil from:nil]; break;
    }
    if (processed)
        return event;

     [[NSApp keyWindow] sendEvent:event];
}

I can now use all the keyboard combinations I wanted to in the WKWebview.

I didn’t want to use the glfw Clipboard functions because I really didn’t want to get involved with this exchange. It’s one Apple OS component talking to another Apple OS component and my application really couldn’t care less. Also the glfw functions would work on all OSes and this is a strictly Apple-only problem. The copy & paste already works fine on the other platforms without any intervention.

Ah. I thought you were trying to implement copy/paste within your own GFLW based application - for example copy/pasting text from a UI implemented using OpenGL/Vulkan in your GLFW window.

(Just replying to the original question for completeness)

We should really add an example that builds and uses a nib file and/or add how to the documentation.

Very briefly, you can create a menu in Xcode > File > New > File > MainMenu. Save the MainMenu.xib when you’re happy with it and compile it with ibtool --compile MainMenu.nib MainMenu.xib. Put MainMenu.nib in the Contents/Resources subdirectory of your application’s bundle. GLFW should pick it up at initialization and use it instead of calling createMenuBar.

Note that this will also disable GLFW setting the application name in the menu bar automatically.