├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_suggestion.yml
├── LICENSE
├── README.md
├── Resources
├── get-windows.swift
├── raise-window
│ ├── raise-window.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ ├── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ │ └── xcuserdata
│ │ │ │ └── vitor.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── xcshareddata
│ │ │ └── xcschemes
│ │ │ │ └── raise-window.xcscheme
│ │ └── xcuserdata
│ │ │ └── vitor.xcuserdatad
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── raise-window
│ │ ├── main.swift
│ │ └── raise-window-Bridging-Header.h
└── request-recording.swift
└── Workflow
├── get-windows
├── icon.png
├── images
└── about
│ └── win.png
├── info.plist
├── raise-window
└── request-recording
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: File a bug report
3 | body:
4 | - type: input
5 | attributes:
6 | label: Workflow version
7 | description: Open the Workflow in Alfred Preferences and find it at the top, near the description
8 | validations:
9 | required: true
10 | - type: input
11 | attributes:
12 | label: Alfred version
13 | description: In the top left corner of Alfred Preferences → General
14 | validations:
15 | required: true
16 | - type: input
17 | attributes:
18 | label: macOS version
19 | description: Click on the menubar → About This Mac
20 | validations:
21 | required: true
22 | - type: textarea
23 | attributes:
24 | label: Debugger output
25 | description: Perform the failing action with [the debugger](https://www.alfredapp.com/help/workflows/advanced/debugger/) open
26 | render: alfred_debugger
27 | validations:
28 | required: true
29 | - type: textarea
30 | attributes:
31 | label: More details
32 | description: Explain what you did, what happened, and what you expected to happen
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_suggestion.yml:
--------------------------------------------------------------------------------
1 | name: Feature Suggestion
2 | description: Suggest a new feature
3 | body:
4 | - type: textarea
5 | attributes:
6 | label: Feature details
7 | description: Explain the feature idea
8 | validations:
9 | required: true
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, Running with Crayons Ltd
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
Window Switcher Alfred Workflow
2 |
3 | Switch to a specific window of an app in the current Desktop Space
4 |
5 | [⤓ Install on the Alfred Gallery](https://alfred.app/workflows/alfredapp/window-switcher)
6 |
7 | ## Usage
8 |
9 | Search app windows in the current Desktop Space via the `win` keyword.
10 |
11 | 
12 |
13 | * ↩︎ Bring window to the front.
14 | * ⌘↩︎ Quit app.
15 |
16 | Configure the [Hotkey](https://www.alfredapp.com/help/workflows/triggers/hotkey/) for faster triggering.
17 |
--------------------------------------------------------------------------------
/Resources/get-windows.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env swift
2 |
3 | import AppKit
4 |
5 | // Helpers
6 | struct ScriptFilterItem: Codable {
7 | let variables: [String: String]
8 | let title: String
9 | let subtitle: String
10 | let arg: [Int32]
11 | let icon: [String: String]
12 | let match: String
13 | }
14 |
15 | // Grab windows
16 | let windowList: CFArray? = CGWindowListCopyWindowInfo(
17 | [.optionOnScreenOnly, .excludeDesktopElements], kCGNullWindowID)
18 |
19 | guard let windows = windowList as? [[String: Any]] else { fatalError("Unable to get window list") }
20 |
21 | // Populate items
22 | let sfItems: [ScriptFilterItem] = windows.compactMap { dict in
23 | guard
24 | dict["kCGWindowLayer"] as? Int == 0,
25 | let appRawName = dict["kCGWindowOwnerName"] as? String,
26 | let appPID = dict["kCGWindowOwnerPID"] as? Int32,
27 | let windowID = dict["kCGWindowNumber"] as? Int32,
28 | let appPath = NSRunningApplication(processIdentifier: appPID)?.bundleURL?.path,
29 | let windowTitle = dict["kCGWindowName"] as? String,
30 | // When using Stage Manager, there are a lot of extra windows from Window Manager
31 | appRawName != "WindowManager",
32 | // Unnamed windows with a low height are generally safe to ignore
33 | // Examples include Safari's 20px status bar and a 68px invisible window present on full screen apps
34 | let windowBounds = dict["kCGWindowBounds"] as? [String: Int32],
35 | let windowHeight = windowBounds["Height"],
36 | !windowTitle.isEmpty || windowHeight > 70
37 | else { return nil }
38 |
39 | // Some apps (e.g. Reeder) have the ".app" extension in "kCGWindowOwnerName"
40 | let appName = URL(fileURLWithPath: appRawName).deletingPathExtension().lastPathComponent
41 |
42 | // Some apps (e.g. Reeder) have legitimate windows without a name
43 | let windowName = windowTitle.isEmpty ? appName : windowTitle
44 |
45 | return ScriptFilterItem(
46 | variables: ["app_name": appName],
47 | title: windowName,
48 | subtitle: appName,
49 | arg: [appPID, windowID],
50 | icon: ["type": "fileicon", "path": appPath],
51 | match: "\(windowName) \(appName)"
52 | )
53 | }
54 |
55 | // Fallback if no valid items
56 | guard !sfItems.isEmpty else {
57 | let subtitle = CGPreflightScreenCaptureAccess() ?
58 | "Make sure there are unminimised windows in the current Desktop Space" :
59 | "Press ↩ to request Screen Recording permissions, necessary to get window information"
60 |
61 | let notFound = [
62 | "title": "No Windows Found",
63 | "subtitle": subtitle,
64 | "arg": "request_permissions"
65 | ]
66 |
67 | let jsonData: Data = try JSONSerialization.data(withJSONObject: ["items": [notFound]])
68 | let jsonString: String = String(data: jsonData, encoding: .utf8)!
69 |
70 | print(jsonString)
71 | exit(0)
72 | }
73 |
74 | // Output JSON
75 | let jsonData = try JSONEncoder().encode(["items": sfItems])
76 | print(String(data: jsonData, encoding: .utf8)!)
77 |
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4E88074D299AED81005D7098 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E88074C299AED81005D7098 /* main.swift */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 4E880747299AED81005D7098 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = /usr/share/man/man1/;
18 | dstSubfolderSpec = 0;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 1;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 4E880749299AED81005D7098 /* raise-window */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "raise-window"; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 4E88074C299AED81005D7098 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; };
28 | 4E880756299AEF6C005D7098 /* raise-window-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "raise-window-Bridging-Header.h"; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 4E880746299AED81005D7098 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 4E880740299AED81005D7098 = {
43 | isa = PBXGroup;
44 | children = (
45 | 4E88074B299AED81005D7098 /* raise-window */,
46 | 4E88074A299AED81005D7098 /* Products */,
47 | );
48 | sourceTree = "";
49 | };
50 | 4E88074A299AED81005D7098 /* Products */ = {
51 | isa = PBXGroup;
52 | children = (
53 | 4E880749299AED81005D7098 /* raise-window */,
54 | );
55 | name = Products;
56 | sourceTree = "";
57 | };
58 | 4E88074B299AED81005D7098 /* raise-window */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 4E88074C299AED81005D7098 /* main.swift */,
62 | 4E880756299AEF6C005D7098 /* raise-window-Bridging-Header.h */,
63 | );
64 | path = "raise-window";
65 | sourceTree = "";
66 | };
67 | /* End PBXGroup section */
68 |
69 | /* Begin PBXNativeTarget section */
70 | 4E880748299AED81005D7098 /* raise-window */ = {
71 | isa = PBXNativeTarget;
72 | buildConfigurationList = 4E880750299AED81005D7098 /* Build configuration list for PBXNativeTarget "raise-window" */;
73 | buildPhases = (
74 | 4E880745299AED81005D7098 /* Sources */,
75 | 4E880746299AED81005D7098 /* Frameworks */,
76 | 4E880747299AED81005D7098 /* CopyFiles */,
77 | );
78 | buildRules = (
79 | );
80 | dependencies = (
81 | );
82 | name = "raise-window";
83 | productName = "raise-window";
84 | productReference = 4E880749299AED81005D7098 /* raise-window */;
85 | productType = "com.apple.product-type.tool";
86 | };
87 | /* End PBXNativeTarget section */
88 |
89 | /* Begin PBXProject section */
90 | 4E880741299AED81005D7098 /* Project object */ = {
91 | isa = PBXProject;
92 | attributes = {
93 | BuildIndependentTargetsInParallel = 1;
94 | LastSwiftUpdateCheck = 1420;
95 | LastUpgradeCheck = 1420;
96 | TargetAttributes = {
97 | 4E880748299AED81005D7098 = {
98 | CreatedOnToolsVersion = 14.2;
99 | };
100 | };
101 | };
102 | buildConfigurationList = 4E880744299AED81005D7098 /* Build configuration list for PBXProject "raise-window" */;
103 | compatibilityVersion = "Xcode 14.0";
104 | developmentRegion = en;
105 | hasScannedForEncodings = 0;
106 | knownRegions = (
107 | en,
108 | Base,
109 | );
110 | mainGroup = 4E880740299AED81005D7098;
111 | productRefGroup = 4E88074A299AED81005D7098 /* Products */;
112 | projectDirPath = "";
113 | projectRoot = "";
114 | targets = (
115 | 4E880748299AED81005D7098 /* raise-window */,
116 | );
117 | };
118 | /* End PBXProject section */
119 |
120 | /* Begin PBXSourcesBuildPhase section */
121 | 4E880745299AED81005D7098 /* Sources */ = {
122 | isa = PBXSourcesBuildPhase;
123 | buildActionMask = 2147483647;
124 | files = (
125 | 4E88074D299AED81005D7098 /* main.swift in Sources */,
126 | );
127 | runOnlyForDeploymentPostprocessing = 0;
128 | };
129 | /* End PBXSourcesBuildPhase section */
130 |
131 | /* Begin XCBuildConfiguration section */
132 | 4E88074E299AED81005D7098 /* Debug */ = {
133 | isa = XCBuildConfiguration;
134 | buildSettings = {
135 | ALWAYS_SEARCH_USER_PATHS = NO;
136 | CLANG_ANALYZER_NONNULL = YES;
137 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
138 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
139 | CLANG_ENABLE_MODULES = YES;
140 | CLANG_ENABLE_OBJC_ARC = YES;
141 | CLANG_ENABLE_OBJC_WEAK = YES;
142 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
143 | CLANG_WARN_BOOL_CONVERSION = YES;
144 | CLANG_WARN_COMMA = YES;
145 | CLANG_WARN_CONSTANT_CONVERSION = YES;
146 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
147 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
148 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
149 | CLANG_WARN_EMPTY_BODY = YES;
150 | CLANG_WARN_ENUM_CONVERSION = YES;
151 | CLANG_WARN_INFINITE_RECURSION = YES;
152 | CLANG_WARN_INT_CONVERSION = YES;
153 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
154 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
155 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
156 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
157 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
158 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
159 | CLANG_WARN_STRICT_PROTOTYPES = YES;
160 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
161 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
162 | CLANG_WARN_UNREACHABLE_CODE = YES;
163 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
164 | COPY_PHASE_STRIP = NO;
165 | DEBUG_INFORMATION_FORMAT = dwarf;
166 | ENABLE_STRICT_OBJC_MSGSEND = YES;
167 | ENABLE_TESTABILITY = YES;
168 | GCC_C_LANGUAGE_STANDARD = gnu11;
169 | GCC_DYNAMIC_NO_PIC = NO;
170 | GCC_NO_COMMON_BLOCKS = YES;
171 | GCC_OPTIMIZATION_LEVEL = 0;
172 | GCC_PREPROCESSOR_DEFINITIONS = (
173 | "DEBUG=1",
174 | "$(inherited)",
175 | );
176 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
177 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
178 | GCC_WARN_UNDECLARED_SELECTOR = YES;
179 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
180 | GCC_WARN_UNUSED_FUNCTION = YES;
181 | GCC_WARN_UNUSED_VARIABLE = YES;
182 | MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
183 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
184 | MTL_FAST_MATH = YES;
185 | ONLY_ACTIVE_ARCH = YES;
186 | SDKROOT = macosx;
187 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
188 | "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = "raise-window/raise-window-Bridging-Header.h";
189 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
190 | };
191 | name = Debug;
192 | };
193 | 4E88074F299AED81005D7098 /* Release */ = {
194 | isa = XCBuildConfiguration;
195 | buildSettings = {
196 | ALWAYS_SEARCH_USER_PATHS = NO;
197 | CLANG_ANALYZER_NONNULL = YES;
198 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
200 | CLANG_ENABLE_MODULES = YES;
201 | CLANG_ENABLE_OBJC_ARC = YES;
202 | CLANG_ENABLE_OBJC_WEAK = YES;
203 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
204 | CLANG_WARN_BOOL_CONVERSION = YES;
205 | CLANG_WARN_COMMA = YES;
206 | CLANG_WARN_CONSTANT_CONVERSION = YES;
207 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
208 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
209 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
210 | CLANG_WARN_EMPTY_BODY = YES;
211 | CLANG_WARN_ENUM_CONVERSION = YES;
212 | CLANG_WARN_INFINITE_RECURSION = YES;
213 | CLANG_WARN_INT_CONVERSION = YES;
214 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
215 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
216 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
217 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
218 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
219 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
220 | CLANG_WARN_STRICT_PROTOTYPES = YES;
221 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
222 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
223 | CLANG_WARN_UNREACHABLE_CODE = YES;
224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
225 | COPY_PHASE_STRIP = NO;
226 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
227 | ENABLE_NS_ASSERTIONS = NO;
228 | ENABLE_STRICT_OBJC_MSGSEND = YES;
229 | GCC_C_LANGUAGE_STANDARD = gnu11;
230 | GCC_NO_COMMON_BLOCKS = YES;
231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
233 | GCC_WARN_UNDECLARED_SELECTOR = YES;
234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
235 | GCC_WARN_UNUSED_FUNCTION = YES;
236 | GCC_WARN_UNUSED_VARIABLE = YES;
237 | MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
238 | MTL_ENABLE_DEBUG_INFO = NO;
239 | MTL_FAST_MATH = YES;
240 | SDKROOT = macosx;
241 | SWIFT_COMPILATION_MODE = wholemodule;
242 | "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = "raise-window/raise-window-Bridging-Header.h";
243 | SWIFT_OPTIMIZATION_LEVEL = "-O";
244 | };
245 | name = Release;
246 | };
247 | 4E880751299AED81005D7098 /* Debug */ = {
248 | isa = XCBuildConfiguration;
249 | buildSettings = {
250 | CODE_SIGN_STYLE = Automatic;
251 | DEVELOPMENT_TEAM = WL898W6Y89;
252 | ENABLE_HARDENED_RUNTIME = YES;
253 | PRODUCT_NAME = "$(TARGET_NAME)";
254 | SWIFT_VERSION = 5.0;
255 | };
256 | name = Debug;
257 | };
258 | 4E880752299AED81005D7098 /* Release */ = {
259 | isa = XCBuildConfiguration;
260 | buildSettings = {
261 | CODE_SIGN_STYLE = Automatic;
262 | DEVELOPMENT_TEAM = WL898W6Y89;
263 | ENABLE_HARDENED_RUNTIME = YES;
264 | PRODUCT_NAME = "$(TARGET_NAME)";
265 | SWIFT_VERSION = 5.0;
266 | };
267 | name = Release;
268 | };
269 | /* End XCBuildConfiguration section */
270 |
271 | /* Begin XCConfigurationList section */
272 | 4E880744299AED81005D7098 /* Build configuration list for PBXProject "raise-window" */ = {
273 | isa = XCConfigurationList;
274 | buildConfigurations = (
275 | 4E88074E299AED81005D7098 /* Debug */,
276 | 4E88074F299AED81005D7098 /* Release */,
277 | );
278 | defaultConfigurationIsVisible = 0;
279 | defaultConfigurationName = Release;
280 | };
281 | 4E880750299AED81005D7098 /* Build configuration list for PBXNativeTarget "raise-window" */ = {
282 | isa = XCConfigurationList;
283 | buildConfigurations = (
284 | 4E880751299AED81005D7098 /* Debug */,
285 | 4E880752299AED81005D7098 /* Release */,
286 | );
287 | defaultConfigurationIsVisible = 0;
288 | defaultConfigurationName = Release;
289 | };
290 | /* End XCConfigurationList section */
291 | };
292 | rootObject = 4E880741299AED81005D7098 /* Project object */;
293 | }
294 |
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window.xcodeproj/project.xcworkspace/xcuserdata/vitor.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfredapp/window-switcher-workflow/298be15358c813d7eaf4aa1bd8351d04265405d0/Resources/raise-window/raise-window.xcodeproj/project.xcworkspace/xcuserdata/vitor.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window.xcodeproj/xcshareddata/xcschemes/raise-window.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
44 |
46 |
52 |
53 |
54 |
55 |
61 |
63 |
69 |
70 |
71 |
72 |
74 |
75 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window.xcodeproj/xcuserdata/vitor.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | raise-window.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 4E880748299AED81005D7098
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window/main.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env swift
2 |
3 | guard
4 | let appPID = Int(CommandLine.arguments[1]),
5 | let windowNumber = Int(CommandLine.arguments[2])
6 | else { fatalError("Requires two arguments: app PID and window number") }
7 |
8 | let axApp = AXUIElementCreateApplication(pid_t(appPID))
9 | var axWindows: AnyObject?
10 | AXUIElementCopyAttributeValue(axApp, kAXWindowsAttribute as CFString, &axWindows)
11 |
12 | (axWindows as! [AXUIElement]).forEach { axWindow in
13 | var axWindowNumber: CGWindowID = 0
14 | _AXUIElementGetWindow(axWindow, &axWindowNumber)
15 |
16 | guard axWindowNumber == windowNumber else { return }
17 |
18 | let app = NSRunningApplication(processIdentifier: pid_t(appPID))
19 | app?.activate(options: .activateIgnoringOtherApps)
20 | AXUIElementPerformAction(axWindow, kAXRaiseAction as CFString)
21 | }
22 |
--------------------------------------------------------------------------------
/Resources/raise-window/raise-window/raise-window-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | AXError _AXUIElementGetWindow(AXUIElementRef element, uint32_t *identifier);
4 |
--------------------------------------------------------------------------------
/Resources/request-recording.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env swift
2 |
3 | import AppKit
4 |
5 | CGRequestScreenCaptureAccess()
6 |
--------------------------------------------------------------------------------
/Workflow/get-windows:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfredapp/window-switcher-workflow/298be15358c813d7eaf4aa1bd8351d04265405d0/Workflow/get-windows
--------------------------------------------------------------------------------
/Workflow/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfredapp/window-switcher-workflow/298be15358c813d7eaf4aa1bd8351d04265405d0/Workflow/icon.png
--------------------------------------------------------------------------------
/Workflow/images/about/win.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfredapp/window-switcher-workflow/298be15358c813d7eaf4aa1bd8351d04265405d0/Workflow/images/about/win.png
--------------------------------------------------------------------------------
/Workflow/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bundleid
6 | com.alfredapp.vitor.windowswitcher
7 | connections
8 |
9 | 4324CC66-57F4-4183-9061-3D94423292FA
10 |
11 |
12 | destinationuid
13 | 82CDD910-A6C3-4F66-8394-90150AF91668
14 | modifiers
15 | 0
16 | modifiersubtext
17 |
18 | vitoclose
19 |
20 |
21 |
22 | destinationuid
23 | E3CE2174-60F6-4DDA-9D12-84B0CA5C4271
24 | modifiers
25 | 1048576
26 | modifiersubtext
27 | Quit {var:app_name}
28 | vitoclose
29 |
30 |
31 |
32 | 463DA12A-D0C4-437F-BD05-B512C4FF5DCA
33 |
34 | 6ADF26CF-C74E-42F5-9267-FBAF87960576
35 |
36 |
37 | destinationuid
38 | 4324CC66-57F4-4183-9061-3D94423292FA
39 | modifiers
40 | 0
41 | modifiersubtext
42 |
43 | vitoclose
44 |
45 |
46 |
47 | 82CDD910-A6C3-4F66-8394-90150AF91668
48 |
49 |
50 | destinationuid
51 | BD68FEF5-ECE3-4AAE-8460-2066D5AD1C70
52 | modifiers
53 | 0
54 | modifiersubtext
55 |
56 | sourceoutputuid
57 | C95ACB3C-10F8-4759-909F-525F6F31008A
58 | vitoclose
59 |
60 |
61 |
62 | destinationuid
63 | 463DA12A-D0C4-437F-BD05-B512C4FF5DCA
64 | modifiers
65 | 0
66 | modifiersubtext
67 |
68 | vitoclose
69 |
70 |
71 |
72 | D7455512-A831-4586-8692-E2D2F4B0B802
73 |
74 |
75 | destinationuid
76 | 4324CC66-57F4-4183-9061-3D94423292FA
77 | modifiers
78 | 0
79 | modifiersubtext
80 |
81 | vitoclose
82 |
83 |
84 |
85 | E3CE2174-60F6-4DDA-9D12-84B0CA5C4271
86 |
87 |
88 | destinationuid
89 | 635BD118-84F5-4946-9311-7AA82F846279
90 | modifiers
91 | 0
92 | modifiersubtext
93 |
94 | vitoclose
95 |
96 |
97 |
98 |
99 | createdby
100 | Vítor Galvão
101 | description
102 | Switch to a specific window of an app in the current Desktop Space
103 | disabled
104 |
105 | name
106 | Window Switcher
107 | objects
108 |
109 |
110 | config
111 |
112 | alfredfiltersresults
113 |
114 | alfredfiltersresultsmatchmode
115 | 2
116 | argumenttreatemptyqueryasnil
117 |
118 | argumenttrimmode
119 | 0
120 | argumenttype
121 | 1
122 | escaping
123 | 68
124 | keyword
125 | {var:windows_keyword}
126 | queuedelaycustom
127 | 3
128 | queuedelayimmediatelyinitially
129 |
130 | queuedelaymode
131 | 0
132 | queuemode
133 | 1
134 | runningsubtext
135 | Gathering windows…
136 | script
137 |
138 | scriptargtype
139 | 1
140 | scriptfile
141 | get-windows
142 | skipuniversalaction
143 |
144 | subtext
145 | {const:alfred_workflow_description}
146 | title
147 | {const:alfred_workflow_name}
148 | type
149 | 8
150 | withspace
151 |
152 |
153 | type
154 | alfred.workflow.input.scriptfilter
155 | uid
156 | 4324CC66-57F4-4183-9061-3D94423292FA
157 | version
158 | 3
159 |
160 |
161 | config
162 |
163 | action
164 | 0
165 | argument
166 | 0
167 | focusedappvariable
168 |
169 | focusedappvariablename
170 |
171 | hotkey
172 | 46
173 | hotmod
174 | 1572864
175 | hotstring
176 | M
177 | leftcursor
178 |
179 | modsmode
180 | 0
181 | relatedAppsMode
182 | 0
183 |
184 | type
185 | alfred.workflow.trigger.hotkey
186 | uid
187 | 6ADF26CF-C74E-42F5-9267-FBAF87960576
188 | version
189 | 2
190 |
191 |
192 | config
193 |
194 | concurrently
195 |
196 | escaping
197 | 0
198 | script
199 |
200 | scriptargtype
201 | 1
202 | scriptfile
203 | request-recording
204 | type
205 | 8
206 |
207 | type
208 | alfred.workflow.action.script
209 | uid
210 | BD68FEF5-ECE3-4AAE-8460-2066D5AD1C70
211 | version
212 | 2
213 |
214 |
215 | config
216 |
217 | conditions
218 |
219 |
220 | inputstring
221 |
222 | matchcasesensitive
223 |
224 | matchmode
225 | 0
226 | matchstring
227 | request_permissions
228 | outputlabel
229 | Request Permissions
230 | uid
231 | C95ACB3C-10F8-4759-909F-525F6F31008A
232 |
233 |
234 | elselabel
235 | Raise Window
236 | hideelse
237 |
238 |
239 | type
240 | alfred.workflow.utility.conditional
241 | uid
242 | 82CDD910-A6C3-4F66-8394-90150AF91668
243 | version
244 | 1
245 |
246 |
247 | config
248 |
249 | concurrently
250 |
251 | escaping
252 | 0
253 | script
254 |
255 | scriptargtype
256 | 1
257 | scriptfile
258 | raise-window
259 | type
260 | 8
261 |
262 | type
263 | alfred.workflow.action.script
264 | uid
265 | 463DA12A-D0C4-437F-BD05-B512C4FF5DCA
266 | version
267 | 2
268 |
269 |
270 | config
271 |
272 | availableviaurlhandler
273 |
274 | triggerid
275 | list_windows
276 |
277 | type
278 | alfred.workflow.trigger.external
279 | uid
280 | D7455512-A831-4586-8692-E2D2F4B0B802
281 | version
282 | 1
283 |
284 |
285 | config
286 |
287 | tasksettings
288 |
289 | app_list
290 | {var:app_name}
291 |
292 | taskuid
293 | com.alfredapp.automation.core/macOS/app.quit
294 |
295 | type
296 | alfred.workflow.automation.task
297 | uid
298 | 635BD118-84F5-4946-9311-7AA82F846279
299 | version
300 | 1
301 |
302 |
303 | type
304 | alfred.workflow.utility.junction
305 | uid
306 | E3CE2174-60F6-4DDA-9D12-84B0CA5C4271
307 | version
308 | 1
309 |
310 |
311 | readme
312 | ## Usage
313 |
314 | Search app windows in the current Desktop Space via the `win` keyword.
315 |
316 | 
317 |
318 | * <kbd>↩</kbd> Bring window to the front.
319 | * <kbd>⌘</kbd><kbd>↩</kbd> Quit app.
320 |
321 | Configure the [Hotkey](https://www.alfredapp.com/help/workflows/triggers/hotkey/) for faster triggering.
322 | uidata
323 |
324 | 4324CC66-57F4-4183-9061-3D94423292FA
325 |
326 | note
327 | Show window selection
328 | xpos
329 | 235
330 | ypos
331 | 40
332 |
333 | 463DA12A-D0C4-437F-BD05-B512C4FF5DCA
334 |
335 | xpos
336 | 590
337 | ypos
338 | 200
339 |
340 | 635BD118-84F5-4946-9311-7AA82F846279
341 |
342 | xpos
343 | 590
344 | ypos
345 | 335
346 |
347 | 6ADF26CF-C74E-42F5-9267-FBAF87960576
348 |
349 | note
350 | Optional Hotkey to invoke window selection
351 | xpos
352 | 45
353 | ypos
354 | 40
355 |
356 | 82CDD910-A6C3-4F66-8394-90150AF91668
357 |
358 | xpos
359 | 410
360 | ypos
361 | 60
362 |
363 | BD68FEF5-ECE3-4AAE-8460-2066D5AD1C70
364 |
365 | xpos
366 | 590
367 | ypos
368 | 40
369 |
370 | D7455512-A831-4586-8692-E2D2F4B0B802
371 |
372 | xpos
373 | 45
374 | ypos
375 | 200
376 |
377 | E3CE2174-60F6-4DDA-9D12-84B0CA5C4271
378 |
379 | xpos
380 | 455
381 | ypos
382 | 365
383 |
384 |
385 | userconfigurationconfig
386 |
387 |
388 | config
389 |
390 | default
391 | win
392 | placeholder
393 |
394 | required
395 |
396 | trim
397 |
398 |
399 | description
400 |
401 | label
402 | Windows Keyword
403 | type
404 | textfield
405 | variable
406 | windows_keyword
407 |
408 |
409 | variablesdontexport
410 |
411 | version
412 | 2024.2
413 | webaddress
414 | https://github.com/alfredapp/window-switcher-workflow/
415 |
416 |
417 |
--------------------------------------------------------------------------------
/Workflow/raise-window:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfredapp/window-switcher-workflow/298be15358c813d7eaf4aa1bd8351d04265405d0/Workflow/raise-window
--------------------------------------------------------------------------------
/Workflow/request-recording:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfredapp/window-switcher-workflow/298be15358c813d7eaf4aa1bd8351d04265405d0/Workflow/request-recording
--------------------------------------------------------------------------------