Я использую углерод для обнаружения ввода с клавиатуры, и он отлично работает, когда я регистрирую горячую клавишу (RegisterEventHotKey), но я хочу зарегистрировать любую клавишу, нажатую на клавиатуре, без объявления горячей клавиши.
Я использую Java, и вот пример того, что у меня есть:
public interface Carbon extends Library {
public static Carbon Lib = (Carbon) Native.loadLibrary("Carbon", Carbon.class);
public static final int cmdKey = 0x0100;
public static final int shiftKey = 0x0200;
public static final int optionKey = 0x0800;
public static final int controlKey = 0x1000;
public Pointer GetEventDispatcherTarget();
public int InstallEventHandler(Pointer inTarget, EventHandlerProcPtr inHandler, int inNumTypes, EventTypeSpec[] inList, Pointer inUserData, PointerByReference outRef);
public int RegisterEventHotKey(int inHotKeyCode, int inHotKeyModifiers, EventHotKeyID.ByValue inHotKeyID, Pointer inTarget, int inOptions, PointerByReference outRef);
public int GetEventParameter(Pointer inEvent, int inName, int inDesiredType, Pointer outActualType, int inBufferSize, IntBuffer outActualSize, EventHotKeyID outData);
public int RemoveEventHandler(Pointer inHandlerRef);
public int UnregisterEventHotKey(Pointer inHotKey);
/* struct EventTypeSpec { UInt32 eventClass; UInt32 eventKind; }; */
public class EventTypeSpec extends Structure {
public int eventClass;
public int eventKind;
@Override
protected List getFieldOrder() {
return Arrays.asList("eventClass", "eventKind");
}
}
/* struct EventHotKeyID { OSType signature; UInt32 id; }; */
public static class EventHotKeyID extends Structure {
public int signature;
public int id;
@Override
protected List getFieldOrder() {
return Arrays.asList("signature", "id");
}
public static class ByValue extends EventHotKeyID implements Structure.ByValue {
}
}
/* typedef OSStatus (*EventHandlerProcPtr) ( EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void * inUserData ); */
public static interface EventHandlerProcPtr extends Callback {
@SuppressWarnings({"UnusedDeclaration"})
public int callback(Pointer inHandlerCallRef, Pointer inEvent, Pointer inUserData);
}
}
CarbonProvider.class
public class CarbonProvider extends Provider {
private static final Logger LOGGER = LoggerFactory.getLogger(CarbonProvider.class);
private static final int kEventHotKeyPressed = 5;
private static final int kEventClassKeyboard = OS_TYPE("keyb");
private static final int typeEventHotKeyID = OS_TYPE("hkid");
private static final int kEventParamDirectObject = OS_TYPE("----");
private static int idSeq = 1;
private Map<Integer, OSXHotKey> hotKeys = new HashMap<Integer, OSXHotKey>();
private Queue<OSXHotKey> registerQueue = new LinkedList<OSXHotKey>();
private final Object lock = new Object();
private boolean listen;
private boolean reset;
private EventHandlerProcPtr keyListener;
private PointerByReference eventHandlerReference;
public Thread thread;
public void init() {
thread = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
LOGGER.info("Installing Event Handler");
eventHandlerReference = new PointerByReference();
keyListener = new EventHandler();
EventTypeSpec[] eventTypes = (EventTypeSpec[]) (new EventTypeSpec().toArray(1));
eventTypes[0].eventClass = kEventClassKeyboard;
eventTypes[0].eventKind = kEventHotKeyPressed;
int status = Lib.InstallEventHandler(Lib.GetEventDispatcherTarget(), keyListener, 1, eventTypes, null, eventHandlerReference); //fHandlerRef
if (status != 0) {
LOGGER.warn("Could not register Event Handler, error code: " + status);
}
if (eventHandlerReference.getValue() == null) {
LOGGER.warn("Event Handler reference is null");
}
listen = true;
while (listen) {
if (reset) {
resetAll();
reset = false;
lock.notify();
}
while (!registerQueue.isEmpty()) {
register(registerQueue.poll());
}
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
thread.start();
}
private void resetAll() {
LOGGER.info("Resetting hotkeys");
for (OSXHotKey hotKey : hotKeys.values()) {
int ret = Lib.UnregisterEventHotKey(hotKey.handler.getValue());
if (ret != 0) {
LOGGER.warn("Could not unregister hotkey. Error code: " + ret);
}
}
hotKeys.clear();
}
private void register(OSXHotKey hotKey) {
KeyStroke keyCode = hotKey.keyStroke;
EventHotKeyID.ByValue hotKeyReference = new EventHotKeyID.ByValue();
int id = idSeq++;
hotKeyReference.id = id;
hotKeyReference.signature = OS_TYPE("hk" + String.format("%02d", id));
PointerByReference gMyHotKeyRef = new PointerByReference();
int status = Lib.RegisterEventHotKey(KeyMap.getKeyCode(keyCode), KeyMap.getModifier(keyCode), hotKeyReference, Lib.GetEventDispatcherTarget(), 0, gMyHotKeyRef);
if (status != 0) {
LOGGER.warn("Could not register HotKey: " + keyCode + ". Error code: " + status);
return;
}
if (gMyHotKeyRef.getValue() == null) {
LOGGER.warn("HotKey returned null handler reference");
return;
}
hotKey.handler = gMyHotKeyRef;
LOGGER.info("Registered hotkey: " + keyCode);
hotKeys.put(id, hotKey);
}
@Override
public void stop() {
LOGGER.info("Stopping now");
try {
synchronized (lock) {
listen = false;
lock.notify();
}
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (eventHandlerReference.getValue() != null) {
Lib.RemoveEventHandler(eventHandlerReference.getValue());
}
super.stop();
}
public void reset() {
synchronized (lock) {
reset = true;
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void register(KeyStroke keyCode, HotKeyListener listener) {
synchronized (lock) {
registerQueue.add(new OSXHotKey(keyCode, listener));
lock.notify();
}
}
public void register(MediaKey mediaKey, HotKeyListener listener) {
LOGGER.warn("Media keys are not supported on this platform");
}
private static int OS_TYPE(String osType) {
byte[] bytes = osType.getBytes();
return (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];
}
private class EventHandler implements Carbon.EventHandlerProcPtr {
public int callback(Pointer inHandlerCallRef, Pointer inEvent, Pointer inUserData) {
EventHotKeyID eventHotKeyID = new EventHotKeyID();
int ret = Lib.GetEventParameter(inEvent, kEventParamDirectObject, typeEventHotKeyID, null, eventHotKeyID.size(), null, eventHotKeyID);
if (ret != 0) {
LOGGER.warn("Could not get event parameters. Error code: " + ret);
} else {
int eventId = eventHotKeyID.id;
LOGGER.info("Received event id: " + eventId);
fireEvent(hotKeys.get(eventId));
}
return 0;
}
}
class OSXHotKey extends HotKey {
PointerByReference handler;
public OSXHotKey(KeyStroke keyStroke, HotKeyListener listener) {
super(keyStroke, listener);
}
}
}
Я пробовал несколько вариантов в CarbonProvider.classизменение типа kEventClassKeyboard и typeEventHotKeyID, но, похоже, ничего не работает.
Не могли бы вы дать мне какие-либо рекомендации о том, как обнаруживать события, которые не являются горячими клавишами?
Спасибо за вашу помощь и время!