feat: better display on some external monitors (closes #3866)
This commit is contained in:
1 parent
b816745830
commit
165a6695b9
7 files changed
+128
-77
No files matched your search
@@ -70,7 +70,7 @@
|
||||
5F21C9E42C6E94700091F72F /* CustomizeStyleSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F21C9E32C6E94700091F72F /* CustomizeStyleSheet.swift */; };
|
||||
5F21C9E62C6E94920091F72F /* AnimationsSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F21C9E52C6E94920091F72F /* AnimationsSheet.swift */; };
|
||||
5F21C9E82C6E96A00091F72F /* SheetWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F21C9E72C6E96A00091F72F /* SheetWindow.swift */; };
|
||||
5F4753072CEE5A2E002C6C5E /* AppearanceUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8D57C86AF492D43A576D /* AppearanceUtils.swift */; };
|
||||
5F4753072CEE5A2E002C6C5E /* AppearanceTestable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8D57C86AF492D43A576D /* AppearanceTestable.swift */; };
|
||||
5F706EC02BA448B1004D542D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5F706EBE2BA448B1004D542D /* Localizable.strings */; };
|
||||
5F706EC32BA448D8004D542D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5F706EC12BA448D8004D542D /* InfoPlist.strings */; };
|
||||
76D02BB22BFE7C9E0056008D /* Pods_alt_tab_macos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0712B3BEA2B3780398C0999 /* Pods_alt_tab_macos.framework */; };
|
||||
@@ -86,7 +86,7 @@
|
||||
BF0C81A79128CF877FE895CC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8A48BBB3BF649864DB08 /* InfoPlist.strings */; };
|
||||
BF0C81B64A1205F066AC796A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C80404D3455D496C02F29 /* Localizable.strings */; };
|
||||
BF0C81D836A8A4CA393B135F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C82E55127D38ABF969CA0 /* InfoPlist.strings */; };
|
||||
BF0C81FA62D810342F59291A /* AppearanceUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C84933936C6FE676CD33C /* AppearanceUtilsTests.swift */; };
|
||||
BF0C81FA62D810342F59291A /* AppearanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C84933936C6FE676CD33C /* AppearanceTests.swift */; };
|
||||
BF0C8203D0EFEDEED0F908E8 /* ScreensEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C822D3BEDAB1F1C9F775E /* ScreensEvents.swift */; };
|
||||
BF0C820C6E89C2D90FA30A4B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8F67ABD271F26FA0EDEF /* Localizable.strings */; };
|
||||
BF0C8224CFD1ED511F3F0063 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8D94228D90FE99D4A3C8 /* Localizable.strings */; };
|
||||
@@ -116,7 +116,7 @@
|
||||
BF0C865E3C3F3B353A7A7CBC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C86FFF1C801761B7CE363 /* Localizable.strings */; };
|
||||
BF0C86BB79E417163E813179 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C80851C26EDB3DB98556C /* InfoPlist.strings */; };
|
||||
BF0C87732A6E660899D13BFD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C886B1D6E707E9E6BE46C /* InfoPlist.strings */; };
|
||||
BF0C8846AFEE2FFF93FAB36F /* AppearanceUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8D57C86AF492D43A576D /* AppearanceUtils.swift */; };
|
||||
BF0C8846AFEE2FFF93FAB36F /* AppearanceTestable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8D57C86AF492D43A576D /* AppearanceTestable.swift */; };
|
||||
BF0C884D88B74F05B8BBF956 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C88A25E1ED37E5F80AC91 /* Localizable.strings */; };
|
||||
BF0C8879F979414A87AB2958 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C89348E07FC05870FEE62 /* InfoPlist.strings */; };
|
||||
BF0C88C371B5550E7D23E4F1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8BF5835F97923BF3E8DA /* InfoPlist.strings */; };
|
||||
@@ -331,6 +331,7 @@
|
||||
5F706EC22BA448D8004D542D /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = InfoPlist.strings; 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>"; };
|
||||
BF0C8070A1BBA8B425C8EF34 /* IOKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IOKit.swift; sourceTree = "<group>"; };
|
||||
BF0C809C9DE36EA1317816FB /* nn */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = nn; path = Localizable.strings; 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>"; };
|
||||
@@ -362,7 +363,7 @@
|
||||
BF0C84674BAE2B4D7871B86C /* et */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = et; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C847A108ABC72723ABBA2 /* hi */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = hi; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C848A4DDFF5D118CA9CAF /* ca */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ca; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C84933936C6FE676CD33C /* AppearanceUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceUtilsTests.swift; sourceTree = "<group>"; };
|
||||
BF0C84933936C6FE676CD33C /* AppearanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceTests.swift; sourceTree = "<group>"; };
|
||||
BF0C84B9B7A41E4A4534E519 /* app-icons-style-full.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "app-icons-style-full.jpg"; sourceTree = "<group>"; };
|
||||
BF0C84E11784B3B0900D0963 /* app.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = app.icns; sourceTree = "<group>"; };
|
||||
BF0C850C46CCD8B978168CCD /* sv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sv; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
@@ -423,7 +424,7 @@
|
||||
BF0C8CE7BBC3B9B0CEC008FF /* vi */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = vi; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C8D3333653ACAEF730DD8 /* menubar-2@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menubar-2@2x.png"; sourceTree = "<group>"; };
|
||||
BF0C8D52C3D33B0669ECF996 /* ro */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ro; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C8D57C86AF492D43A576D /* AppearanceUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceUtils.swift; sourceTree = "<group>"; };
|
||||
BF0C8D57C86AF492D43A576D /* AppearanceTestable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceTestable.swift; sourceTree = "<group>"; };
|
||||
BF0C8D606B53D315F2D9927B /* KeyRepeatTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyRepeatTimer.swift; sourceTree = "<group>"; };
|
||||
BF0C8D7DE89E594FEE6DA692 /* ta */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ta; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C8D87C20B7308B16498B6 /* et */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = et; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
@@ -436,6 +437,7 @@
|
||||
BF0C8E54658B4DAEA0528200 /* menubar-3@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menubar-3@2x.png"; sourceTree = "<group>"; };
|
||||
BF0C8E5D2BD5F7F93DF77DF5 /* sk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sk; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C8E7B087DCC97A454C0AE /* uk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = uk; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
BF0C8EAF02309B9C489E65F4 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
BF0C8EC400A560FDF99F8C35 /* el */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = el; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C8EE17F3ABD7A6D44BFFE /* pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = pl; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
BF0C8FC083A2443F3EAF5DB7 /* preferences-blacklist.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "preferences-blacklist.jpg"; sourceTree = "<group>"; };
|
||||
@@ -854,6 +856,15 @@
|
||||
path = sl.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BF0C827B752F58F79EDB6B6C /* experimentations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BF0C8070A1BBA8B425C8EF34 /* IOKit.swift */,
|
||||
BF0C8EAF02309B9C489E65F4 /* README.md */,
|
||||
);
|
||||
path = experimentations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BF0C82D4A643500E81DB2965 /* ga.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -902,7 +913,7 @@
|
||||
BF0C8719351B41D268CE8B70 /* unit-tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BF0C84933936C6FE676CD33C /* AppearanceUtilsTests.swift */,
|
||||
BF0C84933936C6FE676CD33C /* AppearanceTests.swift */,
|
||||
);
|
||||
path = "unit-tests";
|
||||
sourceTree = "<group>";
|
||||
@@ -1112,7 +1123,7 @@
|
||||
BF0C8BA452332236D972C60E /* ATShortcut.swift */,
|
||||
1C961AC3633CD0C62CCE050E /* Appearance.swift */,
|
||||
BF0C8D606B53D315F2D9927B /* KeyRepeatTimer.swift */,
|
||||
BF0C8D57C86AF492D43A576D /* AppearanceUtils.swift */,
|
||||
BF0C8D57C86AF492D43A576D /* AppearanceTestable.swift */,
|
||||
);
|
||||
path = logic;
|
||||
sourceTree = "<group>";
|
||||
@@ -1376,6 +1387,7 @@
|
||||
D04BA70746DEEC3D30B43F81 /* main.swift */,
|
||||
D04BA0D80B24E72B9B981A1D /* logic */,
|
||||
D04BA229883E5D540D00232D /* ui */,
|
||||
BF0C827B752F58F79EDB6B6C /* experimentations */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
@@ -2124,8 +2136,8 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BF0C81FA62D810342F59291A /* AppearanceUtilsTests.swift in Sources */,
|
||||
5F4753072CEE5A2E002C6C5E /* AppearanceUtils.swift in Sources */,
|
||||
BF0C81FA62D810342F59291A /* AppearanceTests.swift in Sources */,
|
||||
5F4753072CEE5A2E002C6C5E /* AppearanceTestable.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2210,7 +2222,7 @@
|
||||
BF0C896B5D08B7DA8F2024AC /* KeyRepeatTimer.swift in Sources */,
|
||||
BF0C8249228867A3188E13F3 /* SystemAppearanceEvents.swift in Sources */,
|
||||
BF0C827A169F0DE86C8F12AD /* SystemScrollerStyleEvents.swift in Sources */,
|
||||
BF0C8846AFEE2FFF93FAB36F /* AppearanceUtils.swift in Sources */,
|
||||
BF0C8846AFEE2FFF93FAB36F /* AppearanceTestable.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -56,13 +56,13 @@ class Appearance {
|
||||
private static func updateSize() {
|
||||
let screen = NSScreen.preferred()
|
||||
let isHorizontalScreen = screen.isHorizontal()
|
||||
maxWidthOnScreen = AppearanceUtils.comfortableWidth(screen.physicalSize()!.width)
|
||||
maxWidthOnScreen = AppearanceTestable.comfortableWidth(screen.physicalSize().map { $0.width })
|
||||
if currentStyle == .appIcons {
|
||||
appIconsSize()
|
||||
} else if currentStyle == .titles {
|
||||
titlesSize(isHorizontalScreen)
|
||||
} else {
|
||||
thumbnailsSize(isHorizontalScreen)
|
||||
thumbnailsSize(isHorizontalScreen, screen)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ class Appearance {
|
||||
}
|
||||
}
|
||||
|
||||
private static func thumbnailsSize(_ isHorizontalScreen: Bool) {
|
||||
private static func thumbnailsSize(_ isHorizontalScreen: Bool, _ screen: NSScreen) {
|
||||
hideThumbnails = false
|
||||
windowPadding = 18
|
||||
cellCornerRadius = 10
|
||||
@@ -96,7 +96,8 @@ class Appearance {
|
||||
iconSize = 32
|
||||
fontHeight = 16
|
||||
}
|
||||
(windowMinWidthInRow, windowMaxWidthInRow) = goodValuesForThumbnailsWidthMinMax()
|
||||
let thumbnailsPanelRatio = (screen.frame.width * maxWidthOnScreen) / (screen.frame.height * maxHeightOnScreen)
|
||||
(windowMinWidthInRow, windowMaxWidthInRow) = AppearanceTestable.goodValuesForThumbnailsWidthMinMax(thumbnailsPanelRatio, rowsCount)
|
||||
if currentVisibility == .highest {
|
||||
edgeInsetsSize = 10
|
||||
cellCornerRadius = 12
|
||||
@@ -241,22 +242,4 @@ class Appearance {
|
||||
highlightBorderWidth = currentStyle == .titles ? 2 : 4
|
||||
}
|
||||
}
|
||||
|
||||
// calculate windowMinWidthInRow and windowMaxWidthInRow such that:
|
||||
// * fullscreen windows fill their tile vertically
|
||||
// * narrow windows have enough width that a few words can be read from their title
|
||||
private static func goodValuesForThumbnailsWidthMinMax() -> (CGFloat, CGFloat) {
|
||||
let aspectRatio = NSScreen.preferred().ratio()
|
||||
let minRatio: CGFloat
|
||||
let maxRatio: CGFloat
|
||||
if aspectRatio >= 1 {
|
||||
minRatio = 0.7 / (aspectRatio * rowsCount)
|
||||
maxRatio = 1.5 / (aspectRatio * rowsCount)
|
||||
} else {
|
||||
minRatio = 1.3 / rowsCount
|
||||
maxRatio = 2.1 / rowsCount
|
||||
}
|
||||
// Make sure the values are clamped between some reasonable bounds
|
||||
return (max(0.09, minRatio), min(0.3, maxRatio))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import Foundation
|
||||
|
||||
class AppearanceTestable {
|
||||
/// How wide should the ThumbnailsPanel be, for comfortable viewing?
|
||||
/// * a comfortable field-of-view is 50-60 degrees
|
||||
/// * people sit at various distances from the screen. We can't know how far they sit
|
||||
/// * most people will seat far enough so that they can view the whole width of the screen
|
||||
/// * some people use wide-screen or TV monitors. Those people tend to be too close to the screen, since they need to use keyboard and mouse on their desk
|
||||
/// Let's use this heuristic: let's assume that people can view 60cm comfortably. Bigger screens can only show parts of AltTab
|
||||
/// Let's clamp at 90% like Windows 11
|
||||
/// Let's clamp at 45% (value for the biggest, 60" screens)
|
||||
static func comfortableWidth(_ physicalWidth: Double?) -> Double {
|
||||
if let physicalWidth = physicalWidth {
|
||||
return min(0.9, max(0.45, 600.0 / physicalWidth))
|
||||
}
|
||||
return 0.9
|
||||
}
|
||||
|
||||
// calculate windowMinWidthInRow and windowMaxWidthInRow such that:
|
||||
// * fullscreen windows fill their tile vertically
|
||||
// * narrow windows have enough width that a few words can be read from their title
|
||||
static func goodValuesForThumbnailsWidthMinMax(_ aspectRatio: CGFloat, _ rowsCount: CGFloat) -> (CGFloat, CGFloat) {
|
||||
let minRatio: CGFloat
|
||||
let maxRatio: CGFloat
|
||||
if aspectRatio >= 1 {
|
||||
minRatio = 0.7 / (aspectRatio * rowsCount)
|
||||
maxRatio = 1.5 / (aspectRatio * rowsCount)
|
||||
} else {
|
||||
minRatio = 1.3 / rowsCount
|
||||
maxRatio = 2.1 / rowsCount
|
||||
}
|
||||
// Make sure the values are clamped between some reasonable bounds
|
||||
return (max(0.09, minRatio), min(0.30, maxRatio))
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
class AppearanceUtils {
|
||||
/// How wide should the ThumbnailsPanel be, for comfortable viewing?
|
||||
/// * a comfortable field-of-view is 50-60 degrees
|
||||
/// * people sit at various distances from the screen. We can't know how far they sit
|
||||
/// * most people will seat far enough so that they can view the whole width of the screen
|
||||
/// * some people use wide-screen or TV monitors. Those people tend to be too close to the screen, since they need to use keyboard and mouse on their desk
|
||||
/// Let's use this heuristic: let's assume that people can view 60cm comfortably. Bigger screens can only show parts of AltTab
|
||||
/// Let's clamp at 90% like Windows 11
|
||||
static func comfortableWidth(_ physicalWidth: Double) -> Double {
|
||||
return min(0.9, 600.0 / physicalWidth)
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,16 @@ extension NSScreen {
|
||||
}
|
||||
|
||||
func physicalSize() -> CGSize? {
|
||||
return number().map { CGDisplayScreenSize($0) }
|
||||
if let number = number() {
|
||||
let size = CGDisplayScreenSize(number)
|
||||
// CGDisplayScreenSize docs says it can return "zero"
|
||||
if size.width > 0 && size.height > 0 &&
|
||||
// CGDisplayScreenSize may return wrong values; we compare physical and logical ratios to reject
|
||||
abs(ratio() - (size.width / size.height)) < 0.2 {
|
||||
return size
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
static func preferred() -> NSScreen {
|
||||
@@ -44,6 +53,8 @@ extension NSScreen {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// NSScreen.main docs are incorrect. It stopped returning the screen with the key window in macOS 10.9
|
||||
|
||||
// see https://stackoverflow.com/a/56268826/2249756
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import XCTest
|
||||
|
||||
final class AppearanceTests: XCTestCase {
|
||||
let screens: [(String, (CGFloat, CGFloat), (CGFloat, CGFloat), (CGFloat, CGFloat), [(Int, CGFloat, CGFloat)])] = [
|
||||
// screen model, (widthInPixels, heightInPixels), (physicalWidthInMM, physicalHeightInMM), (expectedWidthForHorizontal, expectedWidthForVertical), (rowCount, expectedMinWidth, expectedMaxWidth)
|
||||
("11\" Laptop: MacBook Air 11\": HD", (1366, 768), (255.7, 178.6), (0.90, 0.90), [(3, 0.12, 0.25), (4, 0.09, 0.19), (5, 0.09, 0.15)]),
|
||||
("13\" Laptop: MacBook Air 13\": WXGA+", (1440, 900), (304.1, 197.8), (0.90, 0.90), [(3, 0.13, 0.28), (4, 0.10, 0.21), (5, 0.09, 0.17)]),
|
||||
("14\" Laptop: MacBook Pro 14\": 3K", (3024, 1964), (311.0, 221.1), (0.90, 0.90), [(3, 0.13, 0.29), (4, 0.10, 0.22), (5, 0.09, 0.17)]),
|
||||
("15\" Laptop: MacBook Pro 15\": QXGA", (2880, 1800), (344.4, 233.0), (0.90, 0.90), [(3, 0.13, 0.28), (4, 0.10, 0.21), (5, 0.09, 0.17)]),
|
||||
("16\" Laptop: MacBook Pro 16\": 3.5K", (3456, 2234), (358.4, 245.9), (0.90, 0.90), [(3, 0.13, 0.29), (4, 0.10, 0.22), (5, 0.09, 0.17)]),
|
||||
("19\" Monitor: Apple Studio Display 19\": HD", (1440, 900), (403.0, 236.0), (0.90, 0.90), [(3, 0.13, 0.28), (4, 0.10, 0.21), (5, 0.09, 0.17)]),
|
||||
("20\" Monitor: Apple Cinema Display 20\": WSXGA+", (1680, 1050), (440.0, 268.0), (0.90, 0.90), [(3, 0.13, 0.28), (4, 0.10, 0.21), (5, 0.09, 0.17)]),
|
||||
("21\" Monitor: LG 21:9 UltraWide: UWHD", (2560, 1080), (470.0, 290.0), (0.90, 0.90), [(3, 0.09, 0.19), (4, 0.09, 0.14), (5, 0.09, 0.11)]),
|
||||
("22\" Monitor: ASUS 22\" Full HD: Full HD", (1920, 1080), (485.0, 290.0), (0.90, 0.90), [(3, 0.12, 0.25), (4, 0.09, 0.19), (5, 0.09, 0.15)]),
|
||||
("24\" Monitor: Dell P2419H: Full HD", (1920, 1080), (531.3, 298.6), (0.90, 0.90), [(3, 0.12, 0.25), (4, 0.09, 0.19), (5, 0.09, 0.15)]),
|
||||
("27\" Monitor: LG 27UK850-W: 4K", (3840, 2160), (596.8, 336.4), (0.90, 0.90), [(3, 0.12, 0.25), (4, 0.09, 0.19), (5, 0.09, 0.15)]),
|
||||
("30\" Monitor: BenQ PD3200U: 4K", (3840, 2160), (657.5, 376.3), (0.90, 0.90), [(3, 0.12, 0.25), (4, 0.09, 0.19), (5, 0.09, 0.15)]),
|
||||
("32\" Monitor: BenQ EW3270U: 4K", (3840, 2160), (711.5, 398.9), (0.84, 0.90), [(3, 0.12, 0.27), (4, 0.09, 0.20), (5, 0.09, 0.16)]),
|
||||
("34\" UltraWide Monitor: LG 34UC79G-B: UWHD", (2560, 1080), (798.5, 336.5), (0.75, 0.90), [(3, 0.10, 0.22), (4, 0.09, 0.17), (5, 0.09, 0.14)]),
|
||||
("34\" UltraWide Monitor: LG 34WN80C-B: UWQHD", (3440, 1440), (799.8, 334.8), (0.75, 0.90), [(3, 0.10, 0.22), (4, 0.09, 0.17), (5, 0.09, 0.13)]),
|
||||
("32\" TV: Samsung UE32T5300: Full HD", (1920, 1080), (715.0, 406.0), (0.83, 0.90), [(3, 0.13, 0.27), (4, 0.09, 0.20), (5, 0.09, 0.16)]),
|
||||
("40\" TV: Samsung Q60B: 4K", (3840, 2160), (889.0, 510.0), (0.67, 0.90), [(3, 0.16, 0.30), (4, 0.12, 0.25), (5, 0.09, 0.20)]),
|
||||
("43\" TV: LG 43UN7300: 4K", (3840, 2160), (956.0, 551.0), (0.62, 0.90), [(3, 0.17, 0.30), (4, 0.13, 0.27), (5, 0.10, 0.22)]),
|
||||
("50\" TV: Samsung TU8000: 4K", (3840, 2160), (1110.0, 630.0), (0.54, 0.90), [(3, 0.19, 0.30), (4, 0.15, 0.30), (5, 0.12, 0.25)]),
|
||||
("55\" TV: LG OLED55CXPUA: 4K", (3840, 2160), (1210.0, 715.0), (0.49, 0.83), [(3, 0.21, 0.30), (4, 0.16, 0.30), (5, 0.13, 0.28)]),
|
||||
("60\" TV: Vizio 60-inch 4K: 4K", (3840, 2160), (1320.0, 750.0), (0.45, 0.80), [(3, 0.23, 0.30), (4, 0.17, 0.30), (5, 0.14, 0.30)]),
|
||||
]
|
||||
|
||||
// TODO add 6, 7, 8 rowsCount and reuse vertical screens data from bellow
|
||||
func testGoodValuesForThumbnailsWidthMinMax() throws {
|
||||
var actual: (CGFloat, CGFloat)
|
||||
for (model, (pixelWidth, pixelHeight), _, (expectedHorizontal, _), expectedArray) in screens {
|
||||
for (rowCount, expectedMin, expectedMax) in expectedArray {
|
||||
actual = AppearanceTestable.goodValuesForThumbnailsWidthMinMax((pixelWidth * expectedHorizontal) / (pixelHeight * 0.8), CGFloat(rowCount))
|
||||
XCTAssertEqual(actual.0, expectedMin, accuracy: 0.01, model)
|
||||
XCTAssertEqual(actual.1, expectedMax, accuracy: 0.01, model)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func testComfortableWidth() throws {
|
||||
var actual: Double
|
||||
for (model, _, (physicalWidth, physicalHeight), (expectedHorizontal, expectedVertical), _) in screens {
|
||||
// screen used horizontally
|
||||
actual = AppearanceTestable.comfortableWidth(physicalWidth)
|
||||
XCTAssertEqual(actual, expectedHorizontal, accuracy: 0.01, model)
|
||||
// screen used vertically
|
||||
actual = AppearanceTestable.comfortableWidth(physicalHeight)
|
||||
XCTAssertEqual(actual, expectedVertical, accuracy: 0.01, model)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import XCTest
|
||||
|
||||
final class AppearanceUtilsTests: XCTestCase {
|
||||
func testComfortableWidth() throws {
|
||||
[
|
||||
// screen model, width, height, expected width %
|
||||
("11\" Laptop: MacBook Air 11\"", 255.7, 178.6, 0.9),
|
||||
("13\" Laptop: MacBook Air 13\"", 304.1, 197.8, 0.9),
|
||||
("14\" Laptop: MacBook Pro 14\"", 311.0, 221.1, 0.9),
|
||||
("15\" Laptop: MacBook Pro 15\"", 344.4, 233.0, 0.9),
|
||||
("16\" Laptop: MacBook Pro 16\"", 358.4, 245.9, 0.9),
|
||||
("19\" Monitor: Apple Studio Display 19\"", 403, 236, 0.9),
|
||||
("20\" Monitor: Apple Cinema Display 20\"", 440, 268, 0.9),
|
||||
("21\" Monitor: LG 21:9 UltraWide", 470, 290, 0.9),
|
||||
("22\" Monitor: ASUS 22\" Full HD", 485, 290, 0.9),
|
||||
("24\" Monitor: Dell P2419H", 531.3, 298.6, 0.9),
|
||||
("27\" Monitor: LG 27UK850-W", 596.8, 336.4, 0.9),
|
||||
("30\" Monitor: BenQ PD3200U", 657.5, 376.3, 0.9),
|
||||
("32\" Monitor: BenQ EW3270U", 711.5, 398.9, 0.8432888264230499),
|
||||
("34\" UltraWide Monitor: LG 34UC79G-B", 798.5, 336.5, 0.7514088916718847),
|
||||
("32\" TV: Samsung UE32T5300", 715, 406, 0.8391608391608392),
|
||||
("40\" TV: Samsung Q60B", 889, 510, 0.6749156355455568),
|
||||
("43\" TV: LG 43UN7300", 956, 551, 0.6276150627615062),
|
||||
("50\" TV: Samsung TU8000", 1110, 630, 0.5405405405405406),
|
||||
("55\" TV: LG OLED55CXPUA", 1210, 715, 0.49586776859504134),
|
||||
("60\" TV: Vizio 60-inch 4K", 1320, 750, 0.45454545454545453),
|
||||
].forEach { screen in
|
||||
let percent = AppearanceUtils.comfortableWidth(screen.1)
|
||||
XCTAssertEqual(percent, screen.3)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user