NSEvent global event monitoring in background - python

I am writing a simple Mac application designed to run in the background and perform certain actions whenever the user clicks the mouse button. The app is written in Python using PyObjC. I am using addGlobalMonitorForEventsMatchingMask to watch for NSLeftMouseDown events:
NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSLeftMouseDownMask, handler)
This code works perfectly when running in the terminal. However, when I bundle it as a standalone app (using py2app) and then launch it, the app doesn't receive any events at first. (Or at least, if it does, it doesn't run the code in my handler method.) Only when I click on the app in the Dock does it start receiving events, and after that, it continues to receive events even after it returns to the background. But it doesn't receive anything until activated once.
My question is: How can I get my app to start receiving events as soon as it is launched, without having to be activated first by clicking the Dock icon? Is this some known quirk of NSEvents, or is there perhaps something wrong with my run loop in PyObjC?
Any help or guidance is greatly appreciated!
Edit: Upon further testing, it seems that, in fact, my app spontaneously starts receiving notifications about ten seconds after launch, regardless of whether I activate it. Which is slightly annoying, but fine.
However, if I run the app with either LSUIElement = true or LSBackgroundOnly = true in my Info.plist (which I ultimately want to do, since this app should only run in the background and never appear in the Dock), I never receive notifications. So I am still stuck.

As you said "Only when I click on the app in the Dock does it start receiving events" , that means the handler gets registered after you click on the app in the Dock.
So it depends on at which point in the code you are calling this : NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSLeftMouseDownMask, handler) ,
that is registering the handler.
You should register the handler in appdidfinishlaunching function.

Related

How to catch the stop button in PyCharm on Windows?

I want to create a program that does something in which someone terminates the script by clicking the stop button in PyCharm. I tried
from sys import exit
def handler(signal_received, frame):
# Handle any cleanup here
print('SIGINT or CTRL-C detected. Exiting gracefully')
exit(0)
if __name__ == '__main__':
signal(SIGINT, handler)
print('Running. Press CTRL-C to exit.')
while True:
# Do nothing and hog CPU forever until SIGINT received.
pass
from https://www.devdungeon.com/content/python-catch-sigint-ctrl-c.
I tried on both Mac and Windows. On the Mac, PyCharm behaved as expected, when I click the stop button it catches the SIGINT. But on Windows, I did exactly the same thing, but it just straightly returns to me a
Process finished with exit code -1. Is there something I can do to change to make the Windows behave like what on Mac?
Any help is appreciated!
I don't think it's a strange question at all. On unix systems, pycham sends a SIGTERM, waits one second, then send a SIGKILL. On windows, it does something else to end the process, something that seems untrappable. Even during development you need a way to cleanly shut down a process that uses native resources. In my case, there is a CAN controller that, if not shut down properly, can't ever be opened again. My work around was to build a simple UI with a stop button that shuts the process down cleanly. The problem is, out of habit, from using pycharm, goland, and intellij, is to just hit the red, square button. Every time I do that I have to reboot the development system. So I think it is clearly also a development time question.
This actually isnt a simple thing, because PyCharm sends SIGKILL with the stop button. Check the discussion here https://youtrack.jetbrains.com/issue/PY-13316
There is a comment that you can enable "kill windows process softly", however it didnt work for me. The one that does work is emulate terminal in the debug config, then use control c when you select the console window

Start a background process with flask, then detects when it stops

I have a flask server and I'm trying to run a script in the background to enable a pairing process on a raspberry pi. I have a button to enable and disable this which works fine.
I use process = subprocess.Popen(["python3","bt.py"]) to run the process then process.kill() when I need to stop it.
But once the task stops I need to update the page with the new device information, but I'm having trouble detecting when the pairing script stops via flask. I know I can run process.poll() to check if the subprocess is still running but I can't think of any way to implement this into flask as it would need to run in a loop, which would stop the client from receiving the page.
The only thing I think could work would be to edit a file from the bt.py script and have the JS part of my flask app detect the change in the file and cause a redirect. However, this seems clunky and feels like bad practice. Any suggestions would be great

py2app application is working but Mac OS X shows it as not responding

I have a python script (no GUI) that spawns a child thread, while parent thread is preventing the app from finishing using this method:
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
pass
finally:
cleanup()
When I create an application from this script with py2app and run it, it is staying in Dock and working as expected, but when I right click, it shows that "Application Not Responding" (the same in Activity Monitor) and to finish it I can only select "Force Quit" which results in a crash report dialog afterwards.
Why is it not responding and, if the reason is sleep(), how can I keep the app open without it?
It's showing as "not responding" because it's not responding. An application on OS X (as opposed to just a plain "Unix executable"/script, agent, or daemon) has to respond to messages from the operating system.
Normally, you do this by using a Cocoa run loop. PyObjC offers some high-level helpers that make it even simpler, or just lets you access the same Cocoa methods that the Apple docs describe from Python.
Another option is to use a script-wrapper that just runs your script while maintaining a run loop (with or without a GUI) for you.
Finally, do you actually need to be an application in the first place?

wxPython not responding

I'm new to python and now I want to try wxpython, but I can't continue even at the very beginning.
Following the toturial,
import wx
app = wx.App(False)
frame = wx.Frame(None, wx.ID_ANY, "Hello World")
frame.Show(True)
after I did that, the new windows stops responding as soon as the it appears or I try to click it. Then I can only force close it and the editor restarts.
All the same on shell or IDLE, even all the same on different computers(I happened to bought a new one). Maybe I've done something wrong since I searched the internet and it seems no one encounters the problem, but I can't figure it out.
I'm using the latest python(x,y).
In addition, I tried tkinter also on my old computer and the problem is the same, if I remember rightly.
that's because the app loop is not running. usually, you also have to do:
app.MainLoop()
after frame.Show(). of course, now your console will be running the main loop, and you won't get your console back until after the app exits (well, when your main window closes), which probably isn't what you want either.
i haven't used python(x,y), but from a quick look, it looks like it supports IPython(x,y). If you use that as the console, then you can do
%gui wx
after loading, and then instead of creating/running the app yourself, IPython itself implements the app and does event processing in a special way as an input hook - which means that while it is waiting for you to type something, instead of just waiting, it actively polls the gui to see if there are active events and processes them if they are. This can create some interesting problems as well, but then you can just create the window & show it, and it will work correctly....

Pidgin script with Python/ Get Focus Signal

I am creating a script in Python to integrate Pidgin with Unity (Ubuntu 12.04), I've managed to do the counting notifications system using the Unity API, but i dont know what event or signal that is activated when the conversation window gains focus(To clear the message counter)...
I've tried some of the signals available on the documentation of Pidgin (https://developer.pidgin.im/wiki/DbusHowto) but none of them worked, is there any GTK(or anything) event that is triggered when the window chat gets focus?
Conversation UI signals are listed here those might be more helpful for what you are trying to do.
Though I don't know that I understand what you meant by your comment about the counter being wiped instantly when you tried some of the other signals. That sounds like it might be a coding error to me.

Categories