Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated X11 contrib API #350

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ Features
* [#338](https://github.com/twall/jna/pull/338): Added `com.sun.jna.platform.mac.XAttr` and `com.sun.jna.platform.mac.XAttrUtil` JNA wrapper for `<sys/xattr.h>` for Mac OS X - [@rednoah](https://github.com/rednoah).
* [#339](https://github.com/twall/jna/pull/339): Added `GetWindowPlacement`, `SetWindowPlacement`, `AdjustWindowRect`, `AdjustWindowRectEx`, `ExitWindowsEx`, and `LockWorkstation` to `com.sun.jna.platform.win32.User32` - [@Timeroot](https://github.com/Timeroot).
* [#286](https://github.com/twall/jna/pull/286): Added in com.sun.jna.platform.win32.Kernel32: CreateRemoteThread, WritePocessMemory and ReadProcessMemory - [@sstokic-tgm](https://github.com/sstokic-tgm).
* Object-oriented X API allows you to get subwindows of an X.Window - [@rm5248](https://github.com/rm5248)
Copy link
Member

Choose a reason for hiding this comment

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

Add a link to the PR in front, please. Also missing a dot at the end of the line :)

Try to say exactly what changed, don't assume people know what "object-oriented X API' is, name the classes and the methods.


Bug Fixes
---------
* [#319](https://github.com/twall/jna/pull/319): Fix direct-mapping type-mapped pointer result types - [@marco2357](https://github.com/marco2357).
* Added Variant and TlbImp Fixes - [@wolftobias](https://github.com/wolftobias).
* Object-oriented X API will now return null if the window property is not found - [@rm5248](https://github.com/rm5248)

Release 4.1
===========
Expand Down
148 changes: 107 additions & 41 deletions contrib/x11/src/jnacontrib/x11/api/X.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import com.sun.jna.platform.unix.X11;
import com.sun.jna.platform.unix.X11.Atom;
import com.sun.jna.platform.unix.X11.WindowByReference;

/**
* Object oriented X window system.
Expand All @@ -51,16 +52,16 @@ public class X {

private static int bytesToInt(byte[] prop) {
return ((prop[3] & 0xff) << 24)
| ((prop[2] & 0xff) << 16)
| ((prop[1] & 0xff) << 8)
| ((prop[0] & 0xff));
| ((prop[2] & 0xff) << 16)
| ((prop[1] & 0xff) << 8)
| ((prop[0] & 0xff));
}

private static int bytesToInt(byte[] prop, int offset) {
return ((prop[3 + offset] & 0xff) << 24)
| ((prop[2 + offset] & 0xff) << 16)
| ((prop[1 + offset] & 0xff) << 8)
| ((prop[offset] & 0xff));
| ((prop[2 + offset] & 0xff) << 16)
| ((prop[1 + offset] & 0xff) << 8)
| ((prop[offset] & 0xff));
}


Expand Down Expand Up @@ -303,11 +304,11 @@ public void showingDesktop(boolean state) throws X11Exception {
* @param on true if auto-repeat shall be enabled
*/
public void setKeyAutoRepeat(boolean on) {
if (on) {
x11.XAutoRepeatOn(x11Display);
} else {
x11.XAutoRepeatOff(x11Display);
}
if (on) {
x11.XAutoRepeatOn(x11Display);
} else {
x11.XAutoRepeatOff(x11Display);
}
}

/**
Expand Down Expand Up @@ -586,7 +587,7 @@ public String getWindowClass() throws X11Exception {
* @return PID of the window
* @throws X11Exception thrown if X11 window errors occurred
*/
public int getPID() throws X11Exception {
public Integer getPID() throws X11Exception {
return getIntProperty(X11.XA_CARDINAL, "_NET_WM_PID");
}

Expand Down Expand Up @@ -645,10 +646,10 @@ public Geometry getGeometry() {
x11.XGetGeometry(display.x11Display, x11Window, junkRoot, junkX, junkY, width, height, borderWidth, depth);

x11.XTranslateCoordinates(display.x11Display, x11Window, junkRoot.getValue(), junkX.getValue(),
junkY.getValue(), x, y, junkRoot);
junkY.getValue(), x, y, junkRoot);

return new Geometry(x.getValue(), y.getValue(), width.getValue(), height.getValue(),
borderWidth.getValue(), depth.getValue());
borderWidth.getValue(), depth.getValue());
}

/**
Expand All @@ -670,7 +671,7 @@ public Rectangle getBounds() {
x11.XGetGeometry(display.x11Display, x11Window, junkRoot, junkX, junkY, width, height, border_width, depth);

x11.XTranslateCoordinates(display.x11Display, x11Window, junkRoot.getValue(), junkX.getValue(),
junkY.getValue(), x, y, junkRoot);
junkY.getValue(), x, y, junkRoot);

int xVal = x.getValue();
int yVal = y.getValue();
Expand Down Expand Up @@ -731,11 +732,15 @@ public int close() throws X11Exception {
*
* @param xa_prop_type property type
* @param xa_prop_name property name
* @return property value as integer
* @return property value as integer or null if not found
* @throws X11Exception thrown if X11 window errors occurred
*/
public int getIntProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X11Exception {
return bytesToInt(getProperty(xa_prop_type, xa_prop_name));
public Integer getIntProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X11Exception {
byte[] property = getProperty(xa_prop_type, xa_prop_name);
Copy link
Member

Choose a reason for hiding this comment

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

These changes all need tests. I would merge without since this is contrib stuff, but I really encourage you to write them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could write tests; the problem is that because this is X programming, any tests are going to be highly dependent on what window manager is running and what windows are open at the time, and as far as I'm aware there's no good way to test GUI-related elements like this.

if( property == null ){
return null;
}
return bytesToInt(property);
}

/**
Expand All @@ -746,7 +751,7 @@ public int getIntProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X
* @return property value as integer
* @throws X11Exception thrown if X11 window errors occurred
*/
public int getIntProperty(X11.Atom xa_prop_type, String xa_prop_name) throws X11Exception {
public Integer getIntProperty(X11.Atom xa_prop_type, String xa_prop_name) throws X11Exception {
return getIntProperty(xa_prop_type, display.getAtom(xa_prop_name));
}

Expand All @@ -755,11 +760,14 @@ public int getIntProperty(X11.Atom xa_prop_type, String xa_prop_name) throws X11
*
* @param xa_prop_type property type
* @param xa_prop_name property name
* @return property value as window
* @return property value as window, or null if not found
* @throws X11Exception thrown if X11 window errors occurred
*/
public Window getWindowProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X11Exception {
int windowId = getIntProperty(xa_prop_type, xa_prop_name);
Integer windowId = getIntProperty(xa_prop_type, xa_prop_name);
if( windowId == null ){
return null;
}
X11.Window x11Window = new X11.Window(windowId);
return new Window(display, x11Window);
}
Expand All @@ -781,13 +789,17 @@ public Window getWindowProperty(X11.Atom xa_prop_type, String xa_prop_name) thro
*
* @param xa_prop_type property type
* @param xa_prop_name property name
* @return property value as a null terminated byte array
* @return property value as a null terminated byte array, or null if not found
* @throws X11Exception thrown if X11 window errors occurred
*/
public byte[] getNullTerminatedProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X11Exception {
byte[] bytesOrig = getProperty(xa_prop_type, xa_prop_name);
byte[] bytesDest;

if( bytesOrig == null ){
return null;
}

// search for '\0'
int i;
for (i = 0; i < bytesOrig.length; i++) {
Expand Down Expand Up @@ -821,12 +833,16 @@ public byte[] getNullTerminatedProperty(X11.Atom xa_prop_type, String xa_prop_na
*
* @param xa_prop_type property type
* @param xa_prop_name property name
* @return property value as byte array where every '\0' character is replaced by '.'
* @return property value as byte array where every '\0' character is replaced by '.'. null if the property was not found
* @throws X11Exception thrown if X11 window errors occurred
*/
public byte[] getNullReplacedStringProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X11Exception {
byte[] bytes = getProperty(xa_prop_type, xa_prop_name);

if( bytes == null ){
return null;
}

// search for '\0'
int i;
for (i = 0; i < bytes.length; i++) {
Expand Down Expand Up @@ -891,11 +907,15 @@ public String[] getStringListProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_na
*
* @param xa_prop_type property type
* @param xa_prop_name property name
* @return property value as string list
* @return property value as string list, or null if the property value does not exist
* @throws X11Exception thrown if X11 window errors occurred
*/
public String[] getStringListProperty(X11.Atom xa_prop_type, String xa_prop_name) throws X11Exception {
return new String(getProperty(xa_prop_type, xa_prop_name)).split("\0");
byte[] property = getProperty(xa_prop_type, xa_prop_name);
if( property == null ){
return null;
}
return new String(property).split("\0");
}

/**
Expand All @@ -908,7 +928,11 @@ public String[] getStringListProperty(X11.Atom xa_prop_type, String xa_prop_name
*/
public String getUtf8Property(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X11Exception {
try {
return new String(getNullReplacedStringProperty(xa_prop_type, xa_prop_name), "UTF8");
byte[] property = getNullReplacedStringProperty(xa_prop_type, xa_prop_name);
if( property == null ){
return null;
}
return new String(property, "UTF8");
} catch (UnsupportedEncodingException e) {
throw new X11Exception(e);
}
Expand Down Expand Up @@ -973,22 +997,27 @@ public byte[] getProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X
NativeLong long_length = new NativeLong(MAX_PROPERTY_VALUE_LEN / 4);

/* MAX_PROPERTY_VALUE_LEN / 4 explanation (XGetWindowProperty manpage):
*
* long_length = Specifies the length in 32-bit multiples of the
* data to be retrieved.
*/
*
* long_length = Specifies the length in 32-bit multiples of the
* data to be retrieved.
*/
if (x11.XGetWindowProperty(display.x11Display, x11Window, xa_prop_name, long_offset, long_length, false,
xa_prop_type, xa_ret_type_ref, ret_format_ref,
ret_nitems_ref, ret_bytes_after_ref, ret_prop_ref) != X11.Success) {
xa_prop_type, xa_ret_type_ref, ret_format_ref,
ret_nitems_ref, ret_bytes_after_ref, ret_prop_ref) != X11.Success) {
String prop_name = x11.XGetAtomName(display.x11Display, xa_prop_name);
throw new X11Exception("Cannot get " + prop_name + " property.");
}

X11.Atom xa_ret_type = xa_ret_type_ref.getValue();
Pointer ret_prop = ret_prop_ref.getValue();

if( xa_ret_type == null ){
//the specified property does not exist for the specified window
return null;
}

if (xa_ret_type == null || xa_prop_type == null ||
!xa_ret_type.toNative().equals(xa_prop_type.toNative())) {
!xa_ret_type.toNative().equals(xa_prop_type.toNative())) {
x11.XFree(ret_prop);
String prop_name = x11.XGetAtomName(display.x11Display, xa_prop_name);
throw new X11Exception("Invalid type of " + prop_name + " property");
Expand Down Expand Up @@ -1031,13 +1060,13 @@ public byte[] getProperty(X11.Atom xa_prop_type, String xa_prop_name) throws X11

public int clientMsg(String msg, int data0, int data1, int data2, int data3, int data4) throws X11Exception {
return clientMsg(
msg,
new NativeLong(data0),
new NativeLong(data1),
new NativeLong(data2),
new NativeLong(data3),
new NativeLong(data4)
);
msg,
new NativeLong(data0),
new NativeLong(data1),
new NativeLong(data2),
new NativeLong(data3),
new NativeLong(data4)
);
}

public int clientMsg(String msg, NativeLong data0, NativeLong data1, NativeLong data2, NativeLong data3, NativeLong data4) throws X11Exception {
Expand Down Expand Up @@ -1068,6 +1097,43 @@ public int clientMsg(String msg, NativeLong data0, NativeLong data1, NativeLong
}
}

public Window[] getSubwindows() throws X11Exception {
WindowByReference root = new WindowByReference();
WindowByReference parent = new WindowByReference();
PointerByReference children = new PointerByReference();
IntByReference childCount = new IntByReference();

if (x11.XQueryTree(display.x11Display, x11Window, root, parent, children, childCount) == 0){
throw new X11Exception("Can't query subwindows");
}

if( childCount.getValue() == 0 ){
return null;
}

Window[] retVal = new Window[ childCount.getValue() ];
//Depending on if we're running on 64-bit or 32-bit systems,
//the long size may be different; we need to make sure that
//we get the data properly no matter what
if( Native.LONG_SIZE == 4 ){
int[] windows = children.getValue().getIntArray( 0, childCount.getValue() );
for( int x = 0; x < retVal.length; x++ ){
X11.Window win = new X11.Window( windows [ x ] );
retVal[ x ] = new Window( display, win );
}
}else if( Native.LONG_SIZE == 8 ){
long[] windows = children.getValue().getLongArray( 0, childCount.getValue() );
for( int x = 0; x < retVal.length; x++ ){
X11.Window win = new X11.Window( windows [ x ] );
retVal[ x ] = new Window( display, win );
}
}

x11.XFree( children.getValue() );

return retVal;
}

public String toString() {
return x11Window.toString();
}
Expand All @@ -1090,7 +1156,7 @@ public Geometry(int x, int y, int width, int height, int border_width, int depth
* General exception which is thrown when an X11 window error occurred.
*/
public static class X11Exception extends Exception {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public X11Exception() {
}

Expand Down
Loading