I'm writing a python app, whose main purpose is to run a minigame (using the 'pygame' library), whenever I use a hotkey (which currently uses the 'keyboard' library). I want this hotkey to be recognized universally, so I'm packaging the whole thing as a status bar app (using the 'rumps' library).
So far, I can start the whole thing, select Play from the status bar dropdown, and it works! Great.
HOWEVER, if I attempt to use the bound hotkey, to run the same function that Play triggers, I get:
python[58226:599749] pid(58226)/euid(0) is calling TIS/TSM in non-main thread
environment, ERROR : This is NOT allowed. Please call TIS/TSM in main thread!!!
This shows up four times, and is followed up
python[58226:599749] WARNING: nextEventMatchingMask should only be
called from the Main Thread! This will throw an exception in the future.
To check that it wasn't the hotkey itself, I did a test: If I connect the hotkey to a simpler function, like setting an alert, it works fine. It still complains, and gives me the error:
python[60308:620099] -[NSAlert runModal] may only be invoked from the main thread. Behavior on other threads is undefined. (
0 AppKit 0x00007fff2b7f563f -[NSAlert runModal] + 178
1 _objc.cpython-36m-darwin.so 0x000000010c1358c7 ffi_call_unix64 + 79
2 ??? 0x000070000f3b2e50 0x0 + 123145557847632
)
but it does RUN. However if it connects to the Play function, it breaks (and produces the first error, above).
To summarize:
1) Dropdown => run minigame: Success!
2) Hotkey => run minigame: Incomprehensible errors!
I've googled this error, but have only seen explanations that are way over my head; is there a way that I could get around this error, by using different software, or a different approach -- but without having to leave python, or performing some deep and evil hack to an underlying system?
Could I get the hotkey/game to USE the Main Thread environment, somehow? How?
Could I use a vehicle other than a status bar app to listen for the hotkey? (Update: I tried pynput, and got the same non-main thread error.)
Could I do something inside of pygame to not make it as offensive? (At the moment, it's literally just animating a rolling sine wave.)
Could I get the rumps callback function to work? At the moment, it's just not doing ANYTHING, no matter where or how it's called.
(And unfortunately, this on a Mac, because pyhk3 is for windows only, and wx.Window (which can have hotkeys) is also for windows only)
FURTHER failure: Can't get it to run with Keyboard Maestro either -- I've never used it before, so may well be using it wrong, but it also seems like a VERY simple command, that just flat-out has no response whatsoever.
Aaand ... the Automator script runs, but -- not with the hotkey! (EDIT: The hotkey was apparently taken. But a different one worked! See below.)
I'm accepting my own answer because it is the only one so far that solves the problem I was most interested in, i.e. getting the thing to run with a global shortcut, BUT, since I would ideally like to package and distribute this, I would still be very glad to see answers that solved the problem within python, and would gladly award the bounty to any answer that did that.
Finally, finally, made it work with a Service in Automator, and System Preferences > Keyboard > Shortcuts. Along the way, I had to