feat: new preference to hide thumbnails (closes #384)

This commit is contained in:
Louis Pontoise authored and lwouis committed 2020-09-05 04:01:32 +09:00
1 parent df3010a3c8
commit 877c93c8a2
9 files changed
+46 -37

No files matched your search

+3 -3
View File
@@ -64,9 +64,9 @@ class Application: NSObject {
func addAndObserveWindows() {
if runningApplication.isFinishedLaunching && runningApplication.activationPolicy != .prohibited && axUiElement == nil {
axUiElement = AXUIElementCreateApplication(runningApplication.processIdentifier)
AXObserverCreate(runningApplication.processIdentifier, axObserverCallback, &axObserver)
debugPrint("Adding app", runningApplication.processIdentifier, runningApplication.bundleIdentifier ?? "nil")
axUiElement = AXUIElementCreateApplication(pid)
AXObserverCreate(pid, axObserverCallback, &axObserver)
debugPrint("Adding app", pid, runningApplication.bundleIdentifier ?? "nil")
observeEvents()
}
}
+2 -1
View File
@@ -60,6 +60,7 @@ class Preferences {
"shortcutStyle": "0",
"hideAppBadges": "false",
"hideWindowlessApps": "false",
"hideThumbnails": "false",
]
// constant values
@@ -69,7 +70,6 @@ class Preferences {
static var windowPadding: CGFloat { 18 }
static var interCellPadding: CGFloat { 5 }
static var intraCellPadding: CGFloat { 5 }
static var fontIconSize: CGFloat { 20 }
// persisted values
static var maxScreenUsage: CGFloat { defaults.cgfloat("maxScreenUsage") / CGFloat(100) }
@@ -100,6 +100,7 @@ class Preferences {
static var hideStatusIcons: Bool { defaults.bool("hideStatusIcons") }
static var hideAppBadges: Bool { defaults.bool("hideAppBadges") }
static var hideWindowlessApps: Bool { defaults.bool("hideWindowlessApps") }
static var hideThumbnails: Bool { defaults.bool("hideThumbnails") }
static var startAtLogin: Bool { defaults.bool("startAtLogin") }
static var dontShowBlacklist: [String] { blacklistStringToArray(defaults.string("dontShowBlacklist")) }
static var disableShortcutsBlacklist: [String] { blacklistStringToArray(defaults.string("disableShortcutsBlacklist")) }
+1 -1
View File
@@ -152,7 +152,7 @@ class Window {
}
func focus() {
if application.runningApplication.processIdentifier == ProcessInfo.processInfo.processIdentifier {
if application.pid == ProcessInfo.processInfo.processIdentifier {
App.app.showSecondaryWindow(App.app.window(withWindowNumber: Int(cgWindowId)))
} else if isWindowlessApp {
if let bundleID = application.runningApplication.bundleIdentifier {
+2
View File
@@ -87,6 +87,7 @@ class Windows {
}
static func refreshFirstFewThumbnailsSync() {
if Preferences.hideThumbnails { return }
list.filter { $0.shouldShowTheUser }
.prefix(criticalFirstThumbnails)
.forEachAsync { window in window.refreshThumbnail() }
@@ -94,6 +95,7 @@ class Windows {
static func refreshThumbnailsAsync(_ screen: NSScreen, _ currentIndex: Int = criticalFirstThumbnails) {
guard App.app.appIsBeingUsed else { return }
if Preferences.hideThumbnails { return }
BackgroundWork.mainQueueConcurrentWorkQueue.async {
if currentIndex < list.count {
let window = list[currentIndex]
@@ -27,11 +27,11 @@ class FontIcon: BaseLabel {
// Font icon using SF Symbols from the SF Pro font from Apple
// see https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/
class ThumbnailFontIconView: ThumbnailTitleView {
convenience init(_ symbol: Symbols, _ size: CGFloat = Preferences.fontIconSize, _ color: NSColor = .white, _ shadow: NSShadow? = ThumbnailView.makeShadow(.darkGray)) {
// This helps SF symbols display vertically centered and not clipped at the bottom
self.init(size, 3, shadow: shadow)
convenience init(_ symbol: Symbols, _ size: CGFloat = Preferences.fontHeight, _ color: NSColor = .white, _ shadow: NSShadow? = ThumbnailView.makeShadow(.darkGray)) {
self.init(size, shadow)
string = symbol.rawValue
font = NSFont(name: "SF Pro Text", size: size)
// This helps SF symbols display vertically centered and not clipped at the top
font = NSFont(name: "SF Pro Text", size: (size * 0.85).rounded())
textColor = color
// This helps SF symbols not be clipped on the right
widthAnchor.constraint(equalToConstant: size * 1.15).isActive = true
@@ -62,15 +62,13 @@ class ThumbnailFontIconView: ThumbnailTitleView {
}
class ThumbnailFilledFontIconView: NSView {
convenience init(_ thumbnailFontIconView: ThumbnailFontIconView, _ backgroundColor: NSColor, _ offset: Bool = false) {
convenience init(_ thumbnailFontIconView: ThumbnailFontIconView, _ backgroundColor: NSColor) {
self.init(frame: .zero)
translatesAutoresizingMaskIntoConstraints = false
let backgroundView = ThumbnailFontIconView(.filledCircled, thumbnailFontIconView.font!.pointSize - (offset ? 2 : 0), backgroundColor)
let backgroundView = ThumbnailFontIconView(.filledCircled, 14 - 2, backgroundColor, nil)
addSubview(backgroundView)
addSubview(thumbnailFontIconView, positioned: .above, relativeTo: nil)
if offset {
backgroundView.leftAnchor.constraint(equalTo: backgroundView.superview!.leftAnchor, constant: 1).isActive = true
}
backgroundView.frame.origin = CGPoint(x: backgroundView.frame.origin.x + 1, y: backgroundView.frame.origin.y + 1)
fit(thumbnailFontIconView.fittingSize.width, thumbnailFontIconView.fittingSize.height)
}
}
+4 -7
View File
@@ -1,9 +1,7 @@
import Cocoa
class ThumbnailTitleView: BaseLabel {
var magicOffset = CGFloat(0)
convenience init(_ size: CGFloat, _ magicOffset: CGFloat = 0, shadow: NSShadow? = ThumbnailView.makeShadow(.darkGray)) {
convenience init(_ size: CGFloat, _ shadow: NSShadow? = ThumbnailView.makeShadow(.darkGray)) {
let textStorage = NSTextStorage()
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
@@ -13,18 +11,17 @@ class ThumbnailTitleView: BaseLabel {
layoutManager.addTextContainer(textContainer)
self.init(NSRect.zero, textContainer)
font = Preferences.font
self.magicOffset = magicOffset
textColor = Preferences.fontColor
self.shadow = shadow
defaultParagraphStyle = makeParagraphStyle(size)
heightAnchor.constraint(equalToConstant: size + magicOffset).isActive = true
heightAnchor.constraint(equalToConstant: size).isActive = true
}
private func makeParagraphStyle(_ size: CGFloat) -> NSMutableParagraphStyle {
let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
paragraphStyle.lineBreakMode = getTruncationMode()
paragraphStyle.maximumLineHeight = size + magicOffset
paragraphStyle.minimumLineHeight = size + magicOffset
paragraphStyle.maximumLineHeight = size
paragraphStyle.minimumLineHeight = size
paragraphStyle.allowsDefaultTighteningForTruncation = false
return paragraphStyle
}
+17 -14
View File
@@ -9,7 +9,7 @@ class ThumbnailView: NSStackView {
var minimizedIcon = ThumbnailFontIconView(.circledMinusSign)
var hiddenIcon = ThumbnailFontIconView(.circledSlashSign)
var spaceIcon = ThumbnailFontIconView(.circledNumber0)
var dockLabelIcon = ThumbnailFilledFontIconView(ThumbnailFontIconView(.filledCircledNumber0, (Preferences.fontIconSize * 0.7).rounded(), NSColor(srgbRed: 1, green: 0.30, blue: 0.25, alpha: 1), nil), NSColor.white, true)
var dockLabelIcon = ThumbnailFilledFontIconView(ThumbnailFontIconView(.filledCircledNumber0, 14, NSColor(srgbRed: 1, green: 0.30, blue: 0.25, alpha: 1), nil), NSColor.white)
var closeIcon = WindowControlView("close", 16)
var minimizeIcon = WindowControlView("minimize", 16)
var maximizeIcon = WindowControlView("fullscreen", 16)
@@ -36,12 +36,10 @@ class ThumbnailView: NSStackView {
layer!.borderWidth = Preferences.cellBorderWidth
edgeInsets = NSEdgeInsets(top: Preferences.intraCellPadding, left: Preferences.intraCellPadding, bottom: Preferences.intraCellPadding, right: Preferences.intraCellPadding)
orientation = .vertical
spacing = Preferences.intraCellPadding
let shadow = ThumbnailView.makeShadow(.gray)
thumbnail.shadow = shadow
appIcon.shadow = shadow
hStackView = NSStackView(views: [appIcon, label, hiddenIcon, fullscreenIcon, minimizedIcon, spaceIcon])
hStackView.spacing = Preferences.intraCellPadding
setViews([hStackView, thumbnail], in: .leading)
addWindowControls()
addDockLabelIcon()
@@ -70,7 +68,7 @@ class ThumbnailView: NSStackView {
if let shouldShowWindowControls = shouldShowWindowControls_ {
self.shouldShowWindowControls = shouldShowWindowControls
}
let shouldShow = shouldShowWindowControls && isHighlighted && !Preferences.hideColoredCircles && !window_!.isWindowlessApp
let shouldShow = shouldShowWindowControls && isHighlighted && !Preferences.hideColoredCircles && !window_!.isWindowlessApp && !Preferences.hideThumbnails
if isShowingWindowControls != shouldShow {
isShowingWindowControls = shouldShow
[closeIcon, minimizeIcon, maximizeIcon].forEach { $0.isHidden = !shouldShow }
@@ -101,14 +99,19 @@ class ThumbnailView: NSStackView {
func updateRecycledCellWithNewContent(_ element: Window, _ index: Int, _ newHeight: CGFloat, _ screen: NSScreen) {
window_ = element
thumbnail.image = element.thumbnail
if let image = thumbnail.image {
image.size = element.thumbnailFullSize!
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
}
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
assignIfDifferent(&spacing, Preferences.hideThumbnails ? 0 : Preferences.intraCellPadding)
assignIfDifferent(&hStackView.spacing, Preferences.fontHeight == 0 ? 0 : Preferences.intraCellPadding)
if appIcon.image != element.icon {
appIcon.image = element.icon
let appIconSize = NSSize(width: Preferences.iconSize, height: Preferences.iconSize)
@@ -142,11 +145,11 @@ class ThumbnailView: NSStackView {
}
dockLabelIcon.setFrameOrigin(NSPoint(x: appIcon.frame.maxX - dockLabelIcon.fittingSize.width - 1, y: appIcon.frame.maxY - dockLabelIcon.fittingSize.height + 4))
}
assignIfDifferent(&frame.size.width, max(thumbnail.frame.size.width + Preferences.intraCellPadding * 2, ThumbnailView.widthMin(screen)))
assignIfDifferent(&frame.size.width, max((Preferences.hideThumbnails ? hStackView.fittingSize.width : thumbnail.frame.size.width) + Preferences.intraCellPadding * 2, ThumbnailView.widthMin(screen)))
assignIfDifferent(&frame.size.height, newHeight)
let fontIconWidth = CGFloat([fullscreenIcon, minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontIconSize + Preferences.intraCellPadding)
let fontIconWidth = CGFloat([fullscreenIcon, minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontHeight + Preferences.intraCellPadding)
assignIfDifferent(&label.textContainer!.size.width, frame.width - Preferences.iconSize - Preferences.intraCellPadding * 3 - fontIconWidth)
assignIfDifferent(&windowlessIcon.isHidden, !element.isWindowlessApp)
assignIfDifferent(&windowlessIcon.isHidden, !element.isWindowlessApp || Preferences.hideThumbnails)
if element.isWindowlessApp {
let maxWidth = (ThumbnailView.widthMin(screen) - Preferences.intraCellPadding * 2).rounded()
let maxHeight = ((ThumbnailView.height(screen) - hStackView.fittingSize.height) - Preferences.intraCellPadding * 2).rounded()
+8 -1
View File
@@ -51,8 +51,15 @@ class ThumbnailsView: NSVisualEffectView {
}
}
func rowHeight(_ screen: NSScreen) -> CGFloat {
if Preferences.hideThumbnails {
return max(Preferences.iconSize, Preferences.fontHeight + 3) + Preferences.intraCellPadding * 2
}
return ThumbnailView.height(screen).rounded(.down)
}
private func layoutThumbnailViews(_ screen: NSScreen, _ widthMax: CGFloat) -> (CGFloat, CGFloat)? {
let height = ThumbnailView.height(screen).rounded(.down)
let height = rowHeight(screen)
let isLeftToRight = App.shared.userInterfaceLayoutDirection == .leftToRight
let startingX = isLeftToRight ? Preferences.interCellPadding : widthMax - Preferences.interCellPadding
var currentX = startingX
@@ -9,7 +9,7 @@ class AppearanceTab {
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Rows of windows:", comment: ""), "rowsCount", 1, 20, 20, true),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Min windows per row:", comment: ""), "minCellsPerRow", 1, 20, 20, true),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Max windows per row:", comment: ""), "maxCellsPerRow", 1, 40, 20, true),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Window app icon size:", comment: ""), "iconSize", 0, 64, 11, false, "px"),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Window app icon size:", comment: ""), "iconSize", 0, 128, 11, false, "px"),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Window title font size:", comment: ""), "fontHeight", 0, 64, 11, false, "px"),
LabelAndControl.makeLabelWithDropdown(NSLocalizedString("Window title truncation:", comment: ""), "titleTruncation", TitleTruncationPreference.allCases),
LabelAndControl.makeLabelWithDropdown(NSLocalizedString("Show on:", comment: ""), "showOnScreen", ShowOnScreenPreference.allCases),
@@ -21,6 +21,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("Hide window thumbnails:", comment: ""), "hideThumbnails"),
])
grid.column(at: 0).xPlacement = .trailing
grid.rowAlignment = .lastBaseline