Skip to content

Commit

Permalink
🔀 Merge pull request #502 from `MrKai77/mrkai77/loop-311-window-paddi…
Browse files Browse the repository at this point in the history
…ng-only-enabled-on-external-monitors`

✨ Ability to set minimum screen size for padding
  • Loading branch information
MrKai77 authored Jul 9, 2024
2 parents c2eccc2 + 9ba0dcc commit 6ab3a7f
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 10 deletions.
8 changes: 8 additions & 0 deletions Loop/Extensions/Defaults+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,11 @@ extension Defaults.Keys {
static let excludedApps = Key<[URL]>("excludedApps", default: [], iCloud: true)
static let sizeIncrement = Key<CGFloat>("sizeIncrement", default: 20, iCloud: true)
}

// MARK: - Extra Advanced

extension Defaults.Keys {
/// Adjust with `defaults write com.MrKai77.Loop paddingMinimumScreenSize -float x`
/// Reset with `defaults delete com.MrKai77.Loop paddingMinimumScreenSize`
static let paddingMinimumScreenSize = Key<CGFloat>("paddingMinimumScreenSize", default: 0, iCloud: true)
}
38 changes: 38 additions & 0 deletions Loop/Extensions/NSScreen+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,41 @@ extension NSScreen {
frame.maxY - visibleFrame.maxY
}
}

// MARK: - Calculate physical screen size

extension NSScreen {
// Returns diagonal size in inches
var diagonalSize: CGFloat {
let unitsPerInch = unitsPerInch
let screenSizeInInches = CGSize(
width: frame.width / unitsPerInch.width,
height: frame.height / unitsPerInch.height
)

// Just the pythagorean theorem
let diagonalSize = sqrt(pow(screenSizeInInches.width, 2) + pow(screenSizeInInches.height, 2))

return diagonalSize
}

private var unitsPerInch: CGSize {
// We need to convert from mm to inch because CGDisplayScreenSize returns units in mm.
let millimetersPerInch: CGFloat = 25.4

let screenDescription = deviceDescription
if let displayUnitSize = (screenDescription[NSDeviceDescriptionKey.size] as? NSValue)?.sizeValue,
let screenNumber = (screenDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber)?.uint32Value {
let displayPhysicalSize = CGDisplayScreenSize(screenNumber)

return CGSize(
width: millimetersPerInch * displayUnitSize.width / displayPhysicalSize.width,
height: millimetersPerInch * displayUnitSize.height / displayPhysicalSize.height
)
} else {
// this is the same as what CoreGraphics assumes if no EDID data is available from the display device
// https://developer.apple.com/documentation/coregraphics/1456599-cgdisplayscreensize?language=objc
return CGSize(width: 72.0, height: 72.0)
}
}
}
4 changes: 1 addition & 3 deletions Loop/Luminare/Settings/Behavior/BehaviorConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ class BehaviorConfigurationModel: ObservableObject {
}

@Published var focusWindowOnResize = Defaults[.focusWindowOnResize] {
didSet {
Defaults[.focusWindowOnResize] = focusWindowOnResize
}
didSet { Defaults[.focusWindowOnResize] = focusWindowOnResize }
}

@Published var respectStageManager = Defaults[.respectStageManager] {
Expand Down
3 changes: 2 additions & 1 deletion Loop/Preview Window/PreviewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ class PreviewController {

let targetWindowFrame = action.getFrame(
window: window,
bounds: screen.safeScreenFrame
bounds: screen.safeScreenFrame,
screen: screen
)
.flipY(maxY: NSScreen.screens[0].frame.maxY)

Expand Down
15 changes: 11 additions & 4 deletions Loop/Window Management/WindowAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,13 @@ struct WindowAction: Codable, Identifiable, Hashable, Equatable, Defaults.Serial
return result.normalized()
}

func getFrame(window: Window?, bounds: CGRect, disablePadding: Bool = false) -> CGRect {
func getFrame(window: Window?, bounds: CGRect, disablePadding: Bool = false, screen: NSScreen? = nil) -> CGRect {
guard direction != .cycle, direction != .noAction else {
return NSRect(origin: bounds.center, size: .zero)
}
var bounds = bounds
if !disablePadding && Defaults[.enablePadding] {
if !disablePadding && Defaults[.enablePadding],
Defaults[.paddingMinimumScreenSize] == .zero || screen?.diagonalSize ?? .zero > Defaults[.paddingMinimumScreenSize] {
bounds = getPaddedBounds(bounds)
}
var result = CGRect(origin: bounds.origin, size: .zero)
Expand Down Expand Up @@ -223,7 +224,7 @@ struct WindowAction: Codable, Identifiable, Hashable, Equatable, Defaults.Serial

if !disablePadding {
if direction != .undo, direction != .initialFrame {
result = cropThenApplyPadding(result, bounds)
result = cropThenApplyInnerPadding(result, bounds)
}

LoopManager.lastTargetFrame = result
Expand Down Expand Up @@ -398,13 +399,19 @@ struct WindowAction: Codable, Identifiable, Hashable, Equatable, Defaults.Serial
return bounds
}

private func cropThenApplyPadding(_ windowFrame: CGRect, _ bounds: CGRect) -> CGRect {
private func cropThenApplyInnerPadding(_ windowFrame: CGRect, _ bounds: CGRect, _ screen: NSScreen? = nil) -> CGRect {
guard !direction.willMove else {
return windowFrame
}

var croppedWindowFrame = windowFrame.intersection(bounds)

let paddingMinimumScreenSize = Defaults[.paddingMinimumScreenSize]
if paddingMinimumScreenSize != .zero,
screen?.diagonalSize ?? .zero < paddingMinimumScreenSize {
return windowFrame
}

guard
!willManipulateExistingWindowFrame,
Defaults[.enablePadding]
Expand Down
5 changes: 3 additions & 2 deletions Loop/Window Management/WindowEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ enum WindowEngine {
return
}

let targetFrame = action.getFrame(window: window, bounds: screen.safeScreenFrame)
let targetFrame = action.getFrame(window: window, bounds: screen.safeScreenFrame, screen: screen)

if action.direction == .undo {
WindowRecords.removeLastAction(for: window)
Expand Down Expand Up @@ -86,7 +86,8 @@ enum WindowEngine {

let screenFrame = action.direction.willMove ? .zero : screen.safeScreenFrame

let bounds = if Defaults[.enablePadding] {
let bounds = if Defaults[.enablePadding],
Defaults[.paddingMinimumScreenSize] == 0 || screen.diagonalSize > Defaults[.paddingMinimumScreenSize] {
Defaults[.padding].apply(on: screenFrame)
} else {
screenFrame
Expand Down

0 comments on commit 6ab3a7f

Please sign in to comment.