Skip to content

Commit

Permalink
🔀 Merge pull request #129 from MrKai77/101-respect-stage-manager
Browse files Browse the repository at this point in the history
✨ #101 Respect Stage Manager
  • Loading branch information
MrKai77 authored Dec 24, 2023
2 parents b4d10cc + 322991b commit 502ee5d
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 12 deletions.
4 changes: 4 additions & 0 deletions Loop.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
A864F4682AA660CD00579738 /* WindowDragManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A864F4672AA660CD00579738 /* WindowDragManager.swift */; };
A86949862A8F2BB70051AAAF /* CGKeyCode+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86949852A8F2BB60051AAAF /* CGKeyCode+Extensions.swift */; };
A869C19F2B37D67900AD1A84 /* BlueprintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A869C19E2B37D67900AD1A84 /* BlueprintView.swift */; };
A869C1A12B38C6E600AD1A84 /* StageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A869C1A02B38C6E600AD1A84 /* StageManager.swift */; };
A86B97AD2AB79E2500099D7F /* ShakeEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86B97AC2AB79E2500099D7F /* ShakeEffect.swift */; };
A86CB7332A3D22E7006A78F2 /* WindowEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86CB7322A3D22E7006A78F2 /* WindowEngine.swift */; };
A87376F62AA288EB001890F4 /* Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87376F52AA288EB001890F4 /* Window.swift */; };
Expand Down Expand Up @@ -106,6 +107,7 @@
A864F4672AA660CD00579738 /* WindowDragManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowDragManager.swift; sourceTree = "<group>"; };
A86949852A8F2BB60051AAAF /* CGKeyCode+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGKeyCode+Extensions.swift"; sourceTree = "<group>"; };
A869C19E2B37D67900AD1A84 /* BlueprintView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlueprintView.swift; sourceTree = "<group>"; };
A869C1A02B38C6E600AD1A84 /* StageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StageManager.swift; sourceTree = "<group>"; };
A86AFD7529888B29008F4892 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
A86B97AC2AB79E2500099D7F /* ShakeEffect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShakeEffect.swift; sourceTree = "<group>"; };
A86CB7322A3D22E7006A78F2 /* WindowEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowEngine.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -191,6 +193,7 @@
A864F4672AA660CD00579738 /* WindowDragManager.swift */,
A82521ED29E235AC00139654 /* PermissionsManager.swift */,
A8EF1F08299C87DF00633440 /* IconManager.swift */,
A869C1A02B38C6E600AD1A84 /* StageManager.swift */,
);
path = Managers;
sourceTree = "<group>";
Expand Down Expand Up @@ -447,6 +450,7 @@
A8330ABD2A3AC0CA00673C8D /* Bundle+Extensions.swift in Sources */,
A86B97AD2AB79E2500099D7F /* ShakeEffect.swift in Sources */,
A82740982AB00FCE00B9BDC5 /* Color+Extensions.swift in Sources */,
A869C1A12B38C6E600AD1A84 /* StageManager.swift in Sources */,
A8DCC9882981B9E100D41065 /* RadialMenuSettingsView.swift in Sources */,
A8F0636D2985AF1F0010C33D /* MoreSettingsView.swift in Sources */,
A8330ACD2A3AC1D100673C8D /* CGGeometry+Extensions.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions Loop/Extensions/Defaults+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,7 @@ extension Defaults.Keys {
Keybind(.bottomRightQuarter, keycode: [.kVK_DownArrow, .kVK_RightArrow]),
Keybind(.bottomLeftQuarter, keycode: [.kVK_DownArrow, .kVK_LeftArrow])
])

static let respectStageManager = Key<Bool>("respectStageManager", default: true)
static let stageStripSize = Key<CGFloat>("stageStripSize", default: 150)
}
25 changes: 20 additions & 5 deletions Loop/Extensions/NSScreen+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
//

import SwiftUI
import Defaults

// Return the CGDirectDisplayID
// Used in to help calculate the size a window needs to be resized to
extension NSScreen {

// Return the CGDirectDisplayID
// Used in to help calculate the size a window needs to be resized to
var displayID: CGDirectDisplayID? {
let key = NSDeviceDescriptionKey("NSScreenNumber")
return self.deviceDescription[key] as? CGDirectDisplayID
Expand All @@ -23,9 +25,14 @@ extension NSScreen {
return screenWithMouse
}

var safeScreenFrame: CGRect? {
guard let displayID = self.displayID,
let visibleFrame = self.visibleFrame.flipY else { return nil }
var safeScreenFrame: CGRect {
guard
let displayID = self.displayID,
let visibleFrame = self.visibleFrame.flipY
else {
return self.frame.flipY!
}

let screenFrame = CGDisplayBounds(displayID)
let menubarHeight = visibleFrame.origin.y

Expand All @@ -38,6 +45,14 @@ extension NSScreen {
safeScreenFrame.origin.y += menubarHeight
safeScreenFrame.origin.x -= screenFrame.minX - visibleFrame.minX

if Defaults[.respectStageManager] && StageManager.enabled && StageManager.shown {
if StageManager.position == .leading {
safeScreenFrame.origin.x += Defaults[.stageStripSize]
}

safeScreenFrame.size.width -= Defaults[.stageStripSize]
}

return safeScreenFrame
}
}
41 changes: 41 additions & 0 deletions Loop/Managers/StageManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// StageManager.swift
// Loop
//
// Created by Kai Azim on 2023-12-24.
//

import SwiftUI

class StageManager {
private static let windowManagerDefaults = UserDefaults(suiteName: "com.apple.WindowManager")
private static let dockDefaults = UserDefaults(suiteName: "com.apple.dock")

static var available: Bool {
guard #available(macOS 13, *) else {
return false
}
return true
}

static var enabled: Bool {
guard let value = windowManagerDefaults?.object(forKey: "GloballyEnabled") as? Bool else {
return false
}
return value
}

static var shown: Bool {
guard let value = windowManagerDefaults?.object(forKey: "AutoHide") as? Bool else {
return false
}
return !value
}

static var position: Edge {
guard let value = dockDefaults?.object(forKey: "orientation") as? String else {
return .leading
}
return value == "left" ? .trailing : .leading
}
}
2 changes: 1 addition & 1 deletion Loop/Preview Window/PreviewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PreviewController {
panel.alphaValue = 0
panel.orderFrontRegardless()

panel.setFrame(screen.visibleFrame, display: false)
panel.setFrame(screen.safeScreenFrame.flipY!, display: false)

loopPreviewWindowController = .init(window: panel)

Expand Down
17 changes: 17 additions & 0 deletions Loop/Settings/MoreSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import Defaults
struct MoreSettingsView: View {
@EnvironmentObject var updater: SoftwareUpdater

@Default(.respectStageManager) var respectStageManager
@Default(.stageStripSize) var stageStripSize

@Default(.animateWindowResizes) var animateWindowResizes
@State var isAccessibilityAccessGranted = false
@State var isScreenRecordingAccessGranted = false
Expand Down Expand Up @@ -51,6 +54,20 @@ struct MoreSettingsView: View {
}
})

Section("Stage Manager") {
Toggle("Respect Stage Manager", isOn: $respectStageManager)
Slider(
value: $stageStripSize,
in: 50...200,
step: 15,
minimumValueLabel: Text("50px"),
maximumValueLabel: Text("200px")
) {
Text("Stage Strip Size")
}
.disabled(!respectStageManager)
}

Section(content: {
HStack {
Text("Accessibility Access")
Expand Down
15 changes: 9 additions & 6 deletions Loop/Window Management/WindowEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ struct WindowEngine {
return
}

guard let screenFrame = screen.safeScreenFrame,
let currentWindowFrame = WindowEngine.generateWindowFrame(window.frame, screenFrame, direction, window)
let screenFrame = screen.safeScreenFrame
guard
let currentWindowFrame = WindowEngine.generateWindowFrame(window.frame, screenFrame, direction, window)
else {
return
}
Expand All @@ -57,12 +58,14 @@ struct WindowEngine {

// Calculate the window's minimum window size and change the target accordingly
window.getMinSize(screen: screen) { minSize in
if (targetWindowFrame.minX + minSize.width) > screen.frame.maxX {
targetWindowFrame.origin.x = screen.frame.maxX - minSize.width - Defaults[.windowPadding]
let nsScreenFrame = screenFrame.flipY!

if (targetWindowFrame.minX + minSize.width) > nsScreenFrame.maxX {
targetWindowFrame.origin.x = nsScreenFrame.maxX - minSize.width - Defaults[.windowPadding]
}

if (targetWindowFrame.minY + minSize.height) > screen.frame.maxY {
targetWindowFrame.origin.y = screen.frame.maxY - minSize.height - Defaults[.windowPadding]
if (targetWindowFrame.minY + minSize.height) > nsScreenFrame.maxY {
targetWindowFrame.origin.y = nsScreenFrame.maxY - minSize.height - Defaults[.windowPadding]
}

window.setFrame(targetWindowFrame, animate: true) {
Expand Down

0 comments on commit 502ee5d

Please sign in to comment.