feat: add option to preview selected window (closes #967)
This commit is contained in:
1 parent
b5c3bedd14
commit
6534a2d62e
53 files changed
+228
-11
No files matched your search
@@ -10,6 +10,7 @@
|
||||
4807A6C623A9CD190052A53E /* SkyLight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4807A6C523A9CD190052A53E /* SkyLight.framework */; };
|
||||
48F3E16224EC0D8800A1C64B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BABDA79F8EF76E3ACDD5F /* Localizable.strings */; };
|
||||
76D02BB22BFE7C9E0056008D /* Pods_alt_tab_macos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0712B3BEA2B3780398C0999 /* Pods_alt_tab_macos.framework */; };
|
||||
AA974BA929B7D84C0099A29E /* PreviewPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA974BA829B7D84C0099A29E /* PreviewPanel.swift */; };
|
||||
BF0C8052AE41B1B10E42BFCE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C875C983226CB16DBD90F /* InfoPlist.strings */; };
|
||||
BF0C807D26E465F467B066F7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C849EBA5A547912BD8BB9 /* Localizable.strings */; };
|
||||
BF0C812C068CD751CE9BFB67 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8D5993267A74D4875C1A /* Localizable.strings */; };
|
||||
@@ -173,6 +174,7 @@
|
||||
481FE54624D2D387001032F1 /* alt-tab-macos-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "alt-tab-macos-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
59DD4BE63D42EEFF1182BA7F /* Pods-alt-tab-macos.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-alt-tab-macos.release.xcconfig"; path = "Target Support Files/Pods-alt-tab-macos/Pods-alt-tab-macos.release.xcconfig"; sourceTree = "<group>"; };
|
||||
672F94799CC7C90282AEB3EA /* Pods-alt-tab-macos.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-alt-tab-macos.debug.xcconfig"; path = "Target Support Files/Pods-alt-tab-macos/Pods-alt-tab-macos.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
AA974BA829B7D84C0099A29E /* PreviewPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewPanel.swift; sourceTree = "<group>"; };
|
||||
BF0C80A05C11C8ADC366EC4A /* lb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = lb; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C8113492C0FFCB4454BC9 /* sl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sl; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C8118F91A00A04AD4DE26 /* bg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = bg; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
@@ -994,6 +996,7 @@
|
||||
D04BA1DF8CAB2FAB7FE9244B /* ThumbnailFontIconView.swift */,
|
||||
D04BA258B56193958D60978A /* ThumbnailView.swift */,
|
||||
D04BAA998119CAA8B70A2B67 /* ThumbnailsView.swift */,
|
||||
AA974BA829B7D84C0099A29E /* PreviewPanel.swift */,
|
||||
);
|
||||
path = "main-window";
|
||||
sourceTree = "<group>";
|
||||
@@ -1618,6 +1621,7 @@
|
||||
D04BA6187A91A847844B6ABB /* Window.swift in Sources */,
|
||||
D04BA737008AA2CD4E230A21 /* Application.swift in Sources */,
|
||||
D04BA2A6FF9DDDC5A1A68E36 /* Applications.swift in Sources */,
|
||||
AA974BA929B7D84C0099A29E /* PreviewPanel.swift in Sources */,
|
||||
D04BA3CF766857381519B892 /* BackgroundWork.swift in Sources */,
|
||||
D04BA48B00B4211A465C7337 /* DebugProfile.swift in Sources */,
|
||||
D04BAB68B7B8D1B548BC3AD5 /* App.swift in Sources */,
|
||||
|
||||
@@ -180,3 +180,4 @@ They helped [localize the app](https://poeditor.com/join/project/8AOEZ0eAZE):
|
||||
* Yukai
|
||||
* yumechan
|
||||
* Yusuf Caliskan
|
||||
* Ивайло
|
||||
@@ -232,6 +232,9 @@
|
||||
/* Menubar option */
|
||||
"Preferences…" = "Preferences…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Quit" = "Quit";
|
||||
|
||||
|
||||
@@ -250,6 +250,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "التفضيلات…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "إغلاق";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Настройки...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Излез";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "পছন্দ…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "প্রস্থান করুন";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferències...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Sortir";
|
||||
|
||||
|
||||
@@ -253,6 +253,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Nastavení...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Zavřít";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferences…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Quit";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Einstellungen…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Beenden";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Προτιμήσεις...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Εγκατάλειψη";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferences…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Quit";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferencias…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Salir";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferences…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Quit";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "ترجیحات...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Quit";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Asetukset…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Lopeta";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Préférences…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Quitter";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferencias...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Saír";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "העדפות";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "צא";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "पसंद";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "बंद करो";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Beállítások…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Kilépés";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferensi…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Keluar";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferenze…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Esci";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "環境設定…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "終了";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "설정…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "종료";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Taybetmendî";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Jêderkeve";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Astellung…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Quit";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Voorkeuren…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Stop";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Valg…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Avslutt";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferencje…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Wyjdź";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferências…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Encerrar";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferências…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Sair";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferințe…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Ieșire";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Настройки…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Выход";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Nastavenia…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Ukončiť";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Nastavitve…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Quit";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Preferencat";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Dil";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Podešavanja…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Zatvori";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Inställningar...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Avsluta";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Tercihler…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Çıkış";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Налаштування...";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Вийти";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "Tuỳ chỉnh";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "Thoát";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "偏好设置…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "退出";
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
/*No comment provided by engineer.*/
|
||||
"Preferences…" = "偏好設定…";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Preview selected window:" = "Preview selected window:";
|
||||
|
||||
/*No comment provided by engineer.*/
|
||||
"Quit" = "離開";
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ extension CGWindowID {
|
||||
return CGSCopySpacesForWindows(cgsMainConnectionId, CGSSpaceMask.all.rawValue, [self] as CFArray) as! [CGSSpaceID]
|
||||
}
|
||||
|
||||
func screenshot() -> CGImage? {
|
||||
func screenshot(_ bestResolution: Bool = false) -> CGImage? {
|
||||
// CGSHWCaptureWindowList
|
||||
var windowId_ = self
|
||||
let list = CGSHWCaptureWindowList(cgsMainConnectionId, &windowId_, 1, [.ignoreGlobalClipShape, .nominalResolution]).takeRetainedValue() as! [CGImage]
|
||||
let list = CGSHWCaptureWindowList(cgsMainConnectionId, &windowId_, 1, [.ignoreGlobalClipShape, bestResolution ? .bestResolution : .nominalResolution]).takeRetainedValue() as! [CGImage]
|
||||
return list.first
|
||||
|
||||
// // CGWindowListCreateImage
|
||||
|
||||
@@ -87,6 +87,7 @@ class Preferences {
|
||||
"hideAppBadges": "false",
|
||||
"hideWindowlessApps": "false",
|
||||
"hideThumbnails": "false",
|
||||
"previewFocusedWindow": "false",
|
||||
]
|
||||
|
||||
// system preferences
|
||||
@@ -130,6 +131,7 @@ class Preferences {
|
||||
static var hideThumbnails: Bool { defaults.bool("hideThumbnails") }
|
||||
static var startAtLogin: Bool { defaults.bool("startAtLogin") }
|
||||
static var blacklist: [BlacklistEntry] { jsonDecode([BlacklistEntry].self, defaults.string("blacklist")) }
|
||||
static var previewFocusedWindow: Bool { defaults.bool("previewFocusedWindow") }
|
||||
|
||||
// macro values
|
||||
static var theme: ThemePreference { defaults.macroPref("theme", ThemePreference.allCases) }
|
||||
|
||||
+15
-3
@@ -93,12 +93,24 @@ class Window {
|
||||
}
|
||||
CFRunLoopAddSource(BackgroundWork.accessibilityEventsThread.runLoop, AXObserverGetRunLoopSource(axObserver), .defaultMode)
|
||||
}
|
||||
|
||||
private func screenshot(_ bestResolution: Bool = false) -> NSImage? {
|
||||
guard !isWindowlessApp, let cgWindowId = cgWindowId, cgWindowId != -1, let cgImage = cgWindowId.screenshot(bestResolution) else {
|
||||
return nil
|
||||
}
|
||||
return NSImage(cgImage: cgImage, size: NSSize(width: cgImage.width, height: cgImage.height))
|
||||
}
|
||||
|
||||
func refreshThumbnail() {
|
||||
if !isWindowlessApp, let cgWindowId = cgWindowId, cgWindowId != -1, let cgImage = cgWindowId.screenshot() {
|
||||
thumbnail = NSImage(cgImage: cgImage, size: NSSize(width: cgImage.width, height: cgImage.height))
|
||||
thumbnailFullSize = thumbnail!.size
|
||||
guard let screenshot = screenshot() else {
|
||||
return
|
||||
}
|
||||
thumbnail = screenshot
|
||||
thumbnailFullSize = thumbnail!.size
|
||||
}
|
||||
|
||||
func getPreview() -> NSImage? {
|
||||
return screenshot(true)
|
||||
}
|
||||
|
||||
func canBeClosed() -> Bool {
|
||||
|
||||
+24
-4
@@ -36,11 +36,11 @@ class Windows {
|
||||
if let app = Applications.find(NSWorkspace.shared.frontmostApplication?.processIdentifier),
|
||||
app.focusedWindow == nil,
|
||||
let lastFocusedWindowIndex = getLastFocusedWindowIndex() {
|
||||
updateHoveredAndFocusedWindowIndexes(lastFocusedWindowIndex)
|
||||
updateFocusedAndHoveredWindowIndex(lastFocusedWindowIndex)
|
||||
} else {
|
||||
cycleFocusedWindowIndex(1)
|
||||
if focusedWindowIndex == 0 {
|
||||
updateHoveredAndFocusedWindowIndexes(0)
|
||||
updateFocusedAndHoveredWindowIndex(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class Windows {
|
||||
return nil
|
||||
}
|
||||
|
||||
static func updateHoveredAndFocusedWindowIndexes(_ newIndex: Int, _ fromMouse: Bool = false) {
|
||||
static func updateFocusedAndHoveredWindowIndex(_ newIndex: Int, _ fromMouse: Bool = false) {
|
||||
var index: Int?
|
||||
if fromMouse && newIndex != hoveredWindowIndex {
|
||||
let oldIndex = hoveredWindowIndex
|
||||
@@ -113,6 +113,7 @@ class Windows {
|
||||
let oldIndex = focusedWindowIndex
|
||||
focusedWindowIndex = newIndex
|
||||
ThumbnailsView.highlight(oldIndex)
|
||||
previewFocusedWindowIfNeeded()
|
||||
index = focusedWindowIndex
|
||||
}
|
||||
guard let index = index else { return }
|
||||
@@ -121,6 +122,25 @@ class Windows {
|
||||
App.app.thumbnailsPanel.thumbnailsView.scrollView.contentView.scrollToVisible(focusedView.frame)
|
||||
voiceOverWindow(index)
|
||||
}
|
||||
|
||||
static func previewFocusedWindowIfNeeded() {
|
||||
guard
|
||||
Preferences.previewFocusedWindow,
|
||||
App.app.appIsBeingUsed && App.app.thumbnailsPanel.isKeyWindow,
|
||||
let window = focusedWindow(),
|
||||
let preview = window.getPreview(),
|
||||
let position = window.position,
|
||||
let size = window.size
|
||||
else {
|
||||
App.app.previewPanel.orderOut(nil)
|
||||
return
|
||||
}
|
||||
App.app.previewPanel.setPreview(preview)
|
||||
var frame = NSRect(origin: position, size: size)
|
||||
frame.origin.y = NSScreen.screens[0].frame.maxY - frame.maxY
|
||||
App.app.previewPanel.setFrame(frame, display: false)
|
||||
App.app.previewPanel.order(.below, relativeTo: App.app.thumbnailsPanel.windowNumber)
|
||||
}
|
||||
|
||||
static func voiceOverWindow(_ windowIndex: Int = focusedWindowIndex) {
|
||||
guard App.app.appIsBeingUsed && App.app.thumbnailsPanel.isKeyWindow else { return }
|
||||
@@ -144,7 +164,7 @@ class Windows {
|
||||
(KeyRepeatTimer.isARepeat || KeyRepeatTimer.timer?.isValid ?? false) {
|
||||
return
|
||||
}
|
||||
updateHoveredAndFocusedWindowIndexes(nextIndex)
|
||||
updateFocusedAndHoveredWindowIndex(nextIndex)
|
||||
}
|
||||
|
||||
static func windowIndexAfterCycling(_ step: Int) -> Int {
|
||||
|
||||
@@ -17,6 +17,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
static let repository = "https://github.com/lwouis/alt-tab-macos"
|
||||
static var app: App!
|
||||
var thumbnailsPanel: ThumbnailsPanel!
|
||||
var previewPanel: PreviewPanel!
|
||||
var preferencesWindow: PreferencesWindow!
|
||||
var feedbackWindow: FeedbackWindow!
|
||||
var isFirstSummon = true
|
||||
@@ -55,6 +56,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
Menubar.initialize()
|
||||
self.loadMainMenuXib()
|
||||
self.thumbnailsPanel = ThumbnailsPanel()
|
||||
self.previewPanel = PreviewPanel()
|
||||
Spaces.initialDiscovery()
|
||||
Applications.initialDiscovery()
|
||||
self.preferencesWindow = PreferencesWindow()
|
||||
@@ -113,6 +115,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
isFirstSummon = true
|
||||
MouseEvents.toggle(false)
|
||||
hideThumbnailPanelWithoutChangingKeyWindow()
|
||||
previewPanel.orderOut(nil)
|
||||
hideAllTooltips()
|
||||
}
|
||||
|
||||
@@ -295,6 +298,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
refreshOpenUi()
|
||||
guard appIsBeingUsed else { return }
|
||||
thumbnailsPanel.show()
|
||||
Windows.previewFocusedWindowIfNeeded()
|
||||
guard appIsBeingUsed else { return }
|
||||
Windows.refreshThumbnailsAsync(screen)
|
||||
guard appIsBeingUsed else { return }
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import Cocoa
|
||||
|
||||
class PreviewPanel: NSPanel {
|
||||
private let previewView = NSImageView()
|
||||
private let borderView = BorderView()
|
||||
|
||||
convenience init() {
|
||||
self.init(contentRect: .zero, styleMask: [.nonactivatingPanel, .titled, .fullSizeContentView], backing: .buffered, defer: false)
|
||||
isFloatingPanel = true
|
||||
animationBehavior = .none
|
||||
hidesOnDeactivate = false
|
||||
titleVisibility = .hidden
|
||||
titlebarAppearsTransparent = true
|
||||
backgroundColor = .clear
|
||||
contentView = previewView
|
||||
borderView.autoresizingMask = [.width, .height]
|
||||
previewView.addSubview(borderView)
|
||||
// triggering AltTab before or during Space transition animation brings the window on the Space post-transition
|
||||
collectionBehavior = .canJoinAllSpaces
|
||||
// 2nd highest level possible; this allows the app to go on top of context menus
|
||||
// highest level is .screenSaver but makes drag and drop on top the main window impossible
|
||||
level = .popUpMenu
|
||||
// helps filter out this window from the thumbnails
|
||||
setAccessibilitySubrole(.unknown)
|
||||
}
|
||||
|
||||
func setPreview(_ preview: NSImage) {
|
||||
previewView.image = preview
|
||||
}
|
||||
}
|
||||
|
||||
private class BorderView: NSView {
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
let path = NSBezierPath(rect: bounds)
|
||||
path.append(NSBezierPath(roundedRect: bounds.insetBy(dx: 5, dy: 5), xRadius: 5, yRadius: 5).reversed)
|
||||
systemAccentColor().withAlphaComponent(0.5).setFill()
|
||||
path.fill()
|
||||
}
|
||||
}
|
||||
|
||||
func systemAccentColor() -> NSColor {
|
||||
if #available(OSX 10.14, *) {
|
||||
// dynamically adapts to changes in System Default; no need to listen to notifications
|
||||
return NSColor.controlAccentColor
|
||||
}
|
||||
return NSColor(srgbRed: 0, green: 0.47843137254901963, blue: 1, alpha: 1)
|
||||
}
|
||||
@@ -187,7 +187,7 @@ class ThumbnailView: NSStackView {
|
||||
windowlessIcon.needsDisplay = true
|
||||
}
|
||||
self.mouseUpCallback = { () -> Void in App.app.focusSelectedWindow(element) }
|
||||
self.mouseMovedCallback = { () -> Void in Windows.updateHoveredAndFocusedWindowIndexes(index, true) }
|
||||
self.mouseMovedCallback = { () -> Void in Windows.updateFocusedAndHoveredWindowIndex(index, true) }
|
||||
[quitIcon, closeIcon, minimizeIcon, maximizeIcon].forEach { $0.window_ = element }
|
||||
showOrHideWindowControls(false)
|
||||
// force a display to avoid flickering; see https://github.com/lwouis/alt-tab-macos/issues/197
|
||||
|
||||
@@ -71,7 +71,7 @@ class ThumbnailsView: NSVisualEffectView {
|
||||
return leadingSide ? NSMinX($0.frame) < originCenter : NSMaxX($0.frame) > originCenter
|
||||
} ?? iterable.last!
|
||||
let targetIndex = ThumbnailsView.recycledViews.firstIndex(of: targetView)!
|
||||
Windows.updateHoveredAndFocusedWindowIndexes(targetIndex)
|
||||
Windows.updateFocusedAndHoveredWindowIndex(targetIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ class AppearanceTab {
|
||||
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide colored circles on mouse hover:", comment: ""), "hideColoredCircles"),
|
||||
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide app badges:", comment: ""), "hideAppBadges"),
|
||||
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide apps with no open window:", comment: ""), "hideWindowlessApps"),
|
||||
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Preview selected window:", comment: ""), "previewFocusedWindow"),
|
||||
])
|
||||
grid.column(at: 0).xPlacement = .trailing
|
||||
grid.fit()
|
||||
|
||||
Reference in new issue
Block a user