[英]How to get list of all window handles in Java (Using JNA) on MacOS?
I have been using the JNA library to get all visible window handles in Windows.我一直在使用 JNA 库来获取 Windows 中所有可见的 window 句柄。 I need to do something similar in macOS using JNA.
我需要在 macOS 中使用 JNA 做类似的事情。
Here is code to get all window handles in Windows:这是获取 Windows 中所有 window 句柄的代码:
public static List<HWND> findAll() {
final List<HWND> windows = new LinkedList<>();
User32.INSTANCE.EnumWindows(new User32.WNDENUMPROC() {
@Override
public boolean callback(HWND hWnd, Pointer arg) {
if (User32.INSTANCE.IsWindowVisible(hWnd)) {
windows.add(hWnd);
}
return true;
}
}, null);
return windows;
}
What is the equivalent code in macOS? macOS 中的等效代码是什么?
You'll need to map portions of the Core Graphics Framework .您需要 map 部分Core Graphics Framework 。 You can list windows using the CGWindowListCopyWindowInfo() function.
您可以使用CGWindowListCopyWindowInfo() function 列出 windows。
To load the framework you'll need to map a CoreGraphics
interface extending JNA's Library
class, and map the function you need:要加载框架,您需要 map 扩展 JNA
Library
class 的CoreGraphics
接口,以及 map 您需要的 ZC1C4145264E6798
public interface CoreGraphics extends Library {
CoreGraphics INSTANCE = Native.load("CoreGraphics", CoreGraphics.class);
CFArrayRef CGWindowListCopyWindowInfo(int option, int relativeToWindow);
}
The CFArrayRef
type is already mapped in JNA in the CoreFoundation
class. CFArrayRef
类型已映射到 JNA 中的CoreFoundation
class。 Pick the appropriate Window List Option (probably kCGWindowListOptionAll
= 0).选择合适的Window 列表选项(可能
kCGWindowListOptionAll
= 0)。 If you already had a window number you could use relative reerences, otherwise you'll use kCGNullWindowID
(0) for the second parameter.如果您已经有一个 window 编号,您可以使用相对引用,否则您将使用
kCGNullWindowID
(0) 作为第二个参数。 Calling it from your code should be simple:从您的代码中调用它应该很简单:
CFArrayRef windowInfo = CoreGraphics.INSTANCE.CGWindowListCopyWindowInfo(0, 0);
That will give you an array of CFDictionaryRef
objects representing the windows.这将为您提供代表 windows 的
CFDictionaryRef
对象数组。 You can iterate the array and then use further methods in the CFDictionaryRef
class to explore these dictionary objects: you'll create a CFString
for the keys.您可以迭代数组,然后使用
CFDictionaryRef
class 中的其他方法来探索这些字典对象:您将为键创建一个CFString
。 A list of required keys is documented here and optional keys are here . 此处记录了所需密钥的列表, 此处提供了可选密钥。 The constant strings match the variable name .
常量字符串与变量名匹配。
This should get you a CFNumberRef
for each window number (the "handle" equivalent):这应该为每个
CFNumberRef
编号(“句柄”等效项)提供一个 CFNumberRef:
// Set up keys for dictionary lookup
CFStringRef kCGWindowNumber = CFStringRef.createCFString("kCGWindowNumber");
CFStringRef kCGWindowOwnerPID = CFStringRef.createCFString("kCGWindowOwnerPID");
// Note: the Quartz name is rarely used
CFStringRef kCGWindowName = CFStringRef.createCFString("kCGWindowName");
CFStringRef kCGWindowOwnerName = CFStringRef.createCFString("kCGWindowOwnerName");
// Iterate the array
int numWindows = windowInfo.getCount();
for (int i = 0; i < numWindows; i++) {
// For each array element, get the dictionary
Pointer result = windowInfo.getValueAtIndex(i);
CFDictionaryRef windowRef = new CFDictionaryRef(result);
// Now get information from the dictionary.
// Get a pointer to the result, in this case a CFNumber
result = windowRef.getValue(kCGWindowNumber);
// "Cast" the pointer to the appropriate type
CFNumberRef windowNumber = new CFNumberRef(result);
// CoreFoundation.INSTANCE.CFNumberGetType(windowNumber)
// --> 4 = kCFNumberSInt64Type, signed 64 bit so use getLong()
// Get a pointer to the result, in this case a CFNumber
result = windowRef.getValue(kCGWindowOwnerPID);
// "Cast" the pointer to the appropriate type
CFNumberRef windowOwnerPID = new CFNumberRef(result);
// CoreFoundation.INSTANCE.CFNumberGetType(windowOwnerPID)
// --> 4 = kCFNumberSInt64Type, signed 64 bit so use getLong()
// Get a pointer to the result, in this case a CFString
result = windowRef.getValue(kCGWindowName);
// "Cast" the pointer to the appropriate type
// Optional key, check for null
String windowName = result == null ? "" : new CFStringRef(result).stringValue();
// Get a pointer to the result, in this case a CFString
result = windowRef.getValue(kCGWindowOwnerName);
// "Cast" the pointer to the appropriate type
// Optional key, check for null
String windowOwnerName = result == null ? "" : new CFStringRef(result).stringValue();
// ... look up other keys if needed ...
// use ProcessHandle with the PID to get start time
// Output or add to List, etc.
System.out.println(windowNumber.longValue()
+ " (" + windowOwnerName + ", pid="
+ windowOwnerPID.longValue()
+ "): " + windowName);
}
// CF references from "Copy" or "Create" must be released
// release the created key references
kCGWindowNumber.release();
kCGWindowOwnerPID.release();
kCGWindowName.release();
kCGWindowOwnerName.release();
// release the array
windowInfo.release();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.