feat: titles appearance now resizes for better readability

parts of #3882

also fixed a display of titles in every appearance, especially on first display of the switcher ui
This commit is contained in:
lwouis committed 2025-11-10 20:48:57 +01:00
1 parent 15a55e6e07
commit 26d40e1149
5 files changed
+55 -16

No files matched your search

-9
View File
@@ -193,15 +193,6 @@ extension DispatchQoS {
}
}
extension NSTextField {
func setWidth(_ width: CGFloat) {
frame.size.width = width
// TODO: NSTextField does some internal magic, and ends up with constraints. We need to add our own to force its size
// I wish there was a better way to only set the frame.size
addOrUpdateConstraint(widthAnchor, width)
}
}
extension NSImage {
func appIconFixedSize(_ size: NSSize) -> CGImage? {
var rect = NSRect(origin: .zero, size: size)
+1 -2
View File
@@ -37,7 +37,7 @@ class Appearance {
// derived
static var font: NSFont {
if #available(macOS 26.0, *) {
return NSFont.systemFont(ofSize: fontHeight, weight: .semibold)
return NSFont.systemFont(ofSize: fontHeight, weight: currentStyle == .appIcons ? .semibold : .medium)
}
return NSFont.systemFont(ofSize: fontHeight)
}
@@ -155,7 +155,6 @@ class Appearance {
windowCornerRadius = 23
cellCornerRadius = 10
edgeInsetsSize = 7
maxWidthOnScreen = isHorizontalScreen ? 0.6 : 0.8
windowMinWidthInRow = 0.6
windowMaxWidthInRow = 0.9
rowsCount = 1
@@ -5,6 +5,8 @@ class ThumbnailTitleView: NSTextField {
self.init(labelWithString: "")
self.font = font
textColor = Appearance.fontColor
// drawsBackground = true
// backgroundColor = .red
allowsDefaultTighteningForTruncation = false
translatesAutoresizingMaskIntoConstraints = false
}
@@ -13,6 +15,19 @@ class ThumbnailTitleView: NSTextField {
heightAnchor.constraint(equalToConstant: fittingSize.height).isActive = true
}
func setWidth(_ width: CGFloat) {
frame.size.width = width
// TODO: NSTextField does some internal magic, and ends up with constraints.
// we can't use addOrUpdateConstraint for some reason, otherwise it will only actually apply after the UI is shown twice
// i tried everything and ended up removing all constraints then adding a fresh one. This seems to work
let toRemove = constraints.filter {
($0.firstItem as? NSView) === self && $0.firstAttribute == .width ||
($0.secondItem as? NSView) === self && $0.secondAttribute == .width
}
toRemove.forEach { removeConstraint($0) }
widthAnchor.constraint(equalToConstant: width).isActive = true
}
override func mouseMoved(with event: NSEvent) {
// no-op here prevents tooltips from disappearing on mouseMoved
}
+28 -5
View File
@@ -2,6 +2,8 @@ import Cocoa
class ThumbnailView: FlippedView {
static let noOpenWindowToolTip = NSLocalizedString("App is running but has no open window", comment: "")
// when calculating the width of a nstextfield, somehow we need to add this suffix to get the correct width
static let extraTextForPadding = "lmnopqrstuvw"
var window_: Window?
var thumbnail = LightImageView()
var windowlessIcon = LightImageView()
@@ -276,20 +278,19 @@ class ThumbnailView: FlippedView {
let availableRightWidth = view.isLastInRow ? 0 : CGFloat(view.numberOfViewsInRow - 1 - view.indexInRow) * viewWidth
let totalWidth = availableLeftWidth + availableRightWidth + viewWidth
let maxLabelWidth = min(totalWidth, maxAllowedWidth)
return maxLabelWidth - Appearance.intraCellPadding * 4
return maxLabelWidth - Appearance.intraCellPadding * 2
}
private func updateAppIconsLabelFrame(_ view: ThumbnailView) {
let viewWidth = view.frame.width
let labelWidth = view.label.fittingSize.width
let labelWidth = view.label.cell!.cellSize.width
let maxAllowedLabelWidth = getMaxAllowedLabelWidth(view)
let effectiveLabelWidth = max(min(labelWidth, maxAllowedLabelWidth), viewWidth)
var leftOffset = CGFloat(0)
var effectiveLabelWidth = max(min(labelWidth, maxAllowedLabelWidth), viewWidth)
- (view.isFirstInRow && view.isLastInRow ? 4 : (view.isFirstInRow || view.isLastInRow ? 2 : 0)) * Appearance.intraCellPadding
var leftOffset = -Appearance.intraCellPadding * 2
if view.isFirstInRow && view.isLastInRow {
leftOffset = -Appearance.intraCellPadding * 2
effectiveLabelWidth -= Appearance.intraCellPadding * 4
} else if view.isLastInRow {
leftOffset = max(0, effectiveLabelWidth - viewWidth + Appearance.intraCellPadding * 2)
} else if !view.isFirstInRow && !view.isLastInRow {
@@ -547,6 +548,28 @@ class ThumbnailView: FlippedView {
return ThumbnailsPanel.maxThumbnailsWidth() * Appearance.windowMaxWidthInRow - Appearance.interCellPadding * 2
}
static func widthOfComfortableReadability() -> CGFloat? {
let labTitleView = ThumbnailTitleView(font: Appearance.font)
labTitleView.stringValue = "abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijk" + extraTextForPadding
Logger.error(labTitleView.font)
return labTitleView.fittingSize.width
}
static func widthOfLongestTitle() -> CGFloat? {
let labTitleView = ThumbnailTitleView(font: Appearance.font)
var maxWidth = CGFloat(0)
for window in Windows.list {
guard window.shouldShowTheUser else { continue }
labTitleView.stringValue = window.title + extraTextForPadding
let width = labTitleView.fittingSize.width
if width > maxWidth {
maxWidth = width
}
}
guard maxWidth > 0 else { return nil }
return maxWidth
}
static func minThumbnailWidth() -> CGFloat {
return ThumbnailsPanel.maxThumbnailsWidth() * Appearance.windowMinWidthInRow - Appearance.interCellPadding * 2
}
+11
View File
@@ -61,6 +61,17 @@ class ThumbnailsPanel: NSPanel {
}
static func maxThumbnailsWidth() -> CGFloat {
if Preferences.appearanceStyle == .titles,
let readableWidth = ThumbnailView.widthOfComfortableReadability(),
let widthOfLongestTitle = ThumbnailView.widthOfLongestTitle() {
return (
min(
NSScreen.preferred.frame.width * Appearance.maxWidthOnScreen,
readableWidth + Appearance.intraCellPadding * 2 + Appearance.appIconLabelSpacing + Appearance.iconSize,
widthOfLongestTitle + Appearance.intraCellPadding * 2 + Appearance.appIconLabelSpacing + Appearance.iconSize
) - Appearance.windowPadding * 2
).rounded()
}
return (NSScreen.preferred.frame.width * Appearance.maxWidthOnScreen - Appearance.windowPadding * 2).rounded()
}