2016-11-23 2 views
0

Ich versuche, eine OS X-Anwendung zu erstellen, die eine externe Anwendung (d. H. TextEdit) auf der laufenden Anwendung ohne Schwerpunkt zu schweben, aber nie verschwinden lässt. Im Grunde versuche ich die ForceQuit-Anwendung nachzuahmen (drücke Option-Befehl-esc, um sie zu sehen), wo sie immer oben ist, aber nicht immer den Fokus hat.Making externe App schweben über OS X-Anwendung

Was mache ich jetzt mit begrenztem Erfolg, ist dies:

ein NSTimer Erstellen zu halten es oben setzen:

_timer = [NSTimer scheduleTimerWithTimeInterval:0.1 target:self selector:@selector(keepTextEditOnTop) userInfo:nil repeats:YES]; 

...

Bringt textEdit nach vorne:

- (void)keepTextEditOnTop { 
    AXUIElementRef appRef = AXUIElementCreateApplication(_textEditProcessID); 
    AXUIElementSetAttributeValue(appRef, kAXFrontmostAttribute, kCFBooleanTrue); 
} 

Das wird textEdit Fenster an der Spitze bleiben, wenn Sie darauf klicken aus (es verlieren machen Fokus). Aber es gibt zwei Probleme. 1.) Es wird kurz blinken und es wieder in den Vordergrund bringen 2.) Es wird im Wesentlichen immer den Fokus behalten, so dass Sie nicht mit der zugrunde liegenden App interagieren können.

Vom appRef, können Sie das Fenster:

CFArrayRef windowList; 
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute, (CFTypeRef *)&windowList); 

AXUIElementRef windowRef = (AXUIElementRef) CFArrayGetValueAtIndex(windowList, 0); 

Aber ich glaube nicht, es möglich sein wird, sie in eine NSWindow zu konvertieren. Wenn ich das könnte, könnte ich mir vorstellen, dass ich ein Kindfenster des Hauptfensters oder vielleicht nur ein schwebendes Fenster machen könnte.

Irgendwelche Ideen, wie dies getan werden könnte?

Bearbeiten- Hinzufügen Vorschläge von @TheDarkKnight

Ich versuche dies:

- (void)testing{ 

    CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 
    for (NSMutableDictionary* entry in (__bridge NSArray*)windowList) 
    { 
     NSString* ownerName = [entry objectForKey:(__bridge id)kCGWindowOwnerName]; 
     NSString *windowNum = [entry objectForKey:(__bridge id)kCGWindowNumber]; 
    if([ownerName isEqualToString:@"Sublime Text"]){ 
     [self holdToTheFront:[windowNum integerValue]]; 
    } 
} 
CFRelease(windowList); 

}

ein EXC_BAD_ACCESS Fehler bekommen, wie unten im Kommentar bemerkt:

- (void)holdToTheFront:(NSInteger)winNum { 
    objc_object* nsviewObject = reinterpret_cast<objc_object *>(winNum); 

    //Getting a "Thread 1:EXC_BAD_ACCESS (code=1, address=0x18)" at the line below: 
    NSWindow* nsWindowObject = ((id (*)(id, SEL))objc_msgSend)((__bridge NSView *)nsviewObject, sel_registerName("window")); 

    int NSWindowCollectionBehaviorCanJoinAllSpaces = 1 << 0; 
    ((id (*)(id, SEL, NSUInteger))objc_msgSend)(nsWindowObject, sel_registerName("setCollectionBehavior:"), NSWindowCollectionBehaviorCanJoinAllSpaces); 
} 

Antwort

0

Für eine Anwendung wi ndow sichtbar sein auf allen Räumen, können Sie dies so etwas wie tun: -

objc_object* nsviewObject = reinterpret_cast<objc_object *>(windowObject); 
objc_object* nsWindowObject = objc_msgSend(nsviewObject, sel_registerName("window")); 
int NSWindowCollectionBehaviorCanJoinAllSpaces = 1 << 0; 
objc_msgSend(nsWindowObject, sel_registerName("setCollectionBehavior:"), NSWindowCollectionBehaviorCanJoinAllSpaces); 

Wo windowObject ist die windowNumber des Anwendungsfensters Sie wollen oben bleiben.

+0

Danke! Ich werde es am Morgen versuchen. – user3564870

+0

Ich glaube nicht, dass es möglich ist, eine Fensternummer für Fenster zu erhalten, die die App nicht besitzt. Dann gäbe es die Annahme, dass die externe App Cocoa ist. – user3564870

+0

Hilft dies [http://stackoverflow.com/questions/2107657/mac-cocoa-getting-a-list-of-windows-using-accessibility-api]? – TheDarkKnight