Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add anti aliasing support for thumbnails #705

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion resources/l10n/Localizable.strings
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* No comment provided by engineer. */
/* No comment provided by engineer. */
"About" = "About";

/* Menubar option. %@ is AltTab */
Expand Down Expand Up @@ -310,6 +310,9 @@
/* No comment provided by engineer. */
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Thumbnail Anti Aliasing:";

/* No comment provided by engineer. */
"Updates policy:" = "Updates policy:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/ar.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "إخفاء النوافذ المصغرة:";

/*No comment provided by engineer.*/
"Updates policy:" = "سياسة التحديثات:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Diese Erlaubnis is nötig um Bildschirmaufnahmen und Titel offener Fenster anzuzeigen";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Fenster-Miniaturansichten ausblenden:";

/*No comment provided by engineer.*/
"Updates policy:" = "Update Richtlinie:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Thumbnail Anti Aliasing:";

/*No comment provided by engineer.*/
"Updates policy:" = "Updates policy:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Este permiso es necesario para mostrar capturas de pantalla y títulos de ventanas abiertas";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Ocultar miniaturas de ventana:";

/*No comment provided by engineer.*/
"Updates policy:" = "Política de actualizaciones:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/fi.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Tarvitaan ikkunoiden otsikoiden ja pikkukuvien näyttämiseen";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Piilota ikkunan pikkukuvat:";

/*No comment provided by engineer.*/
"Updates policy:" = "Päivityspolitiikka:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Cette permission est nécessaire pour afficher les miniatures et titres des fenêtres ouvertes";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Masquer les miniatures de fenêtre:";

/*No comment provided by engineer.*/
"Updates policy:" = "Politique de mise-à-jour :";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/hu.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Ez a jogosultság ahhoz szükséges hogy megjeleníthessük a képernyőképeket és csempéket a nyitott ablakokhoz";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Az ablak miniatűrjeinek elrejtése:";

/*No comment provided by engineer.*/
"Updates policy:" = "Frissítési beállítások:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/id.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Izin ini diperlukan untuk menampilkan tangkapan layar dan judul jendela yang terbuka";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Sembunyikan thumbnail jendela:";

/*No comment provided by engineer.*/
"Updates policy:" = "Kebijakan pembaruan:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Nascondi le miniature delle finestre:";

/*No comment provided by engineer.*/
"Updates policy:" = "Politica sugli aggiornamenti:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "こちらの許可は、スクリーンショットと開いているウィンドウを表示するのに必要です。";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "ウィンドウのサムネイルを非表示にする:";

/*No comment provided by engineer.*/
"Updates policy:" = "アップデートポリシー:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/ko.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "이 권한은 윈도우의 이미지와 제목을 띄울 수 있게 해줍니다";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "창 축소판 숨기기:";

/*No comment provided by engineer.*/
"Updates policy:" = "업데이트 방법:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/nl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Deze permissie is nodig om screenshots en titels van geopende vensters te tonen";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Verberg vensterminiaturen:";

/*No comment provided by engineer.*/
"Updates policy:" = "Updatebeleid:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/no.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Denne tillatelsen er nødvendig for å kunne vise skjermbilde og tittel på åpne vinduer";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Skjul miniatyrbilder av vinduer:";

/*No comment provided by engineer.*/
"Updates policy:" = "Oppdateringspolicy:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/pl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "To uprawnienie jest potrzebne do wyświetlania zrzutów ekranu i tytułów otwartych okien";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Ukryj miniatury okien:";

/*No comment provided by engineer.*/
"Updates policy:" = "Zasady aktualizacji:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/pt-BR.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Esta permissão é necessária para exibir pré-visualizações e títulos das janelas abertas";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Ocultar miniaturas de janela:";

/*No comment provided by engineer.*/
"Updates policy:" = "Política de atualizações:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/pt.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Esta permissão é necessária para mostrar capturas de ecrã e títulos das janelas abertas";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Ocultar miniaturas de janela:";

/*No comment provided by engineer.*/
"Updates policy:" = "Regras de actualização:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/ru.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Это разрешение нужно для показа скриншотов и заголовков открытых окон";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Скрыть эскизы окон:";

/*No comment provided by engineer.*/
"Updates policy:" = "Правило обновлений:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/sk.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Toto povolenie je potrebné na zobrazovanie snímok obrazovky a názvov otvorených okien";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Skryť miniatúry okien:";

/*No comment provided by engineer.*/
"Updates policy:" = "Pravidlá aktualizácií:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/sl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Skrij sličice oken:";

/*No comment provided by engineer.*/
"Updates policy:" = "Politika posodobitev:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/tr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "Pencere küçük resimlerini gizle:";

/*No comment provided by engineer.*/
"Updates policy:" = "Güncelleme politikası:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/zh-CN.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "需要此权限以显示窗口截屏与标题";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "使用抗锯齿缩略图:";

/*No comment provided by engineer.*/
"Updates policy:" = "更新方式:";

Expand Down
3 changes: 3 additions & 0 deletions resources/l10n/zh-TW.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "需要取得此權限,才能顯示打開視窗的截圖與標題資訊";

/* No comment provided by engineer. */
"Thumbnail Anti Aliasing:" = "隱藏視窗縮圖:";

/*No comment provided by engineer.*/
"Updates policy:" = "更新策略:";

Expand Down
16 changes: 10 additions & 6 deletions src/api-wrappers/HelperExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ extension NSViewController {
}

extension NSImage {
func resizeToCopy(newSize: NSSize, interpolation : NSImageInterpolation = .default) -> NSImage {
let img = NSImage(size: newSize)
img.lockFocus()
NSGraphicsContext.current?.imageInterpolation = interpolation
draw(in: NSMakeRect(0, 0, newSize.width, newSize.height), from: NSMakeRect(0, 0, size.width, size.height), operation: .copy, fraction: 1)
img.unlockFocus()
return img
}

// NSImage(named) caches/reuses NSImage objects; we force separate instances of images by using copy()
static func initCopy(_ name: String) -> NSImage {
return NSImage(named: name)!.copy() as! NSImage
Expand All @@ -136,12 +145,7 @@ extension NSImage {
// copy and resize an image using high quality interpolation
static func initResizedCopy(_ name: String, _ width: CGFloat, _ height: CGFloat) -> NSImage {
let original = initCopy(name)
let img = NSImage(size: CGSize(width: width, height: height))
img.lockFocus()
NSGraphicsContext.current?.imageInterpolation = .high
original.draw(in: NSMakeRect(0, 0, width, height), from: NSMakeRect(0, 0, original.size.width, original.size.height), operation: .copy, fraction: 1)
img.unlockFocus()
return img
return original.resizeToCopy(newSize: CGSize(width: width, height: height), interpolation: .high)
}

func tinted(_ tint: NSColor) -> NSImage {
Expand Down
18 changes: 18 additions & 0 deletions src/logic/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class Preferences {
"hideAppBadges": "false",
"hideWindowlessApps": "false",
"hideThumbnails": "false",
"thumbnailAntiAliasing": ThumbnailAntiAliasingPreference.none.rawValue,
]

// constant values
Expand Down Expand Up @@ -119,6 +120,7 @@ class Preferences {
static var showFullscreenWindows: [ShowHowPreference] { ["showFullscreenWindows", "showFullscreenWindows2"].map { defaults.macroPref($0, ShowHowPreference.allCases) } }
static var shortcutStyle: [ShortcutStylePreference] { ["shortcutStyle", "shortcutStyle2"].map { defaults.macroPref($0, ShortcutStylePreference.allCases) } }
static var menubarIcon: MenubarIconPreference { defaults.macroPref("menubarIcon", MenubarIconPreference.allCases) }
static var thumbnailAntiAliasing: ThumbnailAntiAliasingPreference { defaults.macroPref("thumbnailAntiAliasing", ThumbnailAntiAliasingPreference.allCases) }

// derived values
static var cellBorderWidth: CGFloat { theme.themeParameters.cellBorderWidth }
Expand Down Expand Up @@ -390,6 +392,22 @@ enum AlignThumbnailsPreference: String, CaseIterable, MacroPreference {
}
}

enum ThumbnailAntiAliasingPreference: String, CaseIterable, MacroPreference {
case none = "0"
case low = "1"
case medium = "2"
case high = "3"

var localizedString: LocalizedString {
switch self {
case .none: return NSLocalizedString("None", comment: "")
case .low: return NSLocalizedString("Low", comment: "")
case .medium: return NSLocalizedString("Medium", comment: "")
case .high: return NSLocalizedString("High", comment: "")
}
}
}

enum ThemePreference: String, CaseIterable, MacroPreference {
case macOs = "0"
case windows10 = "1"
Expand Down
7 changes: 1 addition & 6 deletions src/logic/Windows.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,7 @@ class Windows {
window.refreshThumbnail()
DispatchQueue.main.async {
let view = ThumbnailsView.recycledViews[currentIndex]
if view.thumbnail.image != window.thumbnail {
let oldSize = view.thumbnail.frame.size
view.thumbnail.image = window.thumbnail
view.thumbnail.image?.size = oldSize
view.thumbnail.frame.size = oldSize
}
view.updateThumbnailIfNeeded(window.thumbnail)
}
}
refreshThumbnailsAsync(screen, currentIndex + 1)
Expand Down
36 changes: 31 additions & 5 deletions src/ui/main-window/ThumbnailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Cocoa
class ThumbnailView: NSStackView {
var window_: Window?
var thumbnail = NSImageView()
var thumbnailRaw = NSImage?(nil)
var appIcon = NSImageView()
var label = ThumbnailTitleView(Preferences.fontHeight)
var fullscreenIcon = ThumbnailFontIconView(.circledPlusSign)
Expand Down Expand Up @@ -97,18 +98,43 @@ class ThumbnailView: NSStackView {
edgeInsets.left = edgeInsets_
}

private func getThumbnailInterpolationLevel() -> NSImageInterpolation {
if Preferences.thumbnailAntiAliasing == .high {
return .high
}
if Preferences.thumbnailAntiAliasing == .medium {
return .medium
}
if Preferences.thumbnailAntiAliasing == .low {
return .low
}
return .none
}

func updateThumbnailIfNeeded(_ image: NSImage?)
{
if thumbnailRaw != image {
let effectSize = thumbnail.frame.size
thumbnailRaw = image
let thumbnailAntiAliasing = getThumbnailInterpolationLevel()
if thumbnailAntiAliasing == .none {
thumbnail.image = image
thumbnail.image?.size = effectSize
thumbnail.setFrameSize(effectSize)
} else {
thumbnail.image = thumbnailRaw?.resizeToCopy(newSize: effectSize, interpolation: thumbnailAntiAliasing)
}
}
}

func updateRecycledCellWithNewContent(_ element: Window, _ index: Int, _ newHeight: CGFloat, _ screen: NSScreen) {
window_ = element
assignIfDifferent(&thumbnail.isHidden, Preferences.hideThumbnails)
if !Preferences.hideThumbnails {
thumbnail.image = element.thumbnail
if let image = thumbnail.image {
image.size = element.thumbnailFullSize!
}
let (thumbnailWidth, thumbnailHeight) = ThumbnailView.thumbnailSize(element.thumbnail, screen)
let thumbnailSize = NSSize(width: thumbnailWidth.rounded(), height: thumbnailHeight.rounded())
thumbnail.image?.size = thumbnailSize
thumbnail.frame.size = thumbnailSize
updateThumbnailIfNeeded(element.thumbnail)
}
assignIfDifferent(&spacing, Preferences.hideThumbnails ? 0 : Preferences.intraCellPadding)
assignIfDifferent(&hStackView.spacing, Preferences.fontHeight == 0 ? 0 : Preferences.intraCellPadding)
Expand Down
1 change: 1 addition & 0 deletions src/ui/preferences-window/tabs/AppearanceTab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class AppearanceTab {
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Max width on screen:", comment: ""), "maxWidthOnScreen", 10, 100, 10, true, "%"),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Max height on screen:", comment: ""), "maxHeightOnScreen", 10, 100, 10, true, "%"),
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide window thumbnails:", comment: ""), "hideThumbnails", extraAction: { _ in toggleRowsCount() }),
LabelAndControl.makeLabelWithDropdown(NSLocalizedString("Thumbnail Anti Aliasing:", comment: ""), "thumbnailAntiAliasing", ThumbnailAntiAliasingPreference.allCases),
rowsCount,
minWidthInRow,
maxWidthInRow,
Expand Down