From b26e0e63ebe7168d31ad6fa3167f0d29c362d802 Mon Sep 17 00:00:00 2001 From: Kai Azim <68963405+MrKai77@users.noreply.github.com> Date: Tue, 3 Oct 2023 19:41:05 -0600 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20#45=20Ability=20to=20restore=20init?= =?UTF-8?q?ial=20window=20frame?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use keybind `Trigger Key` + `I` --- Loop/Extensions/Defaults+Extensions.swift | 4 +++ Loop/Managers/LoopManager.swift | 22 ++++++++----- Loop/Preview Window/PreviewView.swift | 2 ++ Loop/Window Management/WindowDirection.swift | 14 ++++++--- Loop/Window Management/WindowEngine.swift | 29 +++++++++++++++-- Loop/Window Management/WindowRecords.swift | 33 +++++++++++++++----- 6 files changed, 82 insertions(+), 22 deletions(-) diff --git a/Loop/Extensions/Defaults+Extensions.swift b/Loop/Extensions/Defaults+Extensions.swift index f1dbee07..2da35968 100644 --- a/Loop/Extensions/Defaults+Extensions.swift +++ b/Loop/Extensions/Defaults+Extensions.swift @@ -42,6 +42,10 @@ extension Defaults.Keys { "centerKeybind", default: [[.kVK_Return]] ) + static let initialFrameKeybind = Key<[Set]>( + "initialFrameKeybind", + default: [[.kVK_ANSI_I]] + ) static let lastDirectionKeybind = Key<[Set]>( "lastDirectionKeybind", default: [[.kVK_ANSI_Z]] diff --git a/Loop/Managers/LoopManager.swift b/Loop/Managers/LoopManager.swift index 68a8ba91..b4025abe 100644 --- a/Loop/Managers/LoopManager.swift +++ b/Loop/Managers/LoopManager.swift @@ -18,6 +18,7 @@ class LoopManager { private let previewController = PreviewController() private var currentResizingDirection: WindowDirection = .noAction + private var actualCurrentResizingDirection: WindowDirection = .noAction // Used when direction is .lastDirection private var isLoopShown: Bool = false private var frontmostWindow: Window? private var screenWithMouse: NSScreen? @@ -69,13 +70,19 @@ class LoopManager { if let direction = notification.userInfo?["direction"] as? WindowDirection { self.currentResizingDirection = direction - if let window = self.frontmostWindow, - self.currentResizingDirection == .lastDirection { + if notification.userInfo?["isActualDirection"] as? Bool == nil || + notification.userInfo?["isActualDirection"] as? Bool == true { + self.actualCurrentResizingDirection = direction + } + if let window = self.frontmostWindow, self.currentResizingDirection == .lastDirection { // If the user sets .lastDirection as the last direction self.currentResizingDirection = WindowRecords.getLastDirection(for: window) DispatchQueue.main.async { - Notification.Name.directionChanged.post(userInfo: ["direction": self.currentResizingDirection]) + Notification.Name.directionChanged.post(userInfo: [ + "direction": self.currentResizingDirection, + "isActualDirection": false] + ) } } else { // Haptic feedback on the trackpad @@ -134,8 +141,9 @@ class LoopManager { } private func openLoop() { - currentResizingDirection = .noAction - frontmostWindow = nil + self.currentResizingDirection = .noAction + self.actualCurrentResizingDirection = .noAction + self.frontmostWindow = nil // Loop will only open if accessibility access has been granted if PermissionsManager.Accessibility.getStatus() { @@ -164,11 +172,11 @@ class LoopManager { self.screenWithMouse != nil && forceClose == false && self.isLoopShown && - self.currentResizingDirection != .noAction { + self.actualCurrentResizingDirection != .noAction { isLoopShown = false - WindowEngine.resize(self.frontmostWindow!, to: self.currentResizingDirection, self.screenWithMouse!) + WindowEngine.resize(self.frontmostWindow!, to: self.actualCurrentResizingDirection, self.screenWithMouse!) Notification.Name.didLoop.post() Defaults[.timesLooped] += 1 iconManager.checkIfUnlockedNewIcon() diff --git a/Loop/Preview Window/PreviewView.swift b/Loop/Preview Window/PreviewView.swift index d97a229c..fcc50057 100644 --- a/Loop/Preview Window/PreviewView.swift +++ b/Loop/Preview Window/PreviewView.swift @@ -87,6 +87,8 @@ struct PreviewView: View { .padding(previewPadding + previewBorderThickness / 2) .frame(width: currentResizeDirection == .noAction ? 0 : nil, height: currentResizeDirection == .noAction ? 0 : nil) + .frame(width: currentResizeDirection == .initialFrame ? 0 : nil, + height: currentResizeDirection == .initialFrame ? 0 : nil) .frame(width: currentResizeDirection == .center ? (window?.size.width ?? 10) - previewPadding + previewBorderThickness / 2 : nil, diff --git a/Loop/Window Management/WindowDirection.swift b/Loop/Window Management/WindowDirection.swift index 5cd5d1e1..09f59399 100644 --- a/Loop/Window Management/WindowDirection.swift +++ b/Loop/Window Management/WindowDirection.swift @@ -14,8 +14,9 @@ enum WindowDirection: CaseIterable { case noAction case maximize case fullscreen - case center case lastDirection + case center + case initialFrame // Halves case topHalf @@ -79,9 +80,10 @@ enum WindowDirection: CaseIterable { switch self { case .noAction: nil case .maximize: "Maximize" - case .fullscreen: "Fullscreen" - case .center: "Center" + case .fullscreen: "Fullscreen" case .lastDirection: nil + case .center: "Center" + case .initialFrame: "Restore Initial Frame" case .topHalf: "Top Half" case .rightHalf: "Right Half" @@ -112,8 +114,9 @@ enum WindowDirection: CaseIterable { case .noAction: [[]] case .maximize: Defaults[.maximizeKeybind] case .fullscreen: Defaults[.fullscreenKeybind] - case .center: Defaults[.centerKeybind] case .lastDirection: Defaults[.lastDirectionKeybind] + case .center: Defaults[.centerKeybind] + case .initialFrame: Defaults[.initialFrameKeybind] case .topHalf: Defaults[.topHalfKeybind] case .rightHalf: Defaults[.rightHalfKeybind] @@ -256,8 +259,9 @@ enum WindowDirection: CaseIterable { case .noAction: nil case .maximize: CGRect(x: 0, y: 0, width: 1.0, height: 1.0) case .fullscreen: CGRect(x: 0, y: 0, width: 1.0, height: 1.0) - case .center: nil case .lastDirection: nil + case .center: nil + case .initialFrame: nil // Halves case .topHalf: CGRect(x: 0, y: 0, width: 1.0, height: 1.0/2.0) diff --git a/Loop/Window Management/WindowEngine.swift b/Loop/Window Management/WindowEngine.swift index f07b095f..e629e22c 100644 --- a/Loop/Window Management/WindowEngine.swift +++ b/Loop/Window Management/WindowEngine.swift @@ -36,8 +36,12 @@ struct WindowEngine { } let oldWindowFrame = window.frame - guard let screenFrame = screen.safeScreenFrame, - let currentWindowFrame = WindowEngine.generateWindowFrame(oldWindowFrame, screenFrame, direction) else { + guard let screenFrame = screen.safeScreenFrame, let currentWindowFrame = WindowEngine.generateWindowFrame( + oldWindowFrame, + screenFrame, + direction, + window + ) else { return } var targetWindowFrame = WindowEngine.applyPadding(currentWindowFrame, direction) @@ -129,7 +133,8 @@ struct WindowEngine { private static func generateWindowFrame( _ windowFrame: CGRect, _ screenFrame: CGRect, - _ direction: WindowDirection + _ direction: WindowDirection, + _ window: Window ) -> CGRect? { let screenWidth = screenFrame.size.width let screenHeight = screenFrame.size.height @@ -149,6 +154,24 @@ struct WindowEngine { width: windowFrame.width, height: windowFrame.height ) + case .lastDirection: + let previousDirection = WindowRecords.getLastDirection(for: window, willResize: true) + if let previousResizeFrame = self.generateWindowFrame( + windowFrame, + screenFrame, + previousDirection, + window + ) { + newWindowFrame = previousResizeFrame + } else { + return nil + } + case .initialFrame: + if let initalFrame = WindowRecords.getInitialFrame(for: window) { + newWindowFrame = initalFrame + } else { + return nil + } default: guard let frameMultiplyValues = direction.frameMultiplyValues else { return nil} newWindowFrame.origin.x += screenWidth * frameMultiplyValues.minX diff --git a/Loop/Window Management/WindowRecords.swift b/Loop/Window Management/WindowRecords.swift index feecda78..52c3be98 100644 --- a/Loop/Window Management/WindowRecords.swift +++ b/Loop/Window Management/WindowRecords.swift @@ -16,6 +16,14 @@ struct WindowRecords { var directionRecords: [WindowDirection] } + static private func getIndex(of window: Window) -> Int? { + guard WindowRecords.hasBeenRecorded(window), + let idx = WindowRecords.records.firstIndex(where: { $0.cgWindowID == window.cgWindowID }) else { + return nil + } + return idx + } + /// This will erase ALL previous records of the window, and start a fresh new record for the selected window. /// - Parameter window: The window to record static func recordFirst(for window: Window) { @@ -25,14 +33,13 @@ struct WindowRecords { WindowRecords.Record( cgWindowID: window.cgWindowID, initialFrame: window.frame, - directionRecords: [.noAction] + directionRecords: [.initialFrame] ) ) } static func recordDirection(_ window: Window, _ direction: WindowDirection) { - guard WindowRecords.hasBeenRecorded(window), - let idx = WindowRecords.records.firstIndex(where: { $0.cgWindowID == window.cgWindowID }) else { + guard let idx = WindowRecords.getIndex(of: window) else { return } @@ -43,12 +50,24 @@ struct WindowRecords { return WindowRecords.records.contains(where: { $0.cgWindowID == window.cgWindowID }) } - static func getLastDirection(for window: Window) -> WindowDirection { - guard WindowRecords.hasBeenRecorded(window), - let idx = WindowRecords.records.firstIndex(where: { $0.cgWindowID == window.cgWindowID }) else { + static func getLastDirection(for window: Window, willResize: Bool = false) -> WindowDirection { + guard let idx = WindowRecords.getIndex(of: window), + WindowRecords.records[idx].directionRecords.count > 1 else { return .noAction } - return WindowRecords.records[idx].directionRecords[1] + let lastDirection = WindowRecords.records[idx].directionRecords[1] + if willResize && WindowRecords.records[idx].directionRecords.count > 2 { + WindowRecords.records[idx].directionRecords.removeFirst(2) + } + return lastDirection + } + + static func getInitialFrame(for window: Window) -> CGRect? { + guard let idx = WindowRecords.getIndex(of: window) else { + return nil + } + + return WindowRecords.records[idx].initialFrame } }