-
Notifications
You must be signed in to change notification settings - Fork 45
/
gstcefnsapplication.mm
94 lines (79 loc) · 2.95 KB
/
gstcefnsapplication.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// SPDX-FileCopyrightText: 2024 L. E. Segovia <[email protected]>
// SPDX-License-Ref: LGPL-2.1-or-later
#include "gstcefsrc.h"
#include "gstcefnsapplication.h"
#include <AppKit/AppKit.h>
#import <Appkit/AppKit.h>
#import <Cocoa/Cocoa.h>
#include <CoreFoundation/CFRunLoop.h>
#include <include/base/cef_lock.h>
#include <include/cef_app.h>
#include <include/cef_application_mac.h>
#include <objc/runtime.h>
#include <syslog.h>
#include <cinttypes>
#include <set>
namespace {
bool g_handling_send_event = false;
} // namespace
@interface NSApplication (GstCEFApplication) <CefAppProtocol>
- (void)runCefEventLoop;
- (BOOL)isHandlingSendEvent;
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent;
- (void)_swizzled_sendEvent:(NSEvent *)event;
@end
void gst_cef_loop() {
auto *app = [NSApplication sharedApplication];
[app performSelectorOnMainThread:@selector(runCefEventLoop)
withObject:app
waitUntilDone:NO];
}
CFRunLoopTimerRef gst_cef_domessagework(CFTimeInterval interval) {
// syslog(LOG_DEBUG, "Scheduling work... %f", interval);
return (CFRunLoopTimerRef)
[NSTimer timerWithTimeInterval:(NSTimeInterval)interval
target:[NSApplication sharedApplication]
selector:@selector(runCefEventLoop)
userInfo:NULL
repeats:YES];
}
@implementation NSApplication (GstCEFApplication)
- (void)runCefEventLoop {
CefDoMessageLoopWork();
}
// This selector is called very early during the application initialization.
+ (void)load {
if ([NSThread currentThread] != [NSThread mainThread]) {
syslog(LOG_ERR, "Swizzling from outside the main thread, relocating...");
[NSApplication performSelectorOnMainThread:@selector(load)
withObject:self
waitUntilDone:NO];
return;
}
syslog(LOG_NOTICE, "Swizzling NSApplication for use with CEF...");
auto swizzle = [&](auto src, auto dst) {
Method originalTerm = class_getInstanceMethod(self, src);
Method swizzledTerm = class_getInstanceMethod(self, dst);
assert(originalTerm != nullptr && swizzledTerm != nullptr);
method_exchangeImplementations(originalTerm, swizzledTerm);
};
swizzle(@selector(sendEvent:), @selector(_swizzled_sendEvent:));
syslog(LOG_NOTICE, "Swizzling complete.");
}
- (BOOL)isHandlingSendEvent {
// syslog(LOG_DEBUG, "Is handling [NSEvent sendEvent]: %i",
// g_handling_send_event);
return g_handling_send_event;
}
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
// syslog(LOG_DEBUG, "Set handling [NSEvent sendEvent]: %i",
// handlingSendEvent);
g_handling_send_event = handlingSendEvent;
}
- (void)_swizzled_sendEvent:(NSEvent *)event {
CefScopedSendingEvent sendingEventScoper;
// syslog(LOG_DEBUG, "[NSEvent sendEvent]: %p", event);
// Calls NSApplication::sendEvent due to the swizzling.
[self _swizzled_sendEvent:event];
}
@end