use of com.sun.jna.Pointer 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();
}
}
use of com.sun.jna.Pointer in project HearthStats.net-Uploader by HearthStats.
the class ProgramHelperOsx method getWindowImage.
/**
* <p>Gets a copy of the Hearthstone window with the provided window ID as an in-memory image.</p>
*
* @param windowId The window ID of Hearthstone, as reported by a call to Quartz Window Services
* @return An image of the window, or null if the window doesn't exist or is too small to be an active window.
*/
private BufferedImage getWindowImage(int windowId) {
// Create a CGRect with zero boundaries so that OS X automatically picks the correct size
CoreGraphicsLibrary.CGRect bounds = new CoreGraphicsLibrary.CGRect.CGRectByValue();
bounds.origin = new CoreGraphicsLibrary.CGPoint();
bounds.origin.x = 0;
bounds.origin.y = 0;
bounds.size = new CoreGraphicsLibrary.CGSize();
bounds.size.width = 0;
bounds.size.height = 0;
// Take a screenshot of the program window
ID imageRef = CoreGraphicsLibrary.INSTANCE.CGWindowListCreateImage(bounds, CoreGraphicsLibrary.kCGWindowListOptionIncludingWindow | CoreGraphicsLibrary.kCGWindowListExcludeDesktopElements, windowId, CoreGraphicsLibrary.kCGWindowImageBoundsIgnoreFraming | CoreGraphicsLibrary.kCGWindowImageNominalResolution);
// Convert the screenshot into a more useful ImageRep object, and retain the object so that it isn't lost before we extract the image data
NSBitmapImageRep imageRep = NSBitmapImageRep.CLASS.alloc().initWithCGImage(imageRef).initWithCGImage(imageRef);
imageRep.retain();
int width = imageRep.pixelsWide();
int height = imageRep.pixelsHigh();
int windowTitleHeight = determineWindowTitleHeight(height, width);
if (debugLog.isTraceEnabled()) {
debugLog.trace(" Window height={} width={} titleHeight={}", new Object[] { height, width, windowTitleHeight });
}
int heightWithoutTitle = height - windowTitleHeight;
Pointer bitmapPointer = imageRep.bitmapData();
if (bitmapPointer == null || bitmapPointer == Pointer.NULL) {
imageRep.release();
return null;
} else {
int[] data = bitmapPointer.getIntArray(0, width * height);
if (heightWithoutTitle > 512) {
BufferedImage image = new BufferedImage(width, heightWithoutTitle, BufferedImage.TYPE_INT_RGB);
// Start on row windowTitleHeight to exclude the window titlebar
int idx = windowTitleHeight * width;
// Manually write each pixel to the raster because OS X generates ARGB screenshots but BufferedImage expects RGB data.
WritableRaster raster = image.getRaster();
for (int y = 0; y < heightWithoutTitle; y++) {
for (int x = 0; x < width; x++) {
int pixel = data[idx++];
// Red is the second byte
raster.setSample(x, y, 0, pixel >> 8 & 0xFF);
// Green is the third byte
raster.setSample(x, y, 1, pixel >> 16 & 0xFF);
// Blue is the fourth byte
raster.setSample(x, y, 2, pixel >> 24 & 0xFF);
}
}
// Now that we have a copy of the image in a Java object it's safe to release the native pointers
Foundation.cfRelease(imageRef);
imageRep.release();
return image;
} else {
// The window is too small to generate an image
return null;
}
}
}
use of com.sun.jna.Pointer in project HearthStats.net-Uploader by HearthStats.
the class ProgramHelperWindows method getWindowHandle.
private HWND getWindowHandle() {
// Cache the window handle for five seconds to reduce CPU load and (possibly) minimise memory leaks
long currentTime = System.currentTimeMillis();
if (currentTime < lastWindowsHandleCheck + 5000) {
// It has been less than five seconds since the last check, so use the cached value
return windowHandle;
} else {
debugLog.debug("Updating window handle ({}ms since last update)", currentTime - lastWindowsHandleCheck);
lastWindowsHandleCheck = currentTime;
windowHandle = null;
}
User32.INSTANCE.EnumWindows(new WNDENUMPROC() {
@Override
public boolean callback(HWND hWnd, Pointer arg1) {
int titleLength = User32.INSTANCE.GetWindowTextLength(hWnd) + 1;
char[] title = new char[titleLength];
User32.INSTANCE.GetWindowText(hWnd, title, titleLength);
String wText = Native.toString(title);
if (wText.isEmpty()) {
return true;
}
PointerByReference pointer = new PointerByReference();
User32DLL.GetWindowThreadProcessId(hWnd, pointer);
Pointer process = Kernel32.OpenProcess(Kernel32.PROCESS_QUERY_INFORMATION | Kernel32.PROCESS_VM_READ, false, pointer.getValue());
Psapi.GetModuleBaseNameW(process, null, baseNameBuffer, STRING_BUFFER_LENGTH);
String baseNameString = Native.toString(baseNameBuffer);
// see https://github.com/JeromeDane/HearthStats.net-Uploader/issues/66#issuecomment-33829132
User32.INSTANCE.GetClassName(hWnd, classNameBuffer, STRING_BUFFER_LENGTH);
String classNameString = Native.toString(classNameBuffer);
if (baseNameString.equals(processName) && classNameString.equals("UnityWndClass")) {
windowHandle = hWnd;
if (windowHandleId == null) {
windowHandleId = windowHandle.toString();
if (lastKnownWindowHandleId == null || lastKnownWindowHandleId != windowHandleId) {
// The window handle has changed, so try to find the location the HearthStats executable. This is used to
// find the HS log file. Only compatible with Windows Vista and later, so we skip for Windows XP.
lastKnownWindowHandleId = windowHandleId;
if (Environment.isOsVersionAtLeast(6, 0)) {
debugLog.debug("Windows version is Vista or later so the location of the Hearthstone is being determined from the process");
Kernel32.QueryFullProcessImageNameW(process, 0, processFileNameBuffer, lpdwSize);
String processFileNameString = Native.toString(processFileNameBuffer);
if (processFileNameString != null) {
int lastSlash = processFileNameString.lastIndexOf('\\');
hearthstoneProcessFolder = processFileNameString.substring(0, lastSlash);
}
}
}
_notifyObserversOfChangeTo("Hearthstone window found with process name " + processName);
}
}
return true;
}
}, null);
// notify of window lost
if (windowHandle == null && windowHandleId != null) {
_notifyObserversOfChangeTo("Hearthstone window with process name " + processName + " closed");
windowHandleId = null;
}
return windowHandle;
}
use of com.sun.jna.Pointer in project HearthStats.net-Uploader by HearthStats.
the class JnaUtil method main.
public static void main(String[] args) throws InterruptedException {
String[] testStrs = { "Untitled-Notepad", "Untitled - Notepad", "Untitled - Notepad", "Java-Epic", "Java - Epic", "Fubars rule!", "The First Night", "New Tab", "Citrix X", "EHR PROD - SVC" };
for (String testStr : testStrs) {
Pointer hWnd = getWinHwnd(testStr);
boolean isWindow = windowExists(hWnd);
System.out.printf("%-22s %5b %16s %b%n", testStr, windowExists(testStr), hWnd, isWindow);
}
String ehrProd = "EHR PROD - SVC";
Pointer hWnd = getWinHwnd(ehrProd);
System.out.println("is it foreground window? " + isForegroundWindow(hWnd));
boolean foo = setForegroundWindow(ehrProd);
System.out.println("foregroundwindow: " + foo);
Thread.sleep(400);
System.out.println("is it foreground window? " + isForegroundWindow(hWnd));
Thread.sleep(400);
try {
Rectangle rect = getWindowRect(ehrProd);
Robot robot = new Robot();
BufferedImage img = robot.createScreenCapture(rect);
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
JOptionPane.showMessageDialog(null, label);
} catch (AWTException e) {
e.printStackTrace();
} catch (JnaUtilException e) {
e.printStackTrace();
}
}
use of com.sun.jna.Pointer in project openhab1-addons by openhab.
the class TellstickException method getMessage.
@Override
public String getMessage() {
Pointer errorP = JNA.CLibrary.INSTANCE.tdGetErrorString(errorcode);
String error = errorP.getString(0);
JNA.CLibrary.INSTANCE.tdReleaseString(errorP);
return dev.getName() + ": " + error;
}
Aggregations