Performance issues on Windows
I switched my project to use your library, it calls get_monitors() once per second, and I noticed it was introducing very noticeable lag across my whole PC after a few hours of use. I'd restart the script and it would be fine for a few hours, then it would break again.
There's two separate issues that it causes:
The first is that apparently GetDC can be a blocking call under certain circumstances. In my case, after a few hours, it's getting in a state where it fails the 100 retries on every run. That loop takes around 0.5 seconds to complete, which pretty much completely locks up the PC while it runs, freezing the mouse cursor.
I tested changing the number of retries to 10, and while it did make a difference, the underlying issue was still there and I could see see the little hitches as I moved my cursor across the screen.
The second issue is that it can cause other events to trigger this. For example when Razer Synapse switches a mouse or keyboard profile, it also triggers the same lag spike.
This is independent of the first issue and happens a lot sooner. Stopping calls to get_monitors doesn't fix it - the only solution is to shut down the script, which I guess releases whatever API resources that are causing the problem.
I tested removing the GetDC calls and it fixed both issues.
I'm not sure if there's any alternative, but it seems that particular call comes with potential side effects, that are more likely to happen the more the script is run.
My one idea would be adding a parameter to get_monitors that could optionally disable that feature:
def get_monitors(name, get_physical_size=True): ...
If I remember right, there was a similar ticket once I had the same problem. But then, is there a need to check for monitors every second? I check in my projects once at start for new monitors and add them in a list. It's the same list as the one get_monitors returns except when you unplug or change any of the screens. In my case that never happens. Maybe this can work for you too?
In my case, the app's purpose is to tracking mouse movements amongst other things, so if there's any change in monitors (new one plugged in / one resized, etc) it needs to instantly know otherwise the data recorded will be all wrong.
I'd not considered looking into hooks that trigger when certain events happen though, if it's possible then I'll give it a try at some point.
Edit: Happy to report it's possible and was not too hard to implement.
Do you think it would make sense to include this workaround as part of the library? My intuition is that this is prone to platform-specific caching problems and can potentially do more harm than good.
If by workaround you mean the event listener, then I reckon that's outside the scope of your module (unless of course you found a reliable way to do it on each OS, in which case it would be a very handy feature).
If you just meant about the GetDC calls, I was only really reporting that there are unfortunately some issues with them, but I'm not sure what the best solution would be. The extra parameter idea was the only thing that came to mind.