Skip to content

Instantly share code, notes, and snippets.

@tylerlong
Last active July 19, 2025 18:34
Show Gist options
  • Select an option

  • Save tylerlong/b5cee1d57920e705fa2df0b3f0990b48 to your computer and use it in GitHub Desktop.

Select an option

Save tylerlong/b5cee1d57920e705fa2df0b3f0990b48 to your computer and use it in GitHub Desktop.

Revisions

  1. tylerlong revised this gist Sep 29, 2016. 1 changed file with 46 additions and 0 deletions.
    46 changes: 46 additions & 0 deletions AXWindow.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    import Cocoa

    class AXWindow {

    let app: AXUIElement
    let window: AXUIElement

    init(app: AXUIElement, window: AXUIElement) {
    self.app = app
    self.window = window
    }

    class func initWithCGWindow(cgWindow: CGWindow) -> AXWindow? {
    let app = AXUIElementCreateApplication(pid_t(cgWindow.ownerPID)).takeRetainedValue();
    let windows: [AXUIElement] = app.getAttribute("Windows")
    for window in windows {
    let title: String = window.getAttribute("Title")
    if title != cgWindow.name {
    continue
    }
    let point: NSPoint = window.getAttribute("Position")
    if point != cgWindow.bounds.origin {
    continue
    }
    let size: NSSize = window.getAttribute("Size")
    if size != cgWindow.bounds.size {
    continue
    }
    return AXWindow(app: app, window: window)
    }
    return nil
    }

    func setPosition(view: NSView) {
    let screenRect = view.screenRect()
    self.window.setBounds(screenRect)
    toFrontQueue.push(self)
    }

    func bringToFront() {
    Swift.print("bringToFront")
    self.app.setAttribute("Frontmost", value: true)
    self.window.setAttribute("Main", value: true)
    }

    }
  2. tylerlong created this gist Sep 29, 2016.
    48 changes: 48 additions & 0 deletions AppkitExtensions.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    import Cocoa

    extension AXValue {

    class func initWith(t: Any) -> AXValue? {
    var t = t
    switch t {
    case is CGPoint:
    return AXValueCreate(AXValueType(rawValue: kAXValueCGPointType)!, &t)!.takeRetainedValue()
    case is CGSize:
    return AXValueCreate(AXValueType(rawValue: kAXValueCGSizeType)!, &t)!.takeRetainedValue()
    default:
    return nil
    }
    }

    func convertTo<T>() -> T {
    let ptr = UnsafeMutablePointer<T>.alloc(1)
    AXValueGetValue(self, AXValueGetType(self), ptr)
    let val = ptr.memory
    ptr.destroy()
    return val
    }

    }

    extension AXUIElement {

    func getAttribute<T>(key: String) -> T {
    var ptr: AnyObject?
    AXUIElementCopyAttributeValue(self, "AX\(key)", &ptr)
    if key == "Size" || key == "Position" {
    let val = ptr as! AXValue
    return val.convertTo()
    }
    return ptr as! T
    }

    func setAttribute<T: AnyObject>(key: String, value: T) {
    AXUIElementSetAttributeValue(self, "AX\(key)", value)
    }

    func setBounds(bounds: NSRect) { // 移动窗口并调整窗口大小
    setAttribute("Position", value: AXValue.initWith(bounds.origin)!)
    setAttribute("Size", value: AXValue.initWith(bounds.size)!)
    }

    }