diff --git a/README.md b/README.md index f0f0c8e..d1a755a 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ This project is inspired by [Game2Text] but takes a different technical approach ## Known limitations -- Currently **only supported on Linux**. Porting it to macOS and Windows should - be doable by adding the ability to list windows (see `windows_list.py`, patch +- Currently **only supported on Linux and Windows**. Porting it to macOS should + be doable by adding the ability to list windows (see `windows_list/windows_list_osx.py`, patch welcome) - **No configuration**, only designed for my own needs so far - A bit **slow to start** due to the OCR model initialization diff --git a/snapstudysensei/windows_list/__init__.py b/snapstudysensei/windows_list/__init__.py new file mode 100644 index 0000000..77b7482 --- /dev/null +++ b/snapstudysensei/windows_list/__init__.py @@ -0,0 +1,8 @@ +import sys + +if sys.platform.startswith("win"): + from .windows_list_win32 import WindowsList +elif sys.platform.startswith("darwin"): + from .windows_list_osx import WindowsList +else: + from .windows_list_x11 import WindowsList diff --git a/snapstudysensei/windows_list/windows_list_osx.py b/snapstudysensei/windows_list/windows_list_osx.py new file mode 100644 index 0000000..9d31b0d --- /dev/null +++ b/snapstudysensei/windows_list/windows_list_osx.py @@ -0,0 +1,3 @@ +class WindowsList: + def __call__(self) -> dict[int, tuple[str, bool]]: + raise NotImplementedError("OSX not supported. Patch welcome.") diff --git a/snapstudysensei/windows_list/windows_list_win32.py b/snapstudysensei/windows_list/windows_list_win32.py new file mode 100644 index 0000000..b3ac075 --- /dev/null +++ b/snapstudysensei/windows_list/windows_list_win32.py @@ -0,0 +1,25 @@ +import ctypes +from ctypes import wintypes + +_USER32 = ctypes.windll.user32 + + +class WindowsList: + def __call__(self) -> dict[int, tuple[str, bool]]: + self.windows = {} + WNDENUMPROC = ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM) + cb_worker = WNDENUMPROC(self._enum_windows_cb) + _USER32.EnumWindows(cb_worker, None) + return self.windows + + def _enum_windows_cb(self, hwnd: wintypes.HWND, _: wintypes.LPARAM): + """Callback for EnumWindows. + + See https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms633498(v=vs.85) + """ + length = _USER32.GetWindowTextLengthW(hwnd) + 1 + buffer = ctypes.create_unicode_buffer(length) + _USER32.GetWindowTextW(hwnd, buffer, length) + if _USER32.IsWindowVisible(hwnd) and len(buffer.value) > 0: + self.windows[hwnd] = (buffer.value, True) + return True diff --git a/snapstudysensei/windows_list.py b/snapstudysensei/windows_list/windows_list_x11.py similarity index 100% rename from snapstudysensei/windows_list.py rename to snapstudysensei/windows_list/windows_list_x11.py