Hi.
I am building a macOS Cocoa application with RemObjects Elements Mercury
(Toffee target). I am trying to register a Carbon global hot key using
RegisterEventHotKey and receive kEventHotKeyPressed through
InstallEventHandler.
Both calls return noErr, and the hot-key registration remains alive. However,
pressing Option+Command+Z never enters the event handler: even the first
NSLog in the callback is not printed.
This is the relevant Mercury code:
Imports Carbon.HIToolbox
Imports Foundation
Imports RemObjects.Elements.System
Public Function handleMacGlobalHotKeyEvent(
nextHandler As EventHandlerCallRef,
eventReference As EventRef,
context As Ptr(Of Void)) As OSStatus
NSLog("Carbon hot-key callback entered")
MacGlobalHotKey.dispatchHotKeyEvent()
Return noErr
End Function
Private _eventHandler As EventHandlerRef
Private _eventHandlerCallback As EventHandlerUPP
Private _hotKey As EventHotKeyRef
Public Function registerHotKey() As Boolean
Dim eventType As EventTypeSpec
eventType.eventClass = kEventClassKeyboard
eventType.eventKind = kEventHotKeyPressed
Dim eventTarget As EventTargetRef = GetApplicationEventTarget()
_eventHandlerCallback = AddressOf Global.MacApp.handleMacGlobalHotKeyEvent
Dim installStatus As OSStatus = InstallEventHandler(
eventTarget,
_eventHandlerCallback,
1,
AddressOf eventType,
Null,
AddressOf _eventHandler)
NSLog("InstallEventHandler status %d", installStatus)
Dim identifier As EventHotKeyID
identifier.signature = &H5A4D524B
identifier.id = 1
Dim registerStatus As OSStatus = RegisterEventHotKey(
6, ' Z
optionKey Or cmdKey,
identifier,
eventTarget,
0,
AddressOf _hotKey)
NSLog("RegisterEventHotKey status %d", registerStatus)
Return installStatus = noErr AndAlso registerStatus = noErr
End Function
The native Carbon declaration is:
typedef OSStatus (*EventHandlerProcPtr)(
EventHandlerCallRef, EventRef, void *);
typedef EventHandlerProcPtr EventHandlerUPP;
On modern macOS, NewEventHandlerUPP(proc) is only a cast macro and
DisposeEventHandlerUPP is a no-op. Therefore I expected assigning
AddressOf directly to the imported EventHandlerUPP type to be equivalent
to the C usage.
Could someone confirm the correct Mercury/Toffee pattern for this API?
Specifically:
- Is
EventHandlerUPPimported as a raw C function-pointer type? - Does
AddressOffor a Mercury top-level function produce an ABI-compatible,
stable C callback pointer forInstallEventHandler? - If not, should I declare a
<FunctionPointer>delegate explicitly, use a
different attribute/calling convention, or add a custom bridge? - Is there a recommended way to inspect the generated Objective-C/C output
for this conversion?
I keep both the returned EventHandlerRef and the callback value alive until
I call RemoveEventHandler, so this should not be a lifetime issue.
Environment:
- Elements version: Fire(with Elements:13.0.0.3095)
- macOS version / CPU architecture: 26.0+
Thank you.
Update: After further investigation, it may not be an issue with
FunctionPointeritself, and we currently believe the likelihood is relatively low. More precisely, the immediate problem I encountered is that Carbon events are not being received, so the keyboard callback is never triggered.