I need a way to send keystrokes to a particular third party application on both Windows and Mac (the same third party app on both platforms).
I don’t know if an app can specifically be targeted for keystrokes or if I would need to somehow programatically bring it to the foreground, ensure it has focus, and then send the keystrokes.
Does anyone know if there is an existing accepted way to this in Xojo already, or is it declare digging time?
Thanks, @Christian_Schmitz, is there a Mac equivalent for WinBringWindowToTop? Playing around with RemoteControlMBS and MacProcessVisible = True makes the application window visible but does not give it the focus.
If anyone else needs a Mac version of AppActivate, here’s a quick and dirty method (requires MBS):
Public Function MacAppActivate(bundleID as String) As Boolean
#If TargetMacOS Then
var n() as NSRunningApplicationMBS = NSRunningApplicationMBS.runningApplicationsWithBundleIdentifier(bundleID)
if n.count = 0 then
//App is not running
Return false
end if
var u as integer, b as boolean = n(0).activateWithOptions(u)
Return b
#EndIf
End Function
Sending keys on Mac via RemoteControlMBS.MacPressKey worked the first time I ran the app in the IDE (when I was prompted to toggle the switch in Accessibility), but fails on each subsequent debug compile. I think perhaps because it no longer has system permissions to send keys, despite the switch still being toggled on in the Privacy & Security preference pane.
I don’t know if this is any help to you, but I use third-party apps because of problems like this. Under Windows AutoHotkey and on the Mac Keyboard Maestro.
Ahhh, that’s too bad. Won’t be able to swing that for my app, but I appreciate the suggestion. It looks like it’d be a great solution for apps that don’t need wide distribution.
There is definitely something funky going on. The RemoteControlMBS.MacPressKey methods have just stopped working, even in the MBS Example Project “Write Something” where it was certainly working just an hour ago with no code changes. If anyone has any insight into what might have changed between runs, I’d appreciate it.
Edit: Okay so it seems that EVERY TIME YOU DEBUG YOUR APP, you have to open System Settings … Privacy & Security… Accessibility, and remove the old entry for your app’s permission. Then you have to let your app re-try its key sending operation, fail, allow the permission for the new instance of your app in Accessibility, and then try again.
This is a huge waste of time. I’m often running dozens of debugs an hour. Does anyone know a way to circumvent this?
I’ve been wrestling with this for days and I haven’t found a good workaround yet that doesn’t involve some serious screwing around with crazy AppleScripts, etc. This is a huge blind spot on Apple’s part for developers… I appreciate that they are focused on security but there ought to be a way to temporarily disable all the checks.
@Eric_Williams Here’s a little something I put together after spending too much time on this issue, lol. Call this method when your app loads and it will remove the old permissions. You will still be prompted to allow it the next time you use accessibility features, but at least it saves you from having to remove it each time.
Public Sub ResetAccessibility()
#If DebugBuild And TargetMacOS Then
Declare Function mainBundle Lib "AppKit" selector "mainBundle"(NSBundleClass As Ptr) As Ptr
Declare Function NSClassFromString Lib "AppKit"(className As CFStringRef) As Ptr
Declare Function getValue Lib "AppKit" selector "bundleIdentifier"(NSBundleRef As Ptr) As CFStringRef
var bundleID As String = getValue(mainBundle(NSClassFromString("NSBundle")))
var s as new Shell
s.Execute("tccutil reset All " + bundleID)
#EndIf
End Sub