quickmacapp 2025.3.16__tar.gz → 2025.3.18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/PKG-INFO +1 -1
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/pyproject.toml +1 -1
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp/__init__.py +2 -0
- quickmacapp-2025.3.18/src/quickmacapp/_background.py +155 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp.egg-info/PKG-INFO +1 -1
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp.egg-info/SOURCES.txt +1 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/LICENSE +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/README.rst +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/setup.cfg +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp/_interactions.py +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp/_quickapp.py +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp/py.typed +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp.egg-info/dependency_links.txt +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp.egg-info/requires.txt +0 -0
- {quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp.egg-info/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
name = "quickmacapp"
|
|
10
10
|
description = "Make it easier to write Mac apps in Python"
|
|
11
11
|
readme = "README.rst"
|
|
12
|
-
version = "2025.03.
|
|
12
|
+
version = "2025.03.18"
|
|
13
13
|
dependencies = [
|
|
14
14
|
"pyobjc-framework-Cocoa",
|
|
15
15
|
"pyobjc-framework-ExceptionHandling",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from ._quickapp import Actionable, Status, mainpoint, menu, quit
|
|
2
2
|
from ._interactions import ask, choose, answer, getpass
|
|
3
|
+
from ._background import dockIconWhenVisible
|
|
3
4
|
|
|
4
5
|
__all__ = [
|
|
5
6
|
"Actionable",
|
|
@@ -11,4 +12,5 @@ __all__ = [
|
|
|
11
12
|
"choose",
|
|
12
13
|
"answer",
|
|
13
14
|
"getpass",
|
|
15
|
+
"dockIconWhenVisible",
|
|
14
16
|
]
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from typing import Any, Callable
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
|
|
5
|
+
from AppKit import (
|
|
6
|
+
NSApplication,
|
|
7
|
+
NSApplicationActivateIgnoringOtherApps,
|
|
8
|
+
NSApplicationActivationPolicyAccessory,
|
|
9
|
+
NSApplicationActivationPolicyRegular,
|
|
10
|
+
NSLog,
|
|
11
|
+
NSNotification,
|
|
12
|
+
NSNotificationCenter,
|
|
13
|
+
NSRunningApplication,
|
|
14
|
+
NSWindow,
|
|
15
|
+
NSWindowWillCloseNotification,
|
|
16
|
+
NSWorkspace,
|
|
17
|
+
NSWorkspaceActiveSpaceDidChangeNotification,
|
|
18
|
+
NSWorkspaceApplicationKey,
|
|
19
|
+
NSWorkspaceDidActivateApplicationNotification,
|
|
20
|
+
NSWorkspaceDidHideApplicationNotification,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class SometimesBackground:
|
|
26
|
+
"""
|
|
27
|
+
An application that is sometimes in the background but has a window that,
|
|
28
|
+
when visible, can own the menubar, become key, etc. However, when that
|
|
29
|
+
window is closed, we withdraw to the menu bar and continue running in the
|
|
30
|
+
background, as an accessory.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
mainWindow: NSWindow
|
|
34
|
+
hideIconOnOtherSpaces: bool
|
|
35
|
+
onSpaceChange: Callable[[], None]
|
|
36
|
+
currentlyRegular: bool = False
|
|
37
|
+
previouslyActiveApp: NSRunningApplication = field(init=False)
|
|
38
|
+
|
|
39
|
+
def someApplicationActivated_(self, notification: Any) -> None:
|
|
40
|
+
# NSLog(f"active {notification} {__file__}")
|
|
41
|
+
whichApp = notification.userInfo()[NSWorkspaceApplicationKey]
|
|
42
|
+
|
|
43
|
+
if whichApp == NSRunningApplication.currentApplication():
|
|
44
|
+
if self.currentlyRegular:
|
|
45
|
+
# NSLog("show editor window")
|
|
46
|
+
self.mainWindow.setIsVisible_(True)
|
|
47
|
+
else:
|
|
48
|
+
# NSLog("reactivate workaround")
|
|
49
|
+
self.currentlyRegular = True
|
|
50
|
+
self.previouslyActiveApp.activateWithOptions_(
|
|
51
|
+
NSApplicationActivateIgnoringOtherApps
|
|
52
|
+
)
|
|
53
|
+
app = NSApplication.sharedApplication()
|
|
54
|
+
app.setActivationPolicy_(NSApplicationActivationPolicyRegular)
|
|
55
|
+
self.mainWindow.setIsVisible_(True)
|
|
56
|
+
from twisted.internet import reactor
|
|
57
|
+
|
|
58
|
+
reactor.callLater( # type:ignore[attr-defined]
|
|
59
|
+
0.1, lambda: app.activateIgnoringOtherApps_(True)
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
self.previouslyActiveApp = whichApp
|
|
63
|
+
|
|
64
|
+
def someApplicationHidden_(self, notification: Any) -> None:
|
|
65
|
+
"""
|
|
66
|
+
An app was hidden.
|
|
67
|
+
"""
|
|
68
|
+
whichApp = notification.userInfo()[NSWorkspaceApplicationKey]
|
|
69
|
+
if whichApp == NSRunningApplication.currentApplication():
|
|
70
|
+
# 'hide others' (and similar functionality) should *not* hide the
|
|
71
|
+
# progress window; that would obviate the whole point of having
|
|
72
|
+
# this app live in the background in order to maintain a constant
|
|
73
|
+
# presence in the user's visual field. however if we're being told
|
|
74
|
+
# to hide, don't ignore the user, hide the main window and retreat
|
|
75
|
+
# into the background as if we were closed.
|
|
76
|
+
self.mainWindow.close()
|
|
77
|
+
app = NSApplication.sharedApplication()
|
|
78
|
+
app.unhide_(self)
|
|
79
|
+
|
|
80
|
+
def someSpaceActivated_(self, notification: NSNotification) -> None:
|
|
81
|
+
"""
|
|
82
|
+
Sometimes, fullscreen application stop getting the HUD overlay.
|
|
83
|
+
"""
|
|
84
|
+
menuBarOwner = NSWorkspace.sharedWorkspace().menuBarOwningApplication()
|
|
85
|
+
# me = NSRunningApplication.currentApplication()
|
|
86
|
+
NSLog("space activated where allegedly %@ owns the menu bar", menuBarOwner)
|
|
87
|
+
if not self.mainWindow.isOnActiveSpace():
|
|
88
|
+
if self.hideIconOnOtherSpaces:
|
|
89
|
+
NSLog("I am not on the active space, closing the window")
|
|
90
|
+
self.mainWindow.close()
|
|
91
|
+
else:
|
|
92
|
+
NSLog("I am not on the active space, but that's OK, leaving window open.")
|
|
93
|
+
else:
|
|
94
|
+
NSLog("I am on the active space; not closing.")
|
|
95
|
+
self.onSpaceChange()
|
|
96
|
+
|
|
97
|
+
def someWindowWillClose_(self, notification: NSNotification) -> None:
|
|
98
|
+
"""
|
|
99
|
+
The main window that we're observing will close.
|
|
100
|
+
"""
|
|
101
|
+
if notification.object() == self.mainWindow:
|
|
102
|
+
self.currentlyRegular = False
|
|
103
|
+
NSApplication.sharedApplication().setActivationPolicy_(
|
|
104
|
+
NSApplicationActivationPolicyAccessory
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def startObserving(self) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Attach the various callbacks.
|
|
110
|
+
"""
|
|
111
|
+
NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(
|
|
112
|
+
self, "someWindowWillClose:", NSWindowWillCloseNotification, None
|
|
113
|
+
)
|
|
114
|
+
wsnc = NSWorkspace.sharedWorkspace().notificationCenter()
|
|
115
|
+
|
|
116
|
+
self.previouslyActiveApp = (
|
|
117
|
+
NSWorkspace.sharedWorkspace().menuBarOwningApplication()
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
wsnc.addObserver_selector_name_object_(
|
|
121
|
+
self,
|
|
122
|
+
"someApplicationActivated:",
|
|
123
|
+
NSWorkspaceDidActivateApplicationNotification,
|
|
124
|
+
None,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
wsnc.addObserver_selector_name_object_(
|
|
128
|
+
self,
|
|
129
|
+
"someApplicationHidden:",
|
|
130
|
+
NSWorkspaceDidHideApplicationNotification,
|
|
131
|
+
None,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
wsnc.addObserver_selector_name_object_(
|
|
135
|
+
self,
|
|
136
|
+
"someSpaceActivated:",
|
|
137
|
+
NSWorkspaceActiveSpaceDidChangeNotification,
|
|
138
|
+
None,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def dockIconWhenVisible(
|
|
143
|
+
mainWindow: NSWindow,
|
|
144
|
+
hideIconOnOtherSpaces: bool = True,
|
|
145
|
+
onSpaceChange: Callable[[], None] = lambda: None,
|
|
146
|
+
):
|
|
147
|
+
"""
|
|
148
|
+
When the given main window is visible, we should have a dock icon (i.e.: be
|
|
149
|
+
NSApplicationActivationPolicyRegular). When our application is activated,
|
|
150
|
+
(i.e.: the user launches it from Spotlight, Finder, or similar) we should
|
|
151
|
+
make the window visible so that the dock icon appears. When that window is
|
|
152
|
+
then closed, or when our application is hidden, we should hide our dock
|
|
153
|
+
icon (i.e.: be NSApplicationActivationPolicyAccessory).
|
|
154
|
+
"""
|
|
155
|
+
SometimesBackground(mainWindow, hideIconOnOtherSpaces, onSpaceChange).startObserving()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickmacapp-2025.3.16 → quickmacapp-2025.3.18}/src/quickmacapp.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|