forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSuggestionPanelController.swift
More file actions
90 lines (82 loc) · 2.95 KB
/
SuggestionPanelController.swift
File metadata and controls
90 lines (82 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import AppKit
import DisplayLink
import SwiftUI
@MainActor
final class SuggestionPanelController {
private lazy var window = {
let it = NSWindow(
contentRect: .zero,
styleMask: .borderless,
backing: .buffered,
defer: false
)
it.isReleasedWhenClosed = false
it.isOpaque = false
it.backgroundColor = .white
it.level = .statusBar
it.contentView = NSHostingView(
rootView: SuggestionPanelView(viewModel: viewModel)
.allowsHitTesting(false)
.frame(width: 500, height: 300)
)
it.setIsVisible(true)
return it
}()
private var displayLinkTask: Task<Void, Never>?
private let viewModel = SuggestionPanelViewModel()
nonisolated init() {
Task { @MainActor in
displayLinkTask = Task {
for await _ in DisplayLink.createStream() {
self.updateWindowLocation()
}
}
}
}
/// Update the window location
///
/// - note:
private func updateWindowLocation() {
if let activeXcode = NSRunningApplication
.runningApplications(withBundleIdentifier: "com.apple.dt.Xcode")
.first(where: \.isActive)
{
let application = AXUIElementCreateApplication(activeXcode.processIdentifier)
if let focusElement: AXUIElement = try? application
.copyValue(key: kAXFocusedUIElementAttribute),
let parent: AXUIElement = try? focusElement.copyValue(key: kAXParentAttribute),
let positionValue: AXValue = try? parent
.copyValue(key: kAXPositionAttribute),
let sizeValue: AXValue = try? parent
.copyValue(key: kAXSizeAttribute)
{
var position: CGPoint = .zero
let foundPosition = AXValueGetValue(positionValue, .cgPoint, &position)
var size: CGSize = .zero
let foundSize = AXValueGetValue(sizeValue, .cgSize, &size)
let screen = NSScreen.screens.first
var frame = CGRect(origin: position, size: size)
if foundSize, foundPosition, let screen {
frame.origin = .init(
x: frame.maxX + 2,
y: screen.frame.height - frame.minY - 300
)
frame.size = .init(width: 500, height: 300)
window.alphaValue = 1
window.setFrame(frame, display: false, animate: true)
return
}
}
}
window.alphaValue = 0
}
}
final class SuggestionPanelViewModel: ObservableObject {
@Published var suggetion: String = "Hello World"
}
struct SuggestionPanelView: View {
@ObservedObject var viewModel: SuggestionPanelViewModel
var body: some View {
Text(viewModel.suggetion)
}
}