From afcf699641407412c3de218abca497fcdfa179fa Mon Sep 17 00:00:00 2001 From: Nikhil Verma Date: Mon, 28 Oct 2024 00:49:36 -0400 Subject: [PATCH 1/6] Add commands for constrianed resize --- Rectangle/WindowAction.swift | 24 ++++++++- .../ChangeSizeCalculation.swift | 52 +++++++++++++------ .../WindowCalculation/WindowCalculation.swift | 4 ++ 3 files changed, 63 insertions(+), 17 deletions(-) diff --git a/Rectangle/WindowAction.swift b/Rectangle/WindowAction.swift index 19fee3c8..e951c6cf 100644 --- a/Rectangle/WindowAction.swift +++ b/Rectangle/WindowAction.swift @@ -92,7 +92,11 @@ enum WindowAction: Int, Codable { halveHeightUp = 76, halveHeightDown = 77, halveWidthLeft = 78, - halveWidthRight = 79 + halveWidthRight = 79, + largerWidth = 80, + smallerWidth = 81, + largerHeight = 82, + smallerHeight = 83 // Order matters here - it's used in the menu static let active = [leftHalf, rightHalf, centerHalf, topHalf, bottomHalf, @@ -225,6 +229,10 @@ enum WindowAction: Int, Codable { case .rightTodo: return "rightTodo" case .cascadeActiveApp: return "cascadeActiveApp" case .centerProminently: return "centerProminently" + case .largerWidth: return "largerWidth" + case .smallerWidth: return "smallerWidth" + case .largerHeight: return "largerHeight" + case .smallerHeight: return "smallerHeight" } } @@ -363,6 +371,8 @@ enum WindowAction: Int, Codable { return nil case .centerProminently: return nil + case .largerWidth, .smallerWidth, .largerHeight, .smallerHeight: + return nil } return NSLocalizedString(key, tableName: "Main", value: value, comment: "") @@ -404,7 +414,9 @@ enum WindowAction: Int, Codable { // Corner thirds .topLeftThird, .topRightThird, .bottomLeftThird, .bottomRightThird, // Eighths - .topLeftEighth, .topCenterLeftEighth, .topCenterRightEighth, .topRightEighth, .bottomLeftEighth, .bottomCenterLeftEighth, .bottomCenterRightEighth, .bottomRightEighth: + .topLeftEighth, .topCenterLeftEighth, .topCenterRightEighth, .topRightEighth, .bottomLeftEighth, .bottomCenterLeftEighth, .bottomCenterRightEighth, .bottomRightEighth, + // Smaller or Larger + .largerWidth, .smallerWidth, .largerHeight, .smallerHeight: return false default: return true @@ -456,6 +468,8 @@ enum WindowAction: Int, Codable { case .centerThird: return Shortcut( ctrl|alt, kVK_ANSI_F ) case .lastTwoThirds: return Shortcut( ctrl|alt, kVK_ANSI_T ) case .lastThird: return Shortcut( ctrl|alt, kVK_ANSI_G ) + case .largerWidth: return Shortcut( ctrl|alt|shift, kVK_ANSI_Equal ) + case .smallerWidth: return Shortcut( ctrl|alt|shift, kVK_ANSI_Minus ) default: return nil } } @@ -537,6 +551,10 @@ enum WindowAction: Int, Codable { case .rightTodo: return NSImage() case .cascadeActiveApp: return NSImage() case .centerProminently: return NSImage() + case .largerWidth: return NSImage() + case .smallerWidth: return NSImage() + case .largerHeight: return NSImage() + case .smallerHeight: return NSImage() } } @@ -581,6 +599,8 @@ enum WindowAction: Int, Codable { return Defaults.applyGapsToMaximizeHeight.userDisabled ? .none : .vertical; case .almostMaximize, .previousDisplay, .nextDisplay, .larger, .smaller, .center, .centerProminently, .restore, .specified, .reverseAll, .tileAll, .cascadeAll, .cascadeActiveApp: return .none + case .largerWidth, .smallerWidth, .largerHeight, .smallerHeight: + return .none } } diff --git a/Rectangle/WindowCalculation/ChangeSizeCalculation.swift b/Rectangle/WindowCalculation/ChangeSizeCalculation.swift index baf877f2..061765c5 100644 --- a/Rectangle/WindowCalculation/ChangeSizeCalculation.swift +++ b/Rectangle/WindowCalculation/ChangeSizeCalculation.swift @@ -25,33 +25,54 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation } override func calculateRect(_ params: RectCalculationParameters) -> RectResult { - let sizeOffset: CGFloat = params.action == .smaller ? -sizeOffsetAbs : sizeOffsetAbs + + let sizeOffset: CGFloat + switch params.action { + case .larger, .largerWidth, .largerHeight: + sizeOffset = sizeOffsetAbs + case .smaller, .smallerWidth, .smallerHeight: + sizeOffset = -sizeOffsetAbs + default: + sizeOffset = 0 + } let visibleFrameOfScreen = params.visibleFrameOfScreen let window = params.window + // Calculate Width + var resizedWindowRect = window.rect - resizedWindowRect.size.width = resizedWindowRect.width + sizeOffset - resizedWindowRect.origin.x = resizedWindowRect.minX - floor(sizeOffset / 2.0) - - if curtainChangeSize { + + if [.larger, .smaller, .largerWidth, .smallerWidth].contains(params.action) { + resizedWindowRect.size.width = resizedWindowRect.width + sizeOffset + resizedWindowRect.origin.x = resizedWindowRect.minX - floor(sizeOffset / 2.0) + + if curtainChangeSize { resizedWindowRect = againstLeftAndRightScreenEdges(originalWindowRect: window.rect, resizedWindowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) - } + } - if resizedWindowRect.width >= visibleFrameOfScreen.width { + if resizedWindowRect.width >= visibleFrameOfScreen.width { resizedWindowRect.size.width = visibleFrameOfScreen.width + } } - resizedWindowRect.size.height = resizedWindowRect.height + sizeOffset - resizedWindowRect.origin.y = resizedWindowRect.minY - floor(sizeOffset / 2.0) - - if curtainChangeSize { + + // Calculate Height + + if [.larger, .smaller, .largerHeight, .smallerHeight].contains(params.action) { + resizedWindowRect.size.height = resizedWindowRect.height + sizeOffset + resizedWindowRect.origin.y = resizedWindowRect.minY - floor(sizeOffset / 2.0) + + if curtainChangeSize { resizedWindowRect = againstTopAndBottomScreenEdges(originalWindowRect: window.rect, resizedWindowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) - } - - if resizedWindowRect.height >= visibleFrameOfScreen.height { + } + + if resizedWindowRect.height >= visibleFrameOfScreen.height { resizedWindowRect.size.height = visibleFrameOfScreen.height resizedWindowRect.origin.y = params.window.rect.minY + } } + + if againstAllScreenEdges(windowRect: window.rect, visibleFrameOfScreen: visibleFrameOfScreen) && (sizeOffset < 0) { resizedWindowRect.size.width = params.window.rect.width + sizeOffset resizedWindowRect.origin.x = params.window.rect.origin.x - floor(sizeOffset / 2.0) @@ -59,9 +80,10 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation resizedWindowRect.origin.y = params.window.rect.origin.y - floor(sizeOffset / 2.0) } - if params.action == .smaller, resizedWindowRectIsTooSmall(windowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) { + if [.smaller, .smallerHeight, .smallerWidth].contains(params.action), resizedWindowRectIsTooSmall(windowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) { resizedWindowRect = window.rect } + return RectResult(resizedWindowRect) } diff --git a/Rectangle/WindowCalculation/WindowCalculation.swift b/Rectangle/WindowCalculation/WindowCalculation.swift index 581b208c..66bd0109 100644 --- a/Rectangle/WindowCalculation/WindowCalculation.swift +++ b/Rectangle/WindowCalculation/WindowCalculation.swift @@ -193,6 +193,10 @@ class WindowCalculationFactory { .nextDisplay: nextPrevDisplayCalculation, .larger: changeSizeCalculation, .smaller: changeSizeCalculation, + .largerWidth: changeSizeCalculation, + .smallerWidth: changeSizeCalculation, + .largerHeight: changeSizeCalculation, + .smallerHeight: changeSizeCalculation, .bottomHalf: bottomHalfCalculation, .topHalf: topHalfCalculation, .center: centerCalculation, From ff84b3af8dd30eb715115aa88547b4cf99dafecc Mon Sep 17 00:00:00 2001 From: Nikhil Verma Date: Mon, 28 Oct 2024 01:17:28 -0400 Subject: [PATCH 2/6] Reduce to two commands --- Rectangle/WindowAction.swift | 20 ++++--------------- .../ChangeSizeCalculation.swift | 8 ++++---- .../WindowCalculation/WindowCalculation.swift | 2 -- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/Rectangle/WindowAction.swift b/Rectangle/WindowAction.swift index e951c6cf..29c6b56e 100644 --- a/Rectangle/WindowAction.swift +++ b/Rectangle/WindowAction.swift @@ -95,8 +95,6 @@ enum WindowAction: Int, Codable { halveWidthRight = 79, largerWidth = 80, smallerWidth = 81, - largerHeight = 82, - smallerHeight = 83 // Order matters here - it's used in the menu static let active = [leftHalf, rightHalf, centerHalf, topHalf, bottomHalf, @@ -231,8 +229,6 @@ enum WindowAction: Int, Codable { case .centerProminently: return "centerProminently" case .largerWidth: return "largerWidth" case .smallerWidth: return "smallerWidth" - case .largerHeight: return "largerHeight" - case .smallerHeight: return "smallerHeight" } } @@ -369,9 +365,7 @@ enum WindowAction: Int, Codable { return nil case .specified, .reverseAll, .tileAll, .cascadeAll, .leftTodo, .rightTodo, .cascadeActiveApp: return nil - case .centerProminently: - return nil - case .largerWidth, .smallerWidth, .largerHeight, .smallerHeight: + case .centerProminently, .largerWidth, .smallerWidth: return nil } @@ -408,15 +402,13 @@ enum WindowAction: Int, Codable { var isDragSnappable: Bool { switch self { - case .restore, .previousDisplay, .nextDisplay, .moveUp, .moveDown, .moveLeft, .moveRight, .specified, .reverseAll, .tileAll, .cascadeAll, .smaller, .larger, .cascadeActiveApp, + case .restore, .previousDisplay, .nextDisplay, .moveUp, .moveDown, .moveLeft, .moveRight, .specified, .reverseAll, .tileAll, .cascadeAll, .larger, .smaller, .largerWidth, .smallerWidth, .cascadeActiveApp, // Ninths .topLeftNinth, .topCenterNinth, .topRightNinth, .middleLeftNinth, .middleCenterNinth, .middleRightNinth, .bottomLeftNinth, .bottomCenterNinth, .bottomRightNinth, // Corner thirds .topLeftThird, .topRightThird, .bottomLeftThird, .bottomRightThird, // Eighths - .topLeftEighth, .topCenterLeftEighth, .topCenterRightEighth, .topRightEighth, .bottomLeftEighth, .bottomCenterLeftEighth, .bottomCenterRightEighth, .bottomRightEighth, - // Smaller or Larger - .largerWidth, .smallerWidth, .largerHeight, .smallerHeight: + .topLeftEighth, .topCenterLeftEighth, .topCenterRightEighth, .topRightEighth, .bottomLeftEighth, .bottomCenterLeftEighth, .bottomCenterRightEighth, .bottomRightEighth: return false default: return true @@ -553,8 +545,6 @@ enum WindowAction: Int, Codable { case .centerProminently: return NSImage() case .largerWidth: return NSImage() case .smallerWidth: return NSImage() - case .largerHeight: return NSImage() - case .smallerHeight: return NSImage() } } @@ -597,9 +587,7 @@ enum WindowAction: Int, Codable { return Defaults.applyGapsToMaximize.userDisabled ? .none : .both; case .maximizeHeight: return Defaults.applyGapsToMaximizeHeight.userDisabled ? .none : .vertical; - case .almostMaximize, .previousDisplay, .nextDisplay, .larger, .smaller, .center, .centerProminently, .restore, .specified, .reverseAll, .tileAll, .cascadeAll, .cascadeActiveApp: - return .none - case .largerWidth, .smallerWidth, .largerHeight, .smallerHeight: + case .almostMaximize, .previousDisplay, .nextDisplay, .larger, .smaller, .largerWidth, .smallerWidth, .center, .centerProminently, .restore, .specified, .reverseAll, .tileAll, .cascadeAll, .cascadeActiveApp: return .none } } diff --git a/Rectangle/WindowCalculation/ChangeSizeCalculation.swift b/Rectangle/WindowCalculation/ChangeSizeCalculation.swift index 061765c5..7f892214 100644 --- a/Rectangle/WindowCalculation/ChangeSizeCalculation.swift +++ b/Rectangle/WindowCalculation/ChangeSizeCalculation.swift @@ -28,9 +28,9 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation let sizeOffset: CGFloat switch params.action { - case .larger, .largerWidth, .largerHeight: + case .larger, .largerWidth: sizeOffset = sizeOffsetAbs - case .smaller, .smallerWidth, .smallerHeight: + case .smaller, .smallerWidth: sizeOffset = -sizeOffsetAbs default: sizeOffset = 0 @@ -58,7 +58,7 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation // Calculate Height - if [.larger, .smaller, .largerHeight, .smallerHeight].contains(params.action) { + if [.larger, .smaller].contains(params.action) { resizedWindowRect.size.height = resizedWindowRect.height + sizeOffset resizedWindowRect.origin.y = resizedWindowRect.minY - floor(sizeOffset / 2.0) @@ -80,7 +80,7 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation resizedWindowRect.origin.y = params.window.rect.origin.y - floor(sizeOffset / 2.0) } - if [.smaller, .smallerHeight, .smallerWidth].contains(params.action), resizedWindowRectIsTooSmall(windowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) { + if [.smaller, .smallerWidth].contains(params.action), resizedWindowRectIsTooSmall(windowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) { resizedWindowRect = window.rect } diff --git a/Rectangle/WindowCalculation/WindowCalculation.swift b/Rectangle/WindowCalculation/WindowCalculation.swift index 66bd0109..fcfbc3a1 100644 --- a/Rectangle/WindowCalculation/WindowCalculation.swift +++ b/Rectangle/WindowCalculation/WindowCalculation.swift @@ -195,8 +195,6 @@ class WindowCalculationFactory { .smaller: changeSizeCalculation, .largerWidth: changeSizeCalculation, .smallerWidth: changeSizeCalculation, - .largerHeight: changeSizeCalculation, - .smallerHeight: changeSizeCalculation, .bottomHalf: bottomHalfCalculation, .topHalf: topHalfCalculation, .center: centerCalculation, From 0a4894e0a6a631a6d08c937b3e8404d5d003e4a1 Mon Sep 17 00:00:00 2001 From: Nikhil Verma Date: Mon, 28 Oct 2024 01:26:55 -0400 Subject: [PATCH 3/6] Fix typo --- Rectangle/WindowAction.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rectangle/WindowAction.swift b/Rectangle/WindowAction.swift index 29c6b56e..6bc9dd88 100644 --- a/Rectangle/WindowAction.swift +++ b/Rectangle/WindowAction.swift @@ -94,7 +94,7 @@ enum WindowAction: Int, Codable { halveWidthLeft = 78, halveWidthRight = 79, largerWidth = 80, - smallerWidth = 81, + smallerWidth = 81 // Order matters here - it's used in the menu static let active = [leftHalf, rightHalf, centerHalf, topHalf, bottomHalf, From d7187c2cb9cf31935f08eeed930b2a5cd702ba74 Mon Sep 17 00:00:00 2001 From: Nikhil Verma Date: Thu, 31 Oct 2024 00:52:07 -0400 Subject: [PATCH 4/6] Add new commands to active --- Rectangle/WindowAction.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Rectangle/WindowAction.swift b/Rectangle/WindowAction.swift index 6bc9dd88..540d03b5 100644 --- a/Rectangle/WindowAction.swift +++ b/Rectangle/WindowAction.swift @@ -100,7 +100,8 @@ enum WindowAction: Int, Codable { static let active = [leftHalf, rightHalf, centerHalf, topHalf, bottomHalf, topLeft, topRight, bottomLeft, bottomRight, firstThird, centerThird, lastThird, firstTwoThirds, lastTwoThirds, - maximize, almostMaximize, maximizeHeight, smaller, larger, center, centerProminently, restore, + maximize, almostMaximize, maximizeHeight, larger, smaller, largerWidth, smallerWidth, + center, centerProminently, restore, nextDisplay, previousDisplay, moveLeft, moveRight, moveUp, moveDown, firstFourth, secondFourth, thirdFourth, lastFourth, firstThreeFourths, lastThreeFourths, From 498d7873f5a44624664e86e58e44d999cd9d27c1 Mon Sep 17 00:00:00 2001 From: Nikhil Verma Date: Fri, 1 Nov 2024 00:20:05 -0400 Subject: [PATCH 5/6] fix indentation and remove shortcut --- Rectangle/WindowAction.swift | 2 -- .../ChangeSizeCalculation.swift | 30 ++++++++++++------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Rectangle/WindowAction.swift b/Rectangle/WindowAction.swift index 540d03b5..06009261 100644 --- a/Rectangle/WindowAction.swift +++ b/Rectangle/WindowAction.swift @@ -461,8 +461,6 @@ enum WindowAction: Int, Codable { case .centerThird: return Shortcut( ctrl|alt, kVK_ANSI_F ) case .lastTwoThirds: return Shortcut( ctrl|alt, kVK_ANSI_T ) case .lastThird: return Shortcut( ctrl|alt, kVK_ANSI_G ) - case .largerWidth: return Shortcut( ctrl|alt|shift, kVK_ANSI_Equal ) - case .smallerWidth: return Shortcut( ctrl|alt|shift, kVK_ANSI_Minus ) default: return nil } } diff --git a/Rectangle/WindowCalculation/ChangeSizeCalculation.swift b/Rectangle/WindowCalculation/ChangeSizeCalculation.swift index 7f892214..3df9389a 100644 --- a/Rectangle/WindowCalculation/ChangeSizeCalculation.swift +++ b/Rectangle/WindowCalculation/ChangeSizeCalculation.swift @@ -28,12 +28,12 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation let sizeOffset: CGFloat switch params.action { - case .larger, .largerWidth: - sizeOffset = sizeOffsetAbs - case .smaller, .smallerWidth: - sizeOffset = -sizeOffsetAbs - default: - sizeOffset = 0 + case .larger, .largerWidth: + sizeOffset = sizeOffsetAbs + case .smaller, .smallerWidth: + sizeOffset = -sizeOffsetAbs + default: + sizeOffset = 0 } let visibleFrameOfScreen = params.visibleFrameOfScreen @@ -48,11 +48,15 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation resizedWindowRect.origin.x = resizedWindowRect.minX - floor(sizeOffset / 2.0) if curtainChangeSize { - resizedWindowRect = againstLeftAndRightScreenEdges(originalWindowRect: window.rect, resizedWindowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) + resizedWindowRect = againstLeftAndRightScreenEdges( + originalWindowRect: window.rect, + resizedWindowRect: resizedWindowRect, + visibleFrameOfScreen: visibleFrameOfScreen + ) } if resizedWindowRect.width >= visibleFrameOfScreen.width { - resizedWindowRect.size.width = visibleFrameOfScreen.width + resizedWindowRect.size.width = visibleFrameOfScreen.width } } @@ -63,12 +67,16 @@ class ChangeSizeCalculation: WindowCalculation, ChangeWindowDimensionCalculation resizedWindowRect.origin.y = resizedWindowRect.minY - floor(sizeOffset / 2.0) if curtainChangeSize { - resizedWindowRect = againstTopAndBottomScreenEdges(originalWindowRect: window.rect, resizedWindowRect: resizedWindowRect, visibleFrameOfScreen: visibleFrameOfScreen) + resizedWindowRect = againstTopAndBottomScreenEdges( + originalWindowRect: window.rect, + resizedWindowRect: resizedWindowRect, + visibleFrameOfScreen: visibleFrameOfScreen + ) } if resizedWindowRect.height >= visibleFrameOfScreen.height { - resizedWindowRect.size.height = visibleFrameOfScreen.height - resizedWindowRect.origin.y = params.window.rect.minY + resizedWindowRect.size.height = visibleFrameOfScreen.height + resizedWindowRect.origin.y = params.window.rect.minY } } From 541bc6268d5661e6929b97a14af7d2fe7368c6de Mon Sep 17 00:00:00 2001 From: Nikhil Verma Date: Fri, 1 Nov 2024 00:55:54 -0400 Subject: [PATCH 6/6] Added documentation --- TerminalCommands.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/TerminalCommands.md b/TerminalCommands.md index 314e92fd..42b127db 100644 --- a/TerminalCommands.md +++ b/TerminalCommands.md @@ -23,6 +23,7 @@ The preferences window is purposefully slim, but there's a lot that can be modif - [Make Smaller limits](#make-smaller-limits) - [Make Smaller/Make Larger size increments](#make-smallermake-larger-size-increments) - [Make Smaller/Make Larger "curtain resize" with gaps](#make-smallermake-larger-curtain-resize-with-gaps) +- [Make Smaller/Make Larger width only](#make-smallermake-larger-width-only) - [Disabling window restore when moving windows](#disabling-window-restore-when-moving-windows) - [Changing the margin for the snap areas](#changing-the-margin-for-the-snap-areas) - [Setting gaps at the screen edges](#setting-gaps-at-the-screen-edges) @@ -333,6 +334,17 @@ By default, windows touching the edge of the screen will keep those shared edges defaults write com.knollsoft.Rectangle curtainChangeSize -int 2 ``` +## Make Smaller/Make Larger width only + +By default, "Make Smaller" and "Make Larger" change both, the window height and the window width. If you only want to change the window width without changing window height, configure shortcuts for the _largerWidth_ and _smallerWidth_ commands. + +For example, if you want to assign `ctrl option ]` to _largerWidth_ and `ctrl option [` to _smallerWidth_, the commands would be: + +```bash +defaults write com.knollsoft.Rectangle largerWidth -dict-add keyCode -float 30 modifierFlags -float 786432 +defaults write com.knollsoft.Rectangle smallerWidth -dict-add keyCode -float 33 modifierFlags -float 786432 +``` + ## Disabling window restore when moving windows ```bash