-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows: capture cursor #272
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Type: Enhancement
PR Summary: The pull request introduces functionality to capture the cursor on Windows systems. It adds new structures to hold cursor and icon information, updates function mappings for cursor-related API calls, and implements methods to capture cursor data and handle monochrome cursors.
Decision: Comment
📝 Type: 'Enhancement' - not supported yet.
- Sourcery currently only approves 'Typo fix' PRs.
✅ Issue addressed: this change correctly addresses the issue or implements the desired feature.
No details provided.
✅ Small diff: the diff is small enough to approve with confidence.
No details provided.
General suggestions:
- Ensure that the new cursor capture functionality is robustly integrated with the existing codebase, including proper error handling and validation of API call results.
- Clarify the necessity of casting 'memdc' to 'HDC' in the 'DrawIcon' call and document the reasoning within the code to aid future maintainability.
- Consider the implications of the change in the return type of '_grab_impl' to 'Optional[ScreenShot]' and verify that all calling code is updated to handle potential 'None' values.
Thanks for using Sourcery. We offer it for free for open source projects and would be very grateful if you could help us grow. If you like it, would you consider sharing Sourcery on your favourite social media? ✨
src/mss/windows.py
Outdated
self._handles.ci = ci | ||
|
||
iconinfo = ICONINFO() # 'ii' felt uncomfortable | ||
self._handles.iconinfo = iconinfo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (llm): The initialization of 'iconinfo' without checking the return value of 'GetIconInfo' could lead to issues if 'GetIconInfo' fails. It would be safer to check the return value before assuming that 'iconinfo' has been properly initialized.
src/mss/windows.py
Outdated
self._handles.bmp = gdi.CreateCompatibleBitmap(srcdc, width, height) | ||
gdi.SelectObject(memdc, self._handles.bmp) | ||
|
||
user32.DrawIcon(HDC(memdc), 0, 0, hcursor) # Why HDC? [1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question (llm): The comment '[1]' questions the need for casting 'memdc' to 'HDC'. It's important to clarify whether this cast is indeed necessary and to document the reason in the code to avoid confusion for future maintainers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great PR, thank you !
Would you mind adding tests like I did in https://github.com/BoboTiG/python-mss/blob/e66199adcdad737ef4d66183083bd26c827090da/src/tests/test_gnu_linux.py 🙏🏻 ?
src/mss/windows.py
Outdated
@@ -121,6 +155,13 @@ def __init__(self, /, **kwargs: Any) -> None: | |||
bmi.bmiHeader.biClrImportant = 0 # See grab.__doc__ [3] | |||
self._handles.bmi = bmi | |||
|
|||
ci = CURSORINFO() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you use more explicit name? cusor_info
seems a good one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, will do
src/mss/windows.py
Outdated
ci.cbSize = ctypes.sizeof(CURSORINFO) | ||
self._handles.ci = ci | ||
|
||
iconinfo = ICONINFO() # 'ii' felt uncomfortable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iconinfo = ICONINFO() # 'ii' felt uncomfortable | |
icon_info = ICONINFO() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea i will fix that too
@@ -200,7 +241,7 @@ def _callback(monitor: int, data: HDC, rect: LPRECT, dc_: LPARAM) -> int: | |||
callback = MONITORNUMPROC(_callback) | |||
user32.EnumDisplayMonitors(0, 0, callback, 0) | |||
|
|||
def _grab_impl(self, monitor: Monitor, /) -> ScreenShot: | |||
def _grab_impl(self, monitor: Monitor, /) -> Optional[ScreenShot]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to not change that part. If the process fails, then an exception will be raised.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it was changed for the linux implementation so i did it but i can see why you would like to avoid that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are all good on Linux side: https://github.com/BoboTiG/python-mss/blob/v9.0.1/src/mss/linux.py#L424
cursors the alpha value of every pixel is 0 for some reason. Therefore, the alpha | ||
value of every non black pixel has to be manually set to 255. | ||
""" | ||
srcdc, memdc = self._handles.srcdc, self._handles.memdc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love the documentation 💪🏻
For the implementation, do we need to copy all from the grab() method? Can it be simplified to only the cursor itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i did not care to look into it but now that you said it i will see if something can be done about simplifying it to just the cursor
i will update you once im done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UPDATE: im afraid it would not be possible since the cursor is a part of the screen's device context, it should not be a huge issue as im making a small 32x32 bitmap and capturing only the cursor's image
im sorry if im wrong, im not an expert at windows api and i would love to learn something new
I have absolutely no experience in writing tests, sorry |
I was trying to make sense of how your linux tests worked, and I assume that you try taking screenshots of a black screen one with cursor and one without cursor and then check if you find an RGB value other than 0, am I right? And if I'm right how do you run this test? I can't make sense of how you are actually going to run this test in a way it does it's job because the screen is mostly never pitch black, do you have a second completely blank monitor that you use for this test? Sorry if I'm just being dumb I don't have any experience with testing. |
Windows tests will be more tricky, for sure. |
Thank you, is there anything else I could help with? |
It's all good for now. I'll check the code, test it on a VM, and get back to the PR when I'll have some time. |
"left": round(pos_screen.x * ratio - self._handles.icon_info.xHotspot), | ||
"top": round(pos_screen.y * ratio - self._handles.icon_info.yHotspot), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I used this PR in my project and from my testing multiplying by ratio actually messes things up. When i removed it everything worked fine even on strange DPI scalings in multiple different positions of multi monitor setup. For testing I used https://github.com/pavlobu/deskreen with https://www.amyuni.com/forum/viewtopic.php?t=3030
Changes proposed in this PR
It is very important to keep up to date tests and documentation.
Is your code right?
flake8
passed