macOS, how resize window across screens?

Viewed 48

I'm trying to programmatically resize macOS windows. Similar to Rectangle.

I have the basic resizing code working, for example, move the window to the right half, and when there is only one screen it works fine, however when I try to resize with two screens (in a vertical layout) the math does not work:

public func moveRight() {
    guard let frontmostWindowElement = AccessibilityElement.frontmostWindow()
    else {
      NSSound.beep()
      return
    }

    let screens = screenDetector.detectScreens(using: frontmostWindowElement)

    guard let usableScreens = screens else {
      NSSound.beep()
      print("Unable to obtain usable screens")
      return
    }

    let screenFrame = usableScreens.currentScreen.adjustedVisibleFrame
    print("Visible frame of current screen \(usableScreens.visibleFrameOfCurrentScreen)")

    let halfPosition = CGPoint(x: screenFrame.origin.x + screenFrame.width / 2, y: -screenFrame.origin.y)
    let halfSize = CGSize(width: screenFrame.width / 2, height: screenFrame.height)

    frontmostWindowElement.set(size: halfSize)
    frontmostWindowElement.set(position: halfPosition)
    frontmostWindowElement.set(size: halfSize)

    print("movedWindowRect \(frontmostWindowElement.rectOfElement())")
  }

If my window is on the main screen then the resizing works correctly, however if it is a screen below (#3 in the diagram below) then the Y coordinate ends up in the top monitor (#2 or #1 depending on x coordinate) instead of the original one.

The output of the code:

Visible frame of current screen (679.0, -800.0, 1280.0, 775.0)
Raw Frame (679.0, -800.0, 1280.0, 800.0)
movedWindowRect (1319.0, 25.0, 640.0, 775.0)

As far as I can see the problem lies in how Screens and windows are positioned:

enter image description here

I'm trying to understand how should I position the window so that it remains in the correct screen (#3), but having no luck so far, there doesn't seem to be any method to get the absolute screen dimensions to place the screen in the correct origin.

Any idea how can this be solved?

1 Answers

I figured it out, I completely missed one of the functions used in the AccessibilityElement class:

static func normalizeCoordinatesOf(_ rect: CGRect) -> CGRect {
    var normalizedRect = rect
    let frameOfScreenWithMenuBar = NSScreen.screens[0].frame as CGRect
    normalizedRect.origin.y = frameOfScreenWithMenuBar.height - rect.maxY
    return normalizedRect
  }

Basically, since everything is calculated based on the main screen then there is no other option than to take the coordinates of that one and then offset to get the real position of the screen element.

Related