From 7029a5eb0e339d9071071b6a136322160177b7dd Mon Sep 17 00:00:00 2001 From: Serhii Bykov Date: Sat, 1 Aug 2026 18:36:06 +0200 Subject: [PATCH] fix(displays): scale preview marker with keyboard size --- .../DisplaysSettingsPane+PreviewCard.swift | 23 +++++++++++++++---- .../Displays/DisplaysSettingsPane.swift | 1 + .../DisplaysSettingsPaneViewModel.swift | 16 ++++++++++--- .../Keyboard/KeyboardVisualizerSettings.swift | 1 + 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane+PreviewCard.swift b/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane+PreviewCard.swift index e261f7c..8f6478f 100644 --- a/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane+PreviewCard.swift +++ b/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane+PreviewCard.swift @@ -15,6 +15,7 @@ extension DisplaysSettingsPane { let anchor: KeyboardVisualizerAnchor let placementMode: KeyboardVisualizerSettings.PlacementMode let stackAxis: KeyboardVisualizerStackAxis + let keyboardScale: Double let windowPadding: Double let customPositionNormalizedX: Double let customPositionNormalizedY: Double @@ -113,10 +114,15 @@ private extension DisplaysSettingsPane.PreviewCard { func markerSize(in displaySize: CGSize) -> CGSize { let maximumSize = self.maximumMarkerSize let scale = self.markerScale(in: displaySize, maximumSize: maximumSize) + let keyboardScale = CGFloat(self.keyboardScale).clamped(to: 0.5...2.0) + let scaledSize = CGSize( + width: maximumSize.width * scale * keyboardScale, + height: maximumSize.height * scale * keyboardScale + ) return CGSize( - width: maximumSize.width * scale, - height: maximumSize.height * scale + width: min(scaledSize.width, max(displaySize.width - Spacing.xs * 2, Spacing.xs)), + height: min(scaledSize.height, max(displaySize.height - Spacing.xs * 2, Spacing.xs)) ) } @@ -173,9 +179,16 @@ private extension DisplaysSettingsPane.PreviewCard { } func customPositionOffset(in size: CGSize, markerSize: CGSize) -> CGSize { - CGSize( - width: size.width * CGFloat(self.customPositionNormalizedX) - size.width / 2, - height: size.height / 2 - size.height * CGFloat(self.customPositionNormalizedY) + let halfMarkerWidth = markerSize.width / 2 + let halfMarkerHeight = markerSize.height / 2 + let x = (size.width * CGFloat(self.customPositionNormalizedX) - size.width / 2) + .clamped(minimum: -size.width / 2 + halfMarkerWidth, maximum: size.width / 2 - halfMarkerWidth) + let y = (size.height / 2 - size.height * CGFloat(self.customPositionNormalizedY)) + .clamped(minimum: -size.height / 2 + halfMarkerHeight, maximum: size.height / 2 - halfMarkerHeight) + + return CGSize( + width: x, + height: y ) } } diff --git a/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane.swift b/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane.swift index 7d544c8..f827d88 100644 --- a/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane.swift +++ b/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPane.swift @@ -23,6 +23,7 @@ struct DisplaysSettingsPane: View { anchor: self.model.selectedAnchor, placementMode: self.model.placementMode, stackAxis: self.model.stackAxis, + keyboardScale: self.model.scale, windowPadding: self.model.windowPadding, customPositionNormalizedX: self.model.customPositionNormalizedX, customPositionNormalizedY: self.model.customPositionNormalizedY, diff --git a/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPaneViewModel.swift b/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPaneViewModel.swift index c31a045..effc4e9 100644 --- a/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPaneViewModel.swift +++ b/Apps/Keyty/Sources/Keyty/Features/Settings/Displays/DisplaysSettingsPaneViewModel.swift @@ -57,9 +57,8 @@ final class DisplaysSettingsPaneViewModel: ObservableObject { didSet { self.keyboardVisualizerSettings.customPositionNormalizedY = CGFloat(self.customPositionNormalizedY) } } - var stackAxis: KeyboardVisualizerStackAxis { - self.keyboardVisualizerSettings.stackAxis - } + @Published private(set) var stackAxis: KeyboardVisualizerStackAxis + @Published private(set) var scale: Double var isCustomPlacement: Bool { self.placementMode == .custom @@ -109,6 +108,8 @@ final class DisplaysSettingsPaneViewModel: ObservableObject { self.windowPadding = Double(keyboardVisualizerSettings.windowPadding) self.customPositionNormalizedX = Double(keyboardVisualizerSettings.customPositionNormalizedX) self.customPositionNormalizedY = Double(keyboardVisualizerSettings.customPositionNormalizedY) + self.stackAxis = keyboardVisualizerSettings.stackAxis + self.scale = Double(keyboardVisualizerSettings.scale) self.screensService.screensDidChange .receive(on: RunLoop.main) @@ -118,6 +119,15 @@ final class DisplaysSettingsPaneViewModel: ObservableObject { self.selectedScreen = self.resolveSelectedScreen(for: self.keyboardVisualizerSettings.screenID) } .store(in: &self.cancellables) + + self.keyboardVisualizerSettings.placementChanges + .receive(on: RunLoop.main) + .sink { [weak self, weak keyboardVisualizerSettings] in + guard let self, let keyboardVisualizerSettings else { return } + self.stackAxis = keyboardVisualizerSettings.stackAxis + self.scale = Double(keyboardVisualizerSettings.scale) + } + .store(in: &self.cancellables) } func toggleCustomPositionSetting() { diff --git a/Apps/Keyty/Sources/Keyty/Features/Visualizers/Keyboard/KeyboardVisualizerSettings.swift b/Apps/Keyty/Sources/Keyty/Features/Visualizers/Keyboard/KeyboardVisualizerSettings.swift index 8405be8..147886e 100644 --- a/Apps/Keyty/Sources/Keyty/Features/Visualizers/Keyboard/KeyboardVisualizerSettings.swift +++ b/Apps/Keyty/Sources/Keyty/Features/Visualizers/Keyboard/KeyboardVisualizerSettings.swift @@ -240,6 +240,7 @@ final class KeyboardVisualizerSettings: KeyboardVisualizerSettingsProtocol, HasS } set { self.storedScale = min(max(newValue, 0.5), 2.0) + self.placementChangesSubject.send(()) } }