com.github.bloodshura.ignitium.ntv.keyboard.impl.X11KeyboardWatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ignitium-native Show documentation
Show all versions of ignitium-native Show documentation
An API for working with native system APIs, with a higher-level interface.
The newest version!
package com.github.bloodshura.ignitium.ntv.keyboard.impl;
import com.github.bloodshura.ignitium.collection.list.XList;
import com.github.bloodshura.ignitium.collection.list.impl.XArrayList;
import com.github.bloodshura.ignitium.input.Key;
import com.github.bloodshura.ignitium.ntv.ErrorCodeNativeException;
import com.github.bloodshura.ignitium.ntv.NativeException;
import com.github.bloodshura.ignitium.ntv.keyboard.AbstractKeyboardWatcher;
import com.sun.jna.platform.unix.X11;
public class X11KeyboardWatcher extends AbstractKeyboardWatcher {
private X11.Display display;
private final byte[] keyBuffer;
private long lastPollMillis;
private int pollMinimumDelay;
public X11KeyboardWatcher() throws NativeException {
super(new X11KeyboardMapping());
this.display = X11.INSTANCE.XOpenDisplay(null);
this.keyBuffer = new byte[32];
this.pollMinimumDelay = 50;
if (display == null) {
throw new ErrorCodeNativeException("Could not open X11 display");
}
}
@Override
public void dispose() throws NativeException {
ensureNotDisposed();
super.dispose();
int status;
// XCloseDisplay can return a X11.BadGC error code, but let's check for anything
if ((status = X11.INSTANCE.XCloseDisplay(display)) != X11.Success) {
throw new ErrorCodeNativeException("Could not dispose X11 display", status);
}
this.display = null;
}
public int getPollMinimumDelay() {
return pollMinimumDelay;
}
@Override
public void poll() throws NativeException {
ensureNotDisposed();
if (System.currentTimeMillis() < lastPollMillis + getPollMinimumDelay()) {
return;
}
int status = X11.INSTANCE.XQueryKeymap(display, keyBuffer);
if (status != 0x1) {
throw new ErrorCodeNativeException("Could not query X11 keymap", status);
}
XList nowPressed = new XArrayList<>();
for (int i = 0; i < keyBuffer.length; i++) {
int test = 1;
for (int bit = 0; bit < 8; bit++) {
if ((keyBuffer[i] & test) > 0) {
byte code = (byte) (i * 8 + bit);
X11.KeySym sym = X11.INSTANCE.XKeycodeToKeysym(display, code, 0x0);
Key key = getMapping().keyOf(sym.intValue());
if (key != null) {
nowPressed.add(key);
}
}
test *= 2;
}
}
// Get the previously pressed keys, and if they weren't pressed now, remove them from overall pressed keys.
pressedKeys.selectNot(nowPressed::contains).forEach(pressedKeys::remove);
// Get the now pressed keys which also were previously pressed, and remove them from the now pressed keys.
nowPressed.select(pressedKeys::contains).forEach(nowPressed::remove);
// Add all the now pressed keys to the overall pressed keys.
pressedKeys.addAll(nowPressed);
this.lastPollMillis = System.currentTimeMillis();
}
public void setPollMinimumDelay(int pollMinimumDelay) {
this.pollMinimumDelay = pollMinimumDelay;
}
private void ensureNotDisposed() throws NativeException {
if (display == null) {
throw new NativeException("Keyboard watcher already disposed");
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy