Skip to content

Commit 9733cf7

Browse files
committed
Refactor DisplayManager API and remove unused methods
1 parent 79cf5b7 commit 9733cf7

File tree

2 files changed

+20
-320
lines changed

2 files changed

+20
-320
lines changed

Sources/Example/main.swift

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ func testDisplayManager() {
88
let displayManager = DisplayManager.shared
99

1010
// Test display count
11-
let count = displayManager.displayCount
12-
print("✅ Display count: \(count)")
11+
let displays = displayManager.getAll()
12+
print("✅ Display count: \(displays.count)")
1313

1414
// Test primary display
15-
if let primary = displayManager.getPrimaryDisplay() {
15+
if let primary = displayManager.getPrimary() {
1616
print("✅ Primary display: \(primary.name)")
1717
print(" Size: \(primary.size.width) x \(primary.size.height)")
1818
print(" Scale: \(primary.scaleFactor)x")
@@ -24,32 +24,12 @@ func testDisplayManager() {
2424
print("❌ No primary display found")
2525
}
2626

27+
displayManager.get(withId: "aaa")
28+
2729
// Test cursor position
2830
let cursor = displayManager.getCursorPosition()
2931
print("✅ Cursor position: (\(cursor.x), \(cursor.y))")
3032

31-
// Test multiple displays
32-
if displayManager.hasMultipleDisplays {
33-
print("✅ Multiple displays detected")
34-
let allDisplays = displayManager.getAllDisplays()
35-
for (index, display) in allDisplays.displays.enumerated() {
36-
print(
37-
" Display \(index + 1): \(display.name) (\(display.size.width)x\(display.size.height))"
38-
)
39-
}
40-
} else {
41-
print("ℹ️ Single display system")
42-
}
43-
44-
// Test display under cursor
45-
if let displayUnderCursor = displayManager.getDisplayUnderCursor() {
46-
print("✅ Display under cursor: \(displayUnderCursor.name)")
47-
}
48-
49-
// Test virtual screen bounds
50-
let virtualBounds = displayManager.getVirtualScreenBounds()
51-
print("✅ Virtual screen bounds: \(virtualBounds.width) x \(virtualBounds.height)")
52-
5333
print("✅ DisplayManager test completed successfully")
5434
print()
5535
}

Sources/NativeAPI/DisplayManager.swift

Lines changed: 15 additions & 295 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@ public class DisplayManager: @unchecked Sendable {
99
private init() {}
1010

1111
/// Get all available displays
12-
/// - Returns: DisplayList containing all system displays
13-
public func getAllDisplays() -> DisplayList {
12+
/// - Returns: Array of Display objects containing all system displays
13+
public func getAll() -> [Display] {
1414
let cList = native_display_manager_get_all()
15-
return DisplayList(cList)
15+
var result: [Display] = []
16+
for i in 0..<cList.count {
17+
let cDisplay = cList.displays.advanced(by: i).pointee
18+
result.append(Display(cDisplay))
19+
}
20+
return result
1621
}
1722

1823
/// Get the primary display
1924
/// - Returns: The primary display, or nil if no displays are available
20-
public func getPrimaryDisplay() -> Display? {
25+
public func getPrimary() -> Display? {
2126
let cDisplay = native_display_manager_get_primary()
2227
// Check if we got a valid display (assuming id is not null for valid displays)
2328
guard cDisplay.id != nil else { return nil }
@@ -34,302 +39,17 @@ public class DisplayManager: @unchecked Sendable {
3439
/// Find display containing the specified point
3540
/// - Parameter point: The point to search for
3641
/// - Returns: Display containing the point, or nil if no display contains the point
37-
public func getDisplay(containing point: Point) -> Display? {
38-
let displays = getAllDisplays()
39-
return displays.displays.first { $0.contains(point: point) }
42+
public func get(containing point: Point) -> Display? {
43+
let displays = getAll()
44+
return displays.first { $0.contains(point: point) }
4045
}
4146

4247
/// Find display by ID
4348
/// - Parameter id: The display ID to search for
4449
/// - Returns: Display with matching ID, or nil if not found
45-
public func getDisplay(withId id: String) -> Display? {
46-
let displays = getAllDisplays()
47-
return displays.display(withId: id)
48-
}
49-
50-
/// Get display at the specified index
51-
/// - Parameter index: The display index
52-
/// - Returns: Display at the index, or nil if index is out of bounds
53-
public func getDisplay(at index: Int) -> Display? {
54-
let displays = getAllDisplays()
55-
return displays.display(at: index)
56-
}
57-
58-
/// Get the display that currently contains the cursor
59-
/// - Returns: Display containing the cursor, or primary display if cursor is outside all displays
60-
public func getDisplayUnderCursor() -> Display? {
61-
let cursorPosition = getCursorPosition()
62-
return getDisplay(containing: cursorPosition) ?? getPrimaryDisplay()
63-
}
64-
65-
/// Get the number of available displays
66-
/// - Returns: Number of displays in the system
67-
public var displayCount: Int {
68-
let displays = getAllDisplays()
69-
return displays.count
70-
}
71-
72-
/// Check if multiple displays are available
73-
/// - Returns: true if more than one display is available
74-
public var hasMultipleDisplays: Bool {
75-
return displayCount > 1
50+
public func get(withId id: String) -> Display? {
51+
let displays = getAll()
52+
return displays.first { $0.id == id }
7653
}
7754

78-
/// Get total virtual screen bounds (bounding box of all displays)
79-
/// - Returns: Rectangle encompassing all displays
80-
public func getVirtualScreenBounds() -> Rectangle {
81-
let displays = getAllDisplays().displays
82-
guard !displays.isEmpty else {
83-
return Rectangle(x: 0, y: 0, width: 0, height: 0)
84-
}
85-
86-
var minX = Double.greatestFiniteMagnitude
87-
var minY = Double.greatestFiniteMagnitude
88-
var maxX = -Double.greatestFiniteMagnitude
89-
var maxY = -Double.greatestFiniteMagnitude
90-
91-
for display in displays {
92-
let bounds = display.bounds
93-
minX = min(minX, bounds.x)
94-
minY = min(minY, bounds.y)
95-
maxX = max(maxX, bounds.x + bounds.width)
96-
maxY = max(maxY, bounds.y + bounds.height)
97-
}
98-
99-
return Rectangle(
100-
x: minX,
101-
y: minY,
102-
width: maxX - minX,
103-
height: maxY - minY
104-
)
105-
}
106-
}
107-
108-
// MARK: - Convenience Methods
109-
110-
extension DisplayManager {
111-
/// Get all displays sorted by their position (left to right, top to bottom)
112-
/// - Returns: Array of displays sorted by position
113-
public func getDisplaysSortedByPosition() -> [Display] {
114-
let displays = getAllDisplays().displays
115-
return displays.sorted { (display1, display2) in
116-
if display1.position.y != display2.position.y {
117-
return display1.position.y < display2.position.y
118-
}
119-
return display1.position.x < display2.position.x
120-
}
121-
}
122-
123-
/// Get all displays sorted by size (largest first)
124-
/// - Returns: Array of displays sorted by size
125-
public func getDisplaysSortedBySize() -> [Display] {
126-
let displays = getAllDisplays().displays
127-
return displays.sorted { (display1, display2) in
128-
let area1 = display1.size.width * display1.size.height
129-
let area2 = display2.size.width * display2.size.height
130-
return area1 > area2
131-
}
132-
}
133-
134-
/// Get all non-primary displays
135-
/// - Returns: Array of displays that are not primary
136-
public func getSecondaryDisplays() -> [Display] {
137-
let displays = getAllDisplays().displays
138-
return displays.filter { !$0.isPrimary }
139-
}
140-
141-
/// Find displays with specific orientation
142-
/// - Parameter orientation: The orientation to filter by
143-
/// - Returns: Array of displays with the specified orientation
144-
public func getDisplays(withOrientation orientation: DisplayOrientation) -> [Display] {
145-
let displays = getAllDisplays().displays
146-
return displays.filter { $0.orientation == orientation }
147-
}
148-
149-
/// Find displays with minimum resolution
150-
/// - Parameters:
151-
/// - width: Minimum width in logical pixels
152-
/// - height: Minimum height in logical pixels
153-
/// - Returns: Array of displays meeting the minimum resolution criteria
154-
public func getDisplays(withMinimumResolution width: Double, height: Double) -> [Display] {
155-
let displays = getAllDisplays().displays
156-
return displays.filter { $0.size.width >= width && $0.size.height >= height }
157-
}
158-
159-
/// Find displays with specific scale factor
160-
/// - Parameter scaleFactor: The scale factor to match
161-
/// - Returns: Array of displays with the specified scale factor
162-
public func getDisplays(withScaleFactor scaleFactor: Double) -> [Display] {
163-
let displays = getAllDisplays().displays
164-
var result: [Display] = []
165-
for display in displays {
166-
let difference = display.scaleFactor - scaleFactor
167-
if (difference < 0 ? -difference : difference) < 0.01 {
168-
result.append(display)
169-
}
170-
}
171-
return result
172-
}
173-
174-
/// Get display statistics
175-
/// - Returns: Dictionary containing various display statistics
176-
public func getDisplayStatistics() -> [String: Any] {
177-
let displays = getAllDisplays().displays
178-
179-
guard !displays.isEmpty else {
180-
return [:]
181-
}
182-
183-
let totalArea = displays.reduce(0.0) { $0 + ($1.size.width * $1.size.height) }
184-
let averageWidth = displays.reduce(0.0) { $0 + $1.size.width } / Double(displays.count)
185-
let averageHeight = displays.reduce(0.0) { $0 + $1.size.height } / Double(displays.count)
186-
let averageScaleFactor =
187-
displays.reduce(0.0) { $0 + $1.scaleFactor } / Double(displays.count)
188-
189-
let landscapeCount = displays.filter { $0.isLandscape }.count
190-
let portraitCount = displays.filter { $0.isPortrait }.count
191-
192-
return [
193-
"totalDisplays": displays.count,
194-
"primaryDisplays": displays.filter { $0.isPrimary }.count,
195-
"totalArea": totalArea,
196-
"averageWidth": averageWidth,
197-
"averageHeight": averageHeight,
198-
"averageScaleFactor": averageScaleFactor,
199-
"landscapeCount": landscapeCount,
200-
"portraitCount": portraitCount,
201-
"virtualScreenBounds": getVirtualScreenBounds(),
202-
]
203-
}
204-
}
205-
206-
// MARK: - Window Positioning Helpers
207-
208-
extension DisplayManager {
209-
/// Find the best display for positioning a window
210-
/// - Parameters:
211-
/// - windowRect: The desired window rectangle
212-
/// - preferPrimary: Whether to prefer the primary display
213-
/// - Returns: The best display for the window, or primary display as fallback
214-
public func getBestDisplay(for windowRect: Rectangle, preferPrimary: Bool = false) -> Display? {
215-
if preferPrimary, let primaryDisplay = getPrimaryDisplay() {
216-
return primaryDisplay
217-
}
218-
219-
let displays = getAllDisplays().displays
220-
221-
// Find display with maximum intersection area
222-
var bestDisplay: Display?
223-
var maxIntersectionArea = 0.0
224-
225-
for display in displays {
226-
if let intersection = display.intersection(with: windowRect) {
227-
let intersectionArea = intersection.width * intersection.height
228-
if intersectionArea > maxIntersectionArea {
229-
maxIntersectionArea = intersectionArea
230-
bestDisplay = display
231-
}
232-
}
233-
}
234-
235-
return bestDisplay ?? getPrimaryDisplay()
236-
}
237-
238-
/// Center a rectangle on a specific display
239-
/// - Parameters:
240-
/// - size: The size of the rectangle to center
241-
/// - display: The display to center on (uses primary if nil)
242-
/// - Returns: Centered rectangle, or nil if no display is available
243-
public func centerRect(size: Size, on display: Display? = nil) -> Rectangle? {
244-
let targetDisplay = display ?? getPrimaryDisplay()
245-
guard let display = targetDisplay else { return nil }
246-
247-
let workArea = display.workArea
248-
let x = workArea.x + (workArea.width - size.width) / 2
249-
let y = workArea.y + (workArea.height - size.height) / 2
250-
251-
return Rectangle(x: x, y: y, width: size.width, height: size.height)
252-
}
253-
254-
/// Ensure a rectangle is visible on screen (move it if necessary)
255-
/// - Parameter rect: The rectangle to make visible
256-
/// - Returns: Adjusted rectangle that is visible on screen
257-
public func ensureRectangleVisible(_ rect: Rectangle) -> Rectangle {
258-
let virtualBounds = getVirtualScreenBounds()
259-
260-
var adjustedRect = rect
261-
262-
// Ensure the rectangle doesn't go beyond virtual screen bounds
263-
if adjustedRect.x < virtualBounds.x {
264-
adjustedRect = Rectangle(
265-
x: virtualBounds.x,
266-
y: adjustedRect.y,
267-
width: adjustedRect.width,
268-
height: adjustedRect.height
269-
)
270-
}
271-
272-
if adjustedRect.y < virtualBounds.y {
273-
adjustedRect = Rectangle(
274-
x: adjustedRect.x,
275-
y: virtualBounds.y,
276-
width: adjustedRect.width,
277-
height: adjustedRect.height
278-
)
279-
}
280-
281-
if adjustedRect.x + adjustedRect.width > virtualBounds.x + virtualBounds.width {
282-
adjustedRect = Rectangle(
283-
x: virtualBounds.x + virtualBounds.width - adjustedRect.width,
284-
y: adjustedRect.y,
285-
width: adjustedRect.width,
286-
height: adjustedRect.height
287-
)
288-
}
289-
290-
if adjustedRect.y + adjustedRect.height > virtualBounds.y + virtualBounds.height {
291-
adjustedRect = Rectangle(
292-
x: adjustedRect.x,
293-
y: virtualBounds.y + virtualBounds.height - adjustedRect.height,
294-
width: adjustedRect.width,
295-
height: adjustedRect.height
296-
)
297-
}
298-
299-
return adjustedRect
300-
}
301-
}
302-
303-
// MARK: - Static Convenience Methods
304-
305-
extension DisplayManager {
306-
/// Quick access to all displays
307-
/// - Returns: Array of all displays
308-
public static func getAllDisplays() -> [Display] {
309-
return DisplayManager.shared.getAllDisplays().displays
310-
}
311-
312-
/// Quick access to primary display
313-
/// - Returns: Primary display, or nil if unavailable
314-
public static func getPrimaryDisplay() -> Display? {
315-
return DisplayManager.shared.getPrimaryDisplay()
316-
}
317-
318-
/// Quick access to cursor position
319-
/// - Returns: Current cursor position
320-
public static func getCursorPosition() -> Point {
321-
return DisplayManager.shared.getCursorPosition()
322-
}
323-
324-
/// Quick access to display count
325-
/// - Returns: Number of displays
326-
public static var displayCount: Int {
327-
return DisplayManager.shared.displayCount
328-
}
329-
330-
/// Quick check for multiple displays
331-
/// - Returns: true if multiple displays are available
332-
public static var hasMultipleDisplays: Bool {
333-
return DisplayManager.shared.hasMultipleDisplays
334-
}
33555
}

0 commit comments

Comments
 (0)