_pygetwindow_macos.py
6.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import Quartz
import pygetwindow
def getAllTitles():
"""Returns a list of strings of window titles for all visible windows.
"""
# Source: https://stackoverflow.com/questions/53237278/obtain-list-of-all-window-titles-on-macos-from-a-python-script/53985082#53985082
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
return ['%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')) for win in windows]
def getActiveWindow():
"""Returns a Window object of the currently active Window."""
# Source: https://stackoverflow.com/questions/5286274/front-most-window-using-cgwindowlistcopywindowinfo
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
for win in windows:
if win['kCGWindowLayer'] == 0:
return '%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')) # Temporary. For now, we'll just return the title of the active window.
raise Exception('Could not find an active window.') # Temporary hack.
def getWindowsAt(x, y):
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
matches = []
for win in windows:
w = win['kCGWindowBounds']
if pygetwindow.pointInRect(x, y, w['X'], w['Y'], w['Width'], w['Height']):
matches.append('%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')))
return matches
def activate():
# TEMP - this is not a real api, I'm just using this name to store these notes for now.
# Source: https://stackoverflow.com/questions/7460092/nswindow-makekeyandorderfront-makes-window-appear-but-not-key-or-front?rq=1
# Source: https://stackoverflow.com/questions/4905024/is-it-possible-to-bring-window-to-front-without-taking-focus?rq=1
pass
def getWindowGeometry(title):
# TEMP - this is not a real api, I'm just using this name to stoe these notes for now.
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
for win in windows:
if title in '%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')):
w = win['kCGWindowBounds']
return (w['X'], w['Y'], w['Width'], w['Height'])
def isVisible(title):
# TEMP - this is not a real api, I'm just using this name to stoe these notes for now.
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
for win in windows:
if title in '%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')):
return win['kCGWindowAlpha'] != 0.0
def isMinimized():
# TEMP - this is not a real api, I'm just using this name to stoe these notes for now.
# Source: https://stackoverflow.com/questions/10258676/how-to-know-whether-a-window-is-minimised-or-not
# Use the kCGWindowIsOnscreen to check this. Minimized windows are considered to not be on the screen. (But I'm not sure if there are other situations where a window is "off screen".)
# I'm not sure how kCGWindowListOptionOnScreenOnly interferes with this.
pass
# TODO: This class doesn't work yet. I've copied the Win32Window class and will make adjustments as needed here.
class MacOSWindow():
def __init__(self, hWnd):
self._hWnd = hWnd # TODO fix this, this is a LP_c_long insead of an int.
def _onRead(attrName):
r = self._getWindowRect(_hWnd)
self._rect._left = r.left # Setting _left directly to skip the onRead.
self._rect._top = r.top # Setting _top directly to skip the onRead.
self._rect._width = r.right - r.left # Setting _width directly to skip the onRead.
self._rect._height = r.bottom - r.top # Setting _height directly to skip the onRead.
def _onChange(oldBox, newBox):
self.moveTo(newBox.left, newBox.top)
self.resizeTo(newBox.width, newBox.height)
r = self._getWindowRect(_hWnd)
self._rect = pyrect.Rect(r.left, r.top, r.right - r.left, r.bottom - r.top, onChange=_onChange, onRead=_onRead)
def __str__(self):
r = self._getWindowRect(_hWnd)
width = r.right - r.left
height = r.bottom - r.top
return '<%s left="%s", top="%s", width="%s", height="%s", title="%s">' % (self.__class__.__name__, r.left, r.top, width, height, self.title)
def __repr__(self):
return '%s(hWnd=%s)' % (self.__class__.__name__, self._hWnd)
def __eq__(self, other):
return isinstance(other, MacOSWindow) and self._hWnd == other._hWnd
def close(self):
"""Closes this window. This may trigger "Are you sure you want to
quit?" dialogs or other actions that prevent the window from
actually closing. This is identical to clicking the X button on the
window."""
raise NotImplementedError
def minimize(self):
"""Minimizes this window."""
raise NotImplementedError
def maximize(self):
"""Maximizes this window."""
raise NotImplementedError
def restore(self):
"""If maximized or minimized, restores the window to it's normal size."""
raise NotImplementedError
def activate(self):
"""Activate this window and make it the foreground window."""
raise NotImplementedError
def resizeRel(self, widthOffset, heightOffset):
"""Resizes the window relative to its current size."""
raise NotImplementedError
def resizeTo(self, newWidth, newHeight):
"""Resizes the window to a new width and height."""
raise NotImplementedError
def moveRel(self, xOffset, yOffset):
"""Moves the window relative to its current position."""
raise NotImplementedError
def moveTo(self, newLeft, newTop):
"""Moves the window to new coordinates on the screen."""
raise NotImplementedError
@property
def isMinimized(self):
"""Returns True if the window is currently minimized."""
raise NotImplementedError
@property
def isMaximized(self):
"""Returns True if the window is currently maximized."""
raise NotImplementedError
@property
def isActive(self):
"""Returns True if the window is currently the active, foreground window."""
raise NotImplementedError
@property
def title(self):
"""Returns the window title as a string."""
raise NotImplementedError
@property
def visible(self):
raise NotImplementedError