Search in sources :

Example 1 with NSString

use of org.rococoa.cocoa.foundation.NSString in project HearthStats.net-Uploader by HearthStats.

the class ProgramHelperOsx method getHSWindowBounds.

@Override
public Rectangle getHSWindowBounds() {
    final NSAutoreleasePool pool = NSAutoreleasePool.new_();
    try {
        if (_pid == 0) {
            _pid = findProgramPid(_bundleIdentifier);
        }
        if (_windowId == 0) {
            _windowId = findWindow(_pid);
        }
        // Instead, obtain a dictionary of all on-screen windows from Quartz Window Services, which will include all running applications.
        CFArrayRef originalArray = CoreGraphicsLibrary.INSTANCE.CGWindowListCopyWindowInfo(CGWindow.kCGWindowListExcludeDesktopElements | CGWindow.kCGWindowListOptionOnScreenOnly, 0);
        long count = CoreFoundationLibrary.INSTANCE.CFArrayGetCount(originalArray);
        for (long i = 0; i < count; i++) {
            // Obtain a CFDictionary containing this window's information dictionary
            Pointer pointer = CoreFoundationLibrary.INSTANCE.CFArrayGetValueAtIndex(originalArray, i);
            CFDictionaryRef dictionaryRef = new CFDictionaryRef(pointer);
            // Determine the ID of this window
            NSString kCGWindowNumber = CoreGraphicsLibrary.kCGWindowNumber;
            Pointer windowNumberPointer = CoreFoundationLibrary.INSTANCE.CFDictionaryGetValue(dictionaryRef, kCGWindowNumber.id());
            IntByReference windowIdRef = new IntByReference();
            CoreFoundationLibrary.INSTANCE.CFNumberGetValue(windowNumberPointer, CoreFoundationLibrary.CFNumberType.kCFNumberIntType, windowIdRef.getPointer());
            int thisWindowId = windowIdRef.getValue();
            if (thisWindowId == _windowId) {
                // Determine the bounds of this window
                NSString kCGWindowBounds = CoreGraphicsLibrary.kCGWindowBounds;
                Pointer boundPointer = CoreFoundationLibrary.INSTANCE.CFDictionaryGetValue(dictionaryRef, kCGWindowBounds.id());
                CoreGraphicsLibrary.CGRectRef rect = new CoreGraphicsLibrary.CGRectRef();
                boolean result = CoreGraphicsLibrary.INSTANCE.CGRectMakeWithDictionaryRepresentation(boundPointer, rect);
                int x = (int) rect.origin.x;
                int y = (int) rect.origin.y;
                int width = (int) rect.size.width;
                int height = (int) rect.size.height;
                // Determine height of the title bar, if present
                int titleHeight = determineWindowTitleHeight(height, width);
                debugLog.debug("Found Hearthstone window at x={} y={} width={} height={} title={}", x, y, width, height, titleHeight);
                return new Rectangle(x, y, width, height);
            }
        }
    } finally {
        pool.drain();
    }
    // Couldn't find the Hearthstone window so return null... this will break the calling code.
    debugLog.warn("Unable to find position of Hearthstone window.");
    return null;
}
Also used : IntByReference(com.sun.jna.ptr.IntByReference) Pointer(com.sun.jna.Pointer) NSString(org.rococoa.cocoa.foundation.NSString) NSAutoreleasePool(org.rococoa.cocoa.foundation.NSAutoreleasePool)

Example 2 with NSString

use of org.rococoa.cocoa.foundation.NSString in project HearthStats.net-Uploader by HearthStats.

the class ProgramHelperOsx method findWindow.

/**
     * <p>Finds the main Hearthstone window ID for the given process ID.</p>
     * <p>Will only return the window that matches expected characteristics of the main Hearthstone window, namely:</p>
     * <ul>
     *     <li>kCGWindowIsOnscreen = 1</li>
     *     <li>kCGWindowLayer = 0</li>
     *     <li>kCGWindowOwnerPID = [pid]</li>
     * </ul>
     *
     * @param pid The process ID of Hearthstone.
     * @return the window ID if found, or zero if no suitable window was found. It is normal for the window ID to be zero briefly during startup of Hearthstone.
     */
private int findWindow(int pid) {
    final NSAutoreleasePool pool = NSAutoreleasePool.new_();
    try {
        // Obtain a dictionary of all on-screen windows from Quartz Window Services, which will include all running applications.
        // Hearthstone typically has five or six windows, but only one or two are 'on screen' and it is those that we are interested in.
        final CFArrayRef originalArray = CoreGraphicsLibrary.INSTANCE.CGWindowListCopyWindowInfo(CGWindow.kCGWindowListExcludeDesktopElements | CGWindow.kCGWindowListOptionOnScreenOnly, 0);
        long count = CoreFoundationLibrary.INSTANCE.CFArrayGetCount(originalArray);
        for (long i = 0; i < count; i++) {
            // Obtain a CFDictionary containing this window's information dictionary
            Pointer pointer = CoreFoundationLibrary.INSTANCE.CFArrayGetValueAtIndex(originalArray, i);
            CFDictionaryRef dictionaryRef = new CFDictionaryRef(pointer);
            // Determine the process ID of this window
            NSString kCGWindowOwnerPID = CoreGraphicsLibrary.kCGWindowOwnerPID;
            Pointer pidPointer = CoreFoundationLibrary.INSTANCE.CFDictionaryGetValue(dictionaryRef, kCGWindowOwnerPID.id());
            NativeLongByReference longByReference = new NativeLongByReference();
            CoreFoundationLibrary.INSTANCE.CFNumberGetValue(pidPointer, CoreFoundationLibrary.CFNumberType.kCFNumberLongType, longByReference.getPointer());
            long pidLong = longByReference.getValue().longValue();
            if (pidLong == pid) {
                // This window is a Hearthstone window
                // When running in full-screen mode, Hearthstone has two windows: one for the game and one that appears to be a temporary desktop or space for the game to run in.
                // The game window always has a kCGWindowLayer of zero, whereas the desktop has a non-zero kCGWindowLayer.
                NSString kCGWindowLayer = CoreGraphicsLibrary.kCGWindowLayer;
                Pointer windowLayerPointer = CoreFoundationLibrary.INSTANCE.CFDictionaryGetValue(dictionaryRef, kCGWindowLayer.id());
                IntByReference windowLayerRef = new IntByReference();
                CoreFoundationLibrary.INSTANCE.CFNumberGetValue(windowLayerPointer, CoreFoundationLibrary.CFNumberType.kCFNumberFloatType, windowLayerRef.getPointer());
                int windowLayer = windowLayerRef.getValue();
                if (windowLayer == 0) {
                    // This window has a zero kCGWindowLayer so it must be the main Hearthstone window
                    NSString kCGWindowNumber = CoreGraphicsLibrary.kCGWindowNumber;
                    Pointer windowNumberPointer = CoreFoundationLibrary.INSTANCE.CFDictionaryGetValue(dictionaryRef, kCGWindowNumber.id());
                    IntByReference windowIdRef = new IntByReference();
                    CoreFoundationLibrary.INSTANCE.CFNumberGetValue(windowNumberPointer, CoreFoundationLibrary.CFNumberType.kCFNumberIntType, windowIdRef.getPointer());
                    int windowId = windowIdRef.getValue();
                    return windowId;
                }
            }
        }
        // No Hearthstone window was found
        return 0;
    } finally {
        pool.drain();
    }
}
Also used : IntByReference(com.sun.jna.ptr.IntByReference) NSAutoreleasePool(org.rococoa.cocoa.foundation.NSAutoreleasePool) Pointer(com.sun.jna.Pointer) NSString(org.rococoa.cocoa.foundation.NSString) NativeLongByReference(com.sun.jna.ptr.NativeLongByReference)

Aggregations

Pointer (com.sun.jna.Pointer)2 IntByReference (com.sun.jna.ptr.IntByReference)2 NSAutoreleasePool (org.rococoa.cocoa.foundation.NSAutoreleasePool)2 NSString (org.rococoa.cocoa.foundation.NSString)2 NativeLongByReference (com.sun.jna.ptr.NativeLongByReference)1