Skip to content
Snippets Groups Projects
Commit 57ff9239 authored by Dallin Nickel (djn011)'s avatar Dallin Nickel (djn011)
Browse files

Merge branch 'feature-os-interface' into 'prototype'

Feature OS interface

See merge request !41
parents 140a256c c5af175d
No related branches found
No related tags found
2 merge requests!45Prototype to Master for Milestone 5,!41Feature OS interface
import javafx.application.Application;
import javafx.stage.Stage;
import model.OSInterface;
import ui.mainScreen;
public class Main extends Application {
......@@ -14,6 +15,11 @@ public class Main extends Application {
public static void main(String[] args) {
Thread thread = new Thread(OSInterface.getInstance());
thread.start();
launch(args);
OSInterface.getInstance().stop();
}
}
package model;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/** Singleton class which interfaces with Windows OS. */
public class OSInterface implements HotkeyDetector, HotkeyRegistration, InputEmulator, OSSettingsWriter,
Runnable {
private static OSInterface instance = null;
private User32 user32 = User32.INSTANCE;
private WinDef.HWND hwnd;
private HashMap<Integer, Hotkey> registeredKeys;
private HashMap<Integer, Boolean> pressedKeys;
private WinUser.MSG msg;
/** Signal for the OSInterface to stop it's thread runnable. **/
private boolean stop = false;
/** Stack for hotkeys to be registered. */
private BlockingQueue<Hotkey> hotkeyRegQueue;
private BlockingQueue<Integer> hotkeyUnRegQueue;
/** Stack for keys to be emulated. */
private BlockingQueue<WinUser.INPUT[]> keySendQueue;
private OSInterface() {
registeredKeys = new HashMap<>();
pressedKeys = new HashMap<>();
msg = new WinUser.MSG();
hotkeyRegQueue = new LinkedBlockingQueue<>();
hotkeyUnRegQueue = new LinkedBlockingQueue<>();
keySendQueue = new LinkedBlockingQueue<>();
}
/**
* Gets the OSInterface instance.
*/
public static OSInterface getInstance() {
if (instance == null)
instance = new OSInterface();
return instance;
}
/**
* Stops the OSInterface runnable.
* Only should be called when the program is shutting down.
*/
public void stop() {
this.stop = true;
}
/**
* Main thread for checking messages and processing requests.
*/
public void run() {
boolean isMsg = user32.PeekMessage(msg, null, 0, 0, 1);
while (msg.message != User32.WM_QUIT && !stop) {
if (isMsg) {
if (msg.message == User32.WM_HOTKEY) {
int keyPressed = msg.wParam.intValue();
if (registeredKeys.containsKey(keyPressed)) {
pressedKeys.put(keyPressed, true);
sendKey(0x45, false);
}
}
}
Queue<Hotkey> toReg = new LinkedList<>();
Queue<Integer> toUnReg = new LinkedList<>();
Queue<WinUser.INPUT[]> toSendKeys = new LinkedList<>();
hotkeyRegQueue.drainTo(toReg);
hotkeyUnRegQueue.drainTo(toUnReg);
keySendQueue.drainTo(toSendKeys);
// Send all keys in the queue.
while (!toSendKeys.isEmpty()) {
WinUser.INPUT[] inputs = toSendKeys.remove();
WinDef.DWORD length = new WinDef.DWORD(inputs.length);
int sizeBytes = inputs[0].size();
WinDef.DWORD sent = user32.SendInput(length, inputs, sizeBytes);
if (sent.intValue() == 0) {
System.out.println("Error sending input!");
}
}
// Register all hotkeys in the queue.
while (!toReg.isEmpty()) {
if (!registerHotkeyThread(toReg.remove())) {
System.out.println("Error registering hotkey!");
}
}
// Unregister all hotkeys in the queue.
while (!toUnReg.isEmpty()) {
if (!unregisterHotkeyThread(toUnReg.remove())) {
System.out.println("Error unregistering hotkey!");
}
}
isMsg = user32.PeekMessage(msg, null, 0, 0, 1);
}
// Unregister all hotkeys after program termination.
registeredKeys.forEach((k, v) -> {
if (!unregisterHotkeyThread(k)) {
System.out.println("Error unregistering hotkey!");
}
});
}
/**
* Sets the HWND to use for interfacing with the OS.
* @param hwnd The HWND of a window.
*/
public void setHWND(WinDef.HWND hwnd) {
if (this.hwnd == null)
this.hwnd = hwnd;
}
@Override
public boolean registerHotkey(Hotkey hotkey) {
if (registeredKeys.containsKey(hotkey.getID()))
return false;
hotkeyRegQueue.add(new Hotkey(hotkey.getKeyCode(), hotkey.getID(), hotkey.getModifier()));
return true;
}
/**
* The logic for registerHotkey that will run on the thread.
* @param hotkey The hotkey to be registered.
* @return If the hotkey registration was successful.
*/
private boolean registerHotkeyThread(Hotkey hotkey) {
if (registeredKeys.containsKey(hotkey.getID()))
return false;
boolean success = user32.RegisterHotKey(null, hotkey.getID(), hotkey.getModifier(), hotkey.getKeyCode());
if (success)
registeredKeys.put(hotkey.getID(), hotkey);
return success;
}
@Override
public boolean unregisterHotkey(int id) {
if (registeredKeys.containsKey(id) || registeredKeys.isEmpty())
return false;
hotkeyUnRegQueue.add(id);
return true;
}
/**
* The logic for unregisterHotkey that will run on the thread.
* @param id The id of the hotkey to be unregistered.
* @return If the hotkey unregistration was successful.
*/
private boolean unregisterHotkeyThread(int id) {
return user32.UnregisterHotKey(null, id);
}
@Override
public boolean setMouseSpeed(int speed) {
return false;
}
@Override
public boolean wasPressed(int id) {
if (!registeredKeys.containsKey(id) || pressedKeys.isEmpty())
return false;
boolean pressed = pressedKeys.get(id);
// Set the hotkey back to default not pressed.
pressedKeys.put(id, false);
return pressed;
}
@Override
public void sendKey(int keyCode, boolean release) {
if (keyCode > 0 && keyCode < 255) {
WinUser.INPUT[] inputs = (WinUser.INPUT[]) new WinUser.INPUT().toArray(2);
// Key down input
inputs[0].type = new WinUser.DWORD(WinUser.INPUT.INPUT_KEYBOARD);
inputs[0].input.setType("ki");
inputs[0].input.ki.wVk = new WinDef.WORD(keyCode);
inputs[0].input.ki.dwFlags = new WinDef.DWORD(0);
inputs[0].input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
// Key up input
inputs[1].type = new WinUser.DWORD(WinUser.INPUT.INPUT_KEYBOARD);
inputs[1].input.setType("ki");
inputs[1].input.ki.wVk = new WinDef.WORD(keyCode);
inputs[1].input.ki.dwFlags = new WinDef.DWORD(WinUser.KEYBDINPUT.KEYEVENTF_KEYUP);
inputs[1].input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
keySendQueue.add(inputs);
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment