From eaca5bf0065194597906aa7dfd557166de57f4c5 Mon Sep 17 00:00:00 2001 From: AuroraWright Date: Mon, 5 May 2025 05:54:38 +0200 Subject: [PATCH] Move macos screenshot code into the class, add config file only flag to use old API --- owocr/config.py | 3 +- owocr/run.py | 97 ++++++++++++++++++++++++------------------------ owocr_config.ini | 1 + 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/owocr/config.py b/owocr/config.py index 5d174b3..7239a95 100644 --- a/owocr/config.py +++ b/owocr/config.py @@ -67,7 +67,8 @@ class Config: 'screen_capture_area': '', 'screen_capture_delay_secs': 3, 'screen_capture_only_active_windows': True, - 'screen_capture_combo': '' + 'screen_capture_combo': '', + 'screen_capture_old_macos_api': False } def __parse(self, value): diff --git a/owocr/run.py b/owocr/run.py index 99d3878..10b6d00 100644 --- a/owocr/run.py +++ b/owocr/run.py @@ -361,53 +361,6 @@ class WindowsWindowTracker(threading.Thread): on_window_closed(False) -def capture_macos_window_screenshot(window_id): - def shareable_content_completion_handler(shareable_content, error): - if error: - screencapturekit_queue.put(None) - return - - target_window = None - for window in shareable_content.windows(): - if window.windowID() == window_id: - target_window = window - break - - if not target_window: - screencapturekit_queue.put(None) - return - - with objc.autorelease_pool(): - content_filter = SCContentFilter.alloc().initWithDesktopIndependentWindow_(target_window) - - frame = content_filter.contentRect() - scale = content_filter.pointPixelScale() - width = frame.size.width * scale - height = frame.size.height * scale - configuration = SCStreamConfiguration.alloc().init() - configuration.setSourceRect_(CGRectMake(0, 0, frame.size.width, frame.size.height)) - configuration.setWidth_(width) - configuration.setHeight_(height) - configuration.setShowsCursor_(False) - configuration.setCaptureResolution_(SCCaptureResolutionBest) - configuration.setIgnoreGlobalClipSingleWindow_(True) - - SCScreenshotManager.captureImageWithFilter_configuration_completionHandler_( - content_filter, configuration, capture_image_completion_handler - ) - - def capture_image_completion_handler(image, error): - if error: - screencapturekit_queue.put(None) - return - - screencapturekit_queue.put(image) - - SCShareableContent.getShareableContentWithCompletionHandler_( - shareable_content_completion_handler - ) - - def get_windows_window_handle(window_title): def callback(hwnd, window_title_part): window_title = win32gui.GetWindowText(hwnd) @@ -551,7 +504,7 @@ class ScreenshotClass: screen_capture_only_active_windows = config.get_general('screen_capture_only_active_windows') area_invalid_error = '"screen_capture_area" must be empty, "screen_N" where N is a screen number starting from 1, a valid set of coordinates, or a valid window name' if sys.platform == 'darwin': - if int(platform.mac_ver()[0].split('.')[0]) < 14: + if config.get_general('screen_capture_old_macos_api') or int(platform.mac_ver()[0].split('.')[0]) < 14: self.old_macos_screenshot_api = True else: self.old_macos_screenshot_api = False @@ -608,6 +561,52 @@ class ScreenshotClass: self.windows_window_tracker.stop = True self.windows_window_tracker.join() + def capture_macos_window_screenshot(self, window_id): + def shareable_content_completion_handler(shareable_content, error): + if error: + screencapturekit_queue.put(None) + return + + target_window = None + for window in shareable_content.windows(): + if window.windowID() == window_id: + target_window = window + break + + if not target_window: + screencapturekit_queue.put(None) + return + + with objc.autorelease_pool(): + content_filter = SCContentFilter.alloc().initWithDesktopIndependentWindow_(target_window) + + frame = content_filter.contentRect() + scale = content_filter.pointPixelScale() + width = frame.size.width * scale + height = frame.size.height * scale + configuration = SCStreamConfiguration.alloc().init() + configuration.setSourceRect_(CGRectMake(0, 0, frame.size.width, frame.size.height)) + configuration.setWidth_(width) + configuration.setHeight_(height) + configuration.setShowsCursor_(False) + configuration.setCaptureResolution_(SCCaptureResolutionBest) + configuration.setIgnoreGlobalClipSingleWindow_(True) + + SCScreenshotManager.captureImageWithFilter_configuration_completionHandler_( + content_filter, configuration, capture_image_completion_handler + ) + + def capture_image_completion_handler(image, error): + if error: + screencapturekit_queue.put(None) + return + + screencapturekit_queue.put(image) + + SCShareableContent.getShareableContentWithCompletionHandler_( + shareable_content_completion_handler + ) + def __call__(self): if self.screencapture_mode == 2: if sys.platform == 'darwin': @@ -615,7 +614,7 @@ class ScreenshotClass: if self.old_macos_screenshot_api: cg_image = CGWindowListCreateImageFromArray(CGRectNull, [self.window_id], kCGWindowImageBoundsIgnoreFraming) else: - capture_macos_window_screenshot(self.window_id) + self.capture_macos_window_screenshot(self.window_id) try: cg_image = screencapturekit_queue.get(timeout=0.5) except queue.Empty: diff --git a/owocr_config.ini b/owocr_config.ini index 635bd58..386ca1a 100644 --- a/owocr_config.ini +++ b/owocr_config.ini @@ -28,6 +28,7 @@ ;screen_capture_delay_secs = 3 ;note: this specifies a combo to wait on for taking a screenshot instead of using the delay. As an example: ++s. The list of keys can be found here: https://pynput.readthedocs.io/en/latest/keyboard.html#pynput.keyboard.Key ;screen_capture_combo = ++s +;screen_capture_old_macos_api = False ;[winrtocr] ;url = http://aaa.xxx.yyy.zzz:8000 ;[oneocr]