Make fullscreen windows work on macOS

This commit is contained in:
AuroraWright
2024-03-01 16:44:42 +01:00
parent 4b58157c09
commit 7eba9235ef

View File

@@ -40,7 +40,10 @@ except ImportError:
try: try:
import objc import objc
from AppKit import NSData, NSImage, NSBitmapImageRep, NSDeviceRGBColorSpace, NSGraphicsContext, NSZeroPoint, NSZeroRect, NSCompositingOperationCopy from AppKit import NSData, NSImage, NSBitmapImageRep, NSDeviceRGBColorSpace, NSGraphicsContext, NSZeroPoint, NSZeroRect, NSCompositingOperationCopy
from Quartz import CGWindowListCreateImageFromArray, kCGWindowImageBoundsIgnoreFraming, CGRectNull, CGWindowListCopyWindowInfo, CGWindowListCreateDescriptionFromArray, kCGWindowListOptionOnScreenAboveWindow, kCGWindowListOptionIncludingWindow, kCGWindowListOptionOnScreenOnly, kCGWindowListExcludeDesktopElements, kCGWindowName, kCGNullWindowID from Quartz import CGWindowListCreateImageFromArray, kCGWindowImageBoundsIgnoreFraming, CGRectNull, CGWindowListCopyWindowInfo, CGWindowListCreateDescriptionFromArray, \
kCGWindowListOptionOnScreenOnly, kCGWindowListExcludeDesktopElements, kCGWindowName, kCGNullWindowID, \
CGImageGetWidth, CGImageGetHeight, CGDataProviderCopyData, CGImageGetDataProvider, CGImageGetBytesPerRow
except ImportError: except ImportError:
pass pass
@@ -170,18 +173,22 @@ class MacOSWindowTracker(threading.Thread):
found = True found = True
while found and not self.stop: while found and not self.stop:
found = False found = False
is_active = False
with objc.autorelease_pool(): with objc.autorelease_pool():
window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenAboveWindow | kCGWindowListOptionIncludingWindow, self.window_id) window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID)
for i, window in enumerate(window_list): for i, window in enumerate(window_list):
if found and window.get(kCGWindowName, '') == 'Fullscreen Backdrop':
is_active = True
break
if self.window_id == window['kCGWindowNumber']: if self.window_id == window['kCGWindowNumber']:
found = True found = True
is_active = window_list[i-1].get(kCGWindowName, '') == 'Dock' if window_list[i-1].get(kCGWindowName, '') == 'Dock':
break is_active = True
break
if not found: if not found:
window_list = CGWindowListCreateDescriptionFromArray([self.window_id]) window_list = CGWindowListCreateDescriptionFromArray([self.window_id])
if len(window_list) > 0: if len(window_list) > 0:
found = True found = True
is_active = False
if found and self.window_active != is_active: if found and self.window_active != is_active:
on_window_activated(is_active) on_window_activated(is_active)
self.window_active = is_active self.window_active = is_active
@@ -684,19 +691,16 @@ def run(read_from=None,
sct_params = {'top': coord_top, 'left': coord_left, 'width': coord_width, 'height': coord_height, 'mon': screen_capture_monitor} sct_params = {'top': coord_top, 'left': coord_left, 'width': coord_width, 'height': coord_height, 'mon': screen_capture_monitor}
else: else:
if sys.platform == 'darwin': if sys.platform == 'darwin':
window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID) window_list = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID)
window_titles = [] window_titles = []
window_ids = [] window_ids = []
window_id = 0 window_id = 0
after_dock = False
target_index = None target_index = None
for i, window in enumerate(window_list): for i, window in enumerate(window_list):
window_title = window.get(kCGWindowName, '') window_title = window.get(kCGWindowName, '')
if after_dock and psutil.Process(window['kCGWindowOwnerPID']).name() not in ('Terminal', 'iTerm2'): if psutil.Process(window['kCGWindowOwnerPID']).name() not in ('Terminal', 'iTerm2'):
window_titles.append(window_title) window_titles.append(window_title)
window_ids.append(window['kCGWindowNumber']) window_ids.append(window['kCGWindowNumber'])
if window_title == 'Dock':
after_dock = True
if screen_capture_coords in window_titles: if screen_capture_coords in window_titles:
window_id = window_ids[window_titles.index(screen_capture_coords)] window_id = window_ids[window_titles.index(screen_capture_coords)]
@@ -877,9 +881,11 @@ def run(read_from=None,
if not cg_image: if not cg_image:
on_window_closed(False) on_window_closed(False)
break break
ns_imagerep = NSBitmapImageRep.alloc().initWithCGImage_(cg_image) width = CGImageGetWidth(cg_image)
img = ns_imagerep.TIFFRepresentation() height = CGImageGetHeight(cg_image)
img = Image.open(io.BytesIO(img)) raw_data = CGDataProviderCopyData(CGImageGetDataProvider(cg_image))
bpr = CGImageGetBytesPerRow(cg_image)
img = Image.frombuffer('RGBA', (width, height), raw_data, 'raw', 'BGRA', bpr, 1)
elif screencapture_mode == 2 and sys.platform == 'win32': elif screencapture_mode == 2 and sys.platform == 'win32':
try: try:
coord_left, coord_top, right, bottom = win32gui.GetWindowRect(window_handle) coord_left, coord_top, right, bottom = win32gui.GetWindowRect(window_handle)