Skip to content

Add CoreGraphics bindings and macOS getAllWindows() implementation#1719

Merged
dbwiddis merged 1 commit into
java-native-access:masterfrom
dbwiddis:add-coregraphics-bindings
May 12, 2026
Merged

Add CoreGraphics bindings and macOS getAllWindows() implementation#1719
dbwiddis merged 1 commit into
java-native-access:masterfrom
dbwiddis:add-coregraphics-bindings

Conversation

@dbwiddis
Copy link
Copy Markdown
Contributor

@dbwiddis dbwiddis commented May 9, 2026

Adds CoreGraphics interface to c.s.j.p.mac providing JNA bindings for the macOS Quartz Window Services and Quartz Display Services APIs.

Also implements getAllWindows() in MacWindowUtils, giving macOS parity with the existing Windows implementation in WindowUtils. (Note that I had to use the Win32 HWND class to be compatible with the DesktopWindow class.)

Window Services

Function Description
CGWindowListCopyWindowInfo Enumerate windows with their properties
CGRectMakeWithDictionaryRepresentation Parse bounds dictionary into CGRect

Constants: kCGWindowListOption* (filtering), kCGWindow* (dictionary keys), sharing types, backing store types.

Display Services

Function Description
CGMainDisplayID Get main display ID
CGDisplayBounds Get display bounds
CGDisplayPixelsWide / CGDisplayPixelsHigh Display dimensions
CGGetActiveDisplayList / CGGetOnlineDisplayList Enumerate displays
CGDisplayRotation Display rotation angle
CGDisplayIsActive / CGDisplayIsMain / CGDisplayIsBuiltin Display state queries
CGDisplayVendorNumber / CGDisplayModelNumber / CGDisplaySerialNumber Display identification

Structures

CGPoint, CGSize, CGRect (with ByValue for return types)

MacWindowUtils.getAllWindows()

Uses CGWindowListCopyWindowInfo to enumerate windows, filtering to normal windows (layer 0). Extracts title, owner name, window ID (as HWND), and bounds, using the DesktopWindow class used by the Windows implementation.

Test Output

On my mac:

[junit] Testsuite: com.sun.jna.platform.mac.CoreGraphicsTest
[junit] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.349 sec
[junit] 
[junit] ------------- Standard Output ---------------
[junit] First window bounds: x=193.0 y=789.0 w=9.0 h=18.0
[junit] On-screen windows (excluding desktop): 57
[junit] Main display rotation: 0.0
[junit] Main display bounds: 3440.0x1440.0
[junit] Active displays: 2
[junit]   Display 3: 3440x1440
[junit]   Display 1: 1728x1117
[junit] Total windows: 376
[junit] First window owner: CursorUIViewService
[junit] First window PID: 2323
[junit] Main display ID: 3
[junit] ------------- ---------------- ---------------

and

➜  jna git:(add-coregraphics-bindings)   jshell --class-path build/jna.jar:contrib/platform/dist/jna-platform.jar -R-XstartOnFirstThread <<< '
  import com.sun.jna.platform.*;
  var windows = WindowUtils.getAllWindows(true);
  System.out.println("Found " + windows.size() + " windows");
  for (var w : windows) System.out.println(w.getTitle() + " | " + w.getFilePath() + " | " + w.getLocAndSize());
  /exit'
|  Welcome to JShell -- Version 25.0.2
|  For an introduction type: /help intro

jshell> 
jshell> 
jshell> windows ==> [com.sun.jna.platform.DesktopWindow@54a097cc, com ... orm.DesktopWindow@97e1986]

jshell> Found 17 windows

jshell>  | Terminal | java.awt.Rectangle[x=140,y=295,width=1332,height=791]
 | Google Chrome | java.awt.Rectangle[x=944,y=30,width=1534,height=1288]
 | Sublime Text | java.awt.Rectangle[x=1607,y=238,width=1710,height=1002]
 | Eclipse | java.awt.Rectangle[x=278,y=52,width=2301,height=1274]
 | Microsoft Outlook | java.awt.Rectangle[x=1129,y=104,width=1728,height=994]
 | Messages | java.awt.Rectangle[x=304,y=191,width=1024,height=768]
 | Slack | java.awt.Rectangle[x=111,y=122,width=1353,height=1016]
 | Finder | java.awt.Rectangle[x=1804,y=285,width=1556,height=851]
 | Code | java.awt.Rectangle[x=1674,y=249,width=1567,height=848]
 | Code | java.awt.Rectangle[x=1665,y=217,width=1584,height=883]
 | Numbers | java.awt.Rectangle[x=1090,y=30,width=1260,height=1201]
 | zoom.us | java.awt.Rectangle[x=194,y=271,width=1280,height=960]
 | Preview | java.awt.Rectangle[x=4,y=34,width=708,height=328]
 | Preview | java.awt.Rectangle[x=4,y=34,width=708,height=328]
 | Preview | java.awt.Rectangle[x=4,y=34,width=708,height=328]
 | Safari | java.awt.Rectangle[x=1185,y=286,width=1324,height=940]
 | Print Center | java.awt.Rectangle[x=1270,y=443,width=900,height=450]

@dbwiddis dbwiddis force-pushed the add-coregraphics-bindings branch from e9bcbca to fcac6d7 Compare May 9, 2026 22:43
@dbwiddis dbwiddis requested a review from matthiasblaesing May 9, 2026 22:45
@dbwiddis dbwiddis force-pushed the add-coregraphics-bindings branch from fcac6d7 to 02819aa Compare May 10, 2026 14:27
Copy link
Copy Markdown
Member

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general the implementation makes sense to me. The usage of HWND is the general API in unfortunate, but the approach taken here is IMHO a good match.

I left two inline comments regarding the data types.

Comment thread contrib/platform/src/com/sun/jna/platform/mac/CoreGraphics.java Outdated
* @see <a href=
* "https://developer.apple.com/documentation/coregraphics/1456599-cgmaindisplayid">CGMainDisplayID</a>
*/
int CGMainDisplayID();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm - the declaration is a bit more involved:

// https://developer.apple.com/documentation/coregraphics/cgdisplaypixelswide(_:)?language=objc
extern size_t CGDisplayPixelsWide(CGDirectDisplayID display);
// https://developer.apple.com/documentation/kernel/size_t?language=objc
typedef typeof (sizeof(int)) size_t;
// https://developer.apple.com/documentation/coregraphics/cgdirectdisplayid?language=objc
typedef uint32_t CGDirectDisplayID;

If I remember correctly sizeof results a value of type size_t. The size of that depends on the architecture and can be 32bit or 64bit. Could you please check if it makes sense to reuse com.sun.jna.platform.unix.LibCAPI.size_t. That type is already used in SystemB for mac os.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That type is already used in SystemB for mac os.

And that was one of my earliest mappings here.

MacOS has been 64-bit capable since 10.6 (Snow Leopard) and 64-bit only since 10.15 (Catalina) in 2019. We had a discussion about 32-bit support here and it looks like you're only building 64-bit binaries for it recently.

OpenJDK dropped 32-bit support with JDK 25 (probably to avoid providing SIZE_T support in FFM 😉).

I can certainly map it that way, although I have a feeling I've already made a 64-bit assumption in a JNA contribution elsewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, size_t is definitely correct here and I looked at all my other contributions here and haven't made any 64-bit assumptions... except one. I added this in #1131 7 years ago and it didn't break anything.

int host_page_size(int hostPort, LongByReference pPageSize);

That's a vm_size_t which is essentially a NativeLongByReference. Should I fix that in another PR?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep compatibility I'd deprecate this method and add the one with the correct mapping. In the end yeah mac os is 64bit only and I have some serious hopes, that by the time 128bit becomes mainstream project panama obsoleted JNA ;-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some serious hopes, that by the time 128bit becomes mainstream project panama obsoleted JNA ;-)

FYI I and another maintainer have essentially replicated most of the JNA mappings I use with Panama mappings. Wish there was a repo I could share them...

@dbwiddis dbwiddis force-pushed the add-coregraphics-bindings branch 2 times, most recently from c0ada93 to e81598f Compare May 10, 2026 20:10
Add CoreGraphics interface to c.s.j.p.mac providing:
- Quartz Window Services: CGWindowListCopyWindowInfo,
  CGRectMakeWithDictionaryRepresentation, window list option constants,
  and window info dictionary key constants
- Quartz Display Services: CGMainDisplayID, CGDisplayBounds,
  CGDisplayPixelsWide/High, CGGetActiveDisplayList,
  CGGetOnlineDisplayList, CGDisplayRotation, CGDisplayIsActive/Main/Builtin,
  CGDisplayVendorNumber/ModelNumber/SerialNumber
- CGPoint, CGSize, CGRect structures

Implement getAllWindows() in MacWindowUtils using CGWindowListCopyWindowInfo,
providing macOS parity with the existing Windows implementation.
@dbwiddis dbwiddis force-pushed the add-coregraphics-bindings branch from e81598f to 8678fe1 Compare May 10, 2026 21:16
Copy link
Copy Markdown
Member

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't really test, but looks sane and I assume you tested on your end. Thank you.

@dbwiddis dbwiddis merged commit 1e2075a into java-native-access:master May 12, 2026
12 checks passed
@dbwiddis dbwiddis deleted the add-coregraphics-bindings branch May 12, 2026 01:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants