[macOS] Extending/swizzling methods in SDLApplication

Hello,

My application uses Chromium Embedded Framework(CEF) which requires NSApplication to implement a protocol which involves overriding [NSApplication sendEvent] so that a scoped object is created on a call to sendEvent. (for example, java-cef/util_mac.mm at master · chromiumembedded/java-cef · GitHub ) Events sent to CEF need to be within the lifetime of the scoped object.

But because [SDLApplication sendEvent] also overrides [NSApplication sendEvent]: SDL/SDL_cocoaevents.m at e8e2c8175cfe269cdf94c0c47c70f27f3a033050 · libsdl-org/SDL · GitHub , I believe I need to extend SDLApplication(or swizzle the sendEvent method) instead, such that that the scoped object gets created whenever [SDLApplication sendEvent].

Is it possible to do this? It seems that SDLApplication is not included in any of the SDL2 include header files.

I’ve run into a similar issue in the past. The easy solution was to override the method I needed in a category. This does produce a compiler warning, but you can #pragma that away or disable that warning…

Unfortunately, this is also what java-CEF is doing, so im not sure how you would ensure that your override is the one that would be called. Unless your whole point was to call the java-CEF version. if that is the case, then this should just work without you needing to write any code, which I imagine is the whole reason java-CEF is using a category to do this rather than subclassing.

Thanks for the reply.

if that is the case, then this should just work without you needing to write any code, which I imagine is the whole reason java-CEF is using a category to do this rather than subclassing.

Yes, overriding NSApplication already works. The problem is that I want the scoped object to be created when SDLApplication processes the event(the call to Cocoa_DispatchEvent) because that’s when the event gets sent to CEF.

Right now, with the approach from the java-cef link above, the scoped object gets created when [NSApplication sendEvent] gets called after the call to Cocoa_DispatchEvent, but by then event is already sent to CEF.

Then simply implement your own category that overrides the sendEvent implementation for SDLApplication that looks like:

@interface SDLApplication (MyCategory)
- (void)sendEvent:(NSEvent *)theEvent;
@end

@implementation SDLApplication (MyCategory)
- (void)sendEvent:(NSEvent *)theEvent
{
    CefScopedSendingEvent sendingEventScoper;
    
    if (s_bShouldHandleEventsInSDLApplication) {
        Cocoa_DispatchEvent(theEvent);
    }

     [self _swizzled_sendEvent: theEvent];
}
@end

hmmm, I see that actually Cocoa_DispatchEvent is static, so its not something you can just add a declaration for to be able to call it.

I wonder if there is a function above sendEvent that you could override instead.

I managed to swizzle [SDLApplication sendEvent] using the approach described in ios - How to swizzle a method of a private class - Stack Overflow

Turns out this still doesn’t get SDL2 fully working with CEF, because of the issue I described in this CEF forum post: CEF Forum • [macOS w/ SDL2] Assertion failure sending mouse click events . If anyone has experience using SDL with CEF, I’d appreciate some input.