Skip to main content
Glama
ScreenSizeHelper.swift3.78 kB
import XCTest struct ScreenSizeHelper { private static var cachedSize: (Float, Float)? private static var lastAppBundleId: String? private static var lastOrientation: UIDeviceOrientation? static func physicalScreenSize() -> (Float, Float) { let springboardBundleId = "com.apple.springboard" let app = RunningApp.getForegroundApp() ?? XCUIApplication(bundleIdentifier: springboardBundleId) do { let currentAppBundleId = app.bundleID let currentOrientation = XCUIDevice.shared.orientation if let cached = cachedSize, currentAppBundleId == lastAppBundleId, currentOrientation == lastOrientation { NSLog("Returning cached screen size") return cached } let dict = try app.snapshot().dictionaryRepresentation let axFrame = AXElement(dict).frame // Safely unwrap width/height guard let width = axFrame["Width"], let height = axFrame["Height"] else { NSLog("Frame keys missing, falling back to SpringBoard.") let springboard = XCUIApplication(bundleIdentifier: springboardBundleId) let size = springboard.frame.size return (Float(size.width), Float(size.height)) } let screenSize = CGSize(width: width, height: height) let size = (Float(screenSize.width), Float(screenSize.height)) // Cache results cachedSize = size lastAppBundleId = currentAppBundleId lastOrientation = currentOrientation return size } catch let error { NSLog("Failure while getting screen size: \(error), falling back to get springboard size.") let application = XCUIApplication( bundleIdentifier: springboardBundleId) let screenSize = application.frame.size return (Float(screenSize.width), Float(screenSize.height)) } } private static func actualOrientation() -> UIDeviceOrientation { let orientation = XCUIDevice.shared.orientation if orientation == .unknown { // If orientation is "unknown", we assume it is "portrait" to // work around https://stackoverflow.com/q/78932288/7009800 return UIDeviceOrientation.portrait } return orientation } /// Takes device orientation into account. static func actualScreenSize() throws -> (Float, Float, UIDeviceOrientation) { let orientation = actualOrientation() let (width, height) = physicalScreenSize() let (actualWidth, actualHeight) = switch orientation { case .portrait, .portraitUpsideDown: (width, height) case .landscapeLeft, .landscapeRight: (height, width) case .faceDown, .faceUp: (width, height) case .unknown: throw AppError( message: "Unsupported orientation: \(orientation)") @unknown default: throw AppError( message: "Unsupported orientation: \(orientation)") } return (actualWidth, actualHeight, orientation) } static func orientationAwarePoint( width: Float, height: Float, point: CGPoint ) -> CGPoint { let orientation = actualOrientation() return switch orientation { case .portrait: point case .landscapeLeft: CGPoint(x: CGFloat(width) - point.y, y: CGFloat(point.x)) case .landscapeRight: CGPoint(x: CGFloat(point.y), y: CGFloat(height) - point.x) default: fatalError("Not implemented yet") } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mobile-dev-inc/Maestro'

If you have feedback or need assistance with the MCP directory API, please join our Discord server