Tracktion / choc

A collection of header only classes, permissively licensed, to provide basic useful tasks with the bare-minimum of dependencies.
Other
543 stars 49 forks source link

Close Desktop with CMD+Q on Mac? #49

Closed lucenta closed 8 months ago

lucenta commented 8 months ago

Is there anyway to close a DesktopWindow with CMD+Q on mac? This is pretty standard for most applications. Is there anyway to attach key stroke listeners?

julianstorer commented 8 months ago

The way cmd-Q works on mac is all about NSApplication level functionality. It's not something that belongs in a window class.

I'm trying to avoid getting dragged into the slippery slope of writing an app framework! If you're doing a mac app and need this kind of mac-specific stuff, you'll need to use the standard mac classes to handle it!

Key stroke listeners in general could be something to add to this, but these also have a lot of gotchas, and it's not on my immediate to-do-list.

lucenta commented 8 months ago

Thank you!

lucenta commented 8 months ago

Just following up here; when I try to link against Cocoa or foundation to NSApplication level functionality, i get
*** NSForwarding: warning: object 0x600000d689c0 of class 'CHOCDesktopWindowDelegate_3400222098' does not implement methodSignatureForSelector: -- trouble ahead

julianstorer commented 8 months ago

That's strange - I link all the same thing and haven't seen that. Will investigate..

julianstorer commented 8 months ago

I can't reproduce this or see why it'd happen, since that class does inherit from the correct base class.. If you can share some code that reproduces it, I could take a look.

lucenta commented 8 months ago

Certainly, here's what I have

KeyListenerInterface.h void callFromCpp();

KeyInterfaceMac.mm

/ KeyListenerInterface.h
#import <Foundation/Foundation.h>

@interface KeyListenerInterface : NSObject

- (void)myMethod;

@end

@implementation KeyListenerInterface

- (void)myMethod {
    NSLog(@"Inside myMethod");
}

@end

void callFromCpp() {
    KeyListenerInterface *myInstance = [[KeyListenerInterface alloc] init];
    [myInstance myMethod];
}

I'm using meson to build,


if is_macos
    env = environment()
    env.set('MACOSX_DEPLOYMENT_TARGET', '10.15')

    add_languages('objcpp')
    add_project_arguments(['-mmacosx-version-min=10.15', '-arch', 'arm64', '-arch', 'x86_64'], language: 'cpp')
    add_project_link_arguments(['-mmacosx-version-min=10.15', '-arch', 'arm64', '-arch', 'x86_64'], language: 'cpp')

    add_project_arguments(['-mmacosx-version-min=10.15', '-arch', 'arm64', '-arch', 'x86_64'], language: 'objcpp')
    add_project_link_arguments(['-mmacosx-version-min=10.15', '-arch', 'arm64', '-arch', 'x86_64'], language: 'objcpp')

    extra_deps = dependency('appleframeworks', modules: ['WebKit', 'Cocoa'])
else
    add_project_arguments(['/MT', '-D_CRT_SECURE_NO_WARNINGS', '-D_CRT_NONSTDC_NO_DEPRECATE'], language: 'cpp')
endif

...

app_src = [
    'src/main.cpp',
    'src/KeyListenerMac.mm',
]

...

app = executable(
    app_name,
    format_first,
    app_src,
    include_directories: app_inc,
    dependencies: [package_manager_dep, extra_deps],
    cpp_args: app_cpp_args,
    objects: app_objects,
    gui_app: true
)

When i compile my app, i get the said error. It's interesting too because if I remove the NS log in the .mm file, i get a different error CHOCDesktopWindowDelegate_748915896 initialize]: unrecognized selector sent to instance 0x6000019f4270 (no message forward handler is installed)

I'm not using any of the code I wrote, (i.e the callFromCpp() function) as the error im getting is just trying to compile the app.

That being said, even if I just add the Cocoa framework in the meson file (and no other additional files), we get the crash no message forward handler is installed . Hope this helps to provide more context.

lucenta commented 8 months ago

Ok I found a very simply way to add this functionality into the framework itself.

In choc_WebView.h I've added the following line (552) at the end of the if statement, and this works. I tried to make a PR but dont have permissions, so please let me know if this can be added!

if (flags == NSEventModifierFlagCommand)
  {
      if (path == "c") return sendAppAction (self, "copy:");
      if (path == "x") return sendAppAction (self, "cut:");
      if (path == "v") return sendAppAction (self, "paste:");
      if (path == "z") return sendAppAction (self, "undo:");
      if (path == "a") return sendAppAction (self, "selectAll:");
      if (path == "q") return sendAppAction (self, "terminate:");
  }
julianstorer commented 8 months ago

Sorry, but that really doesn't belong in there. If you were writing an app, then maybe you'd do that, but this is a library, I can't add specific functionality like that to a library class.

lucenta commented 8 months ago

@julianstorer No problem, thanks for the help!