Skip to content

Commit

Permalink
Java Deprecation
Browse files Browse the repository at this point in the history
  • Loading branch information
denyncrawford committed Jun 19, 2021
1 parent 53f3358 commit a19b2a8
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 33 deletions.
39 changes: 32 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# Deno GKM
Async based, Global Keyboard and Mouse listener (GKM) driver for Deno.
Async based, Global Keyboard and Mouse listener (GKM) for Deno.

Tested on Windows, but should work on Linux and Mac OS X as well (untested).
> We're planing to implement GKM as an event trigger in the future, so it can be used for automation.
Built on Windows, there's no Linux binaries available at the moment.

## Why?

Deno do not have any global keyboard and mouse listener available.

## Requirements

Deno GKM depends on [JNativeHook](https://github.com/kwhat/jnativehook) and [gkm-java](https://github.com/tomzx/gkm-java), which runs on Java. Thus **you will need to have a JVM available** and more importantly, java availble on your PATH, but this could change in the future.
Deno GKM doesn't depends on Java anymore but it still requires the executable binary **Rusty GKM** which is a rust native plugin for listening (and emitting in the future) system events.

It installs the binaries in the `%APPDATA%/gkm` folder, you will find `gkm.jar`, which source you can find at https://github.com/tomzx/gkm-java.
You will also find `JNativeHook.jar`, which source you can find at https://github.com/kwhat/jnativehook.
It automatically installs the binary in the `%APPDATA%/gkm` | `%HOME%/gmk` folder, you will find `gkm.exe`, which source you can find at https://github.com/denyncrawford/rusty-gkm.

## Getting started

Expand Down Expand Up @@ -51,7 +52,31 @@ for await (const line of wildcard('mouse.*')) {
...const line of wildcard('key.*')...
```

## Building binaries
## Accessing event names, data values and literals

Since the event names are designed to be level accessible (trough wildcards), they follow the `[device].[event_action]?.[action_complement]`.

**Available event names**:

```bash
mouse.move
mouse.wheel
mouse.button.press
mouse.button.release
key.press
key.release
```

**Available data value formats**:

- Mouse Move and Wheel: Data object with coordinates or deltas.
- Mouse Button and keys: Key or button string.

**Literals**:

Literals are values of key press or wheel modifications, so you can detect character case state or keybinding codes. If the event doesn't haver or support literals it will be `None`.

## Building the binary

**Install bundler**:

Expand All @@ -62,7 +87,7 @@ deno install -f --allow-read --allow-write -n bundler https://raw.githubusercont
**Run the bundler**:

```bash
bundler ts-bundle lib jars.b.ts
bundler ts-bundle lib gkm.b.ts
```

## License
Expand Down
Binary file added lib/gkm.exe
Binary file not shown.
Binary file removed lib/gkm.jar
Binary file not shown.
Binary file removed lib/lib/JNativeHook.jar
Binary file not shown.
11 changes: 11 additions & 0 deletions src/gkm.b.ts

Large diffs are not rendered by default.

24 changes: 19 additions & 5 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@

import { join, ensureDir, exists } from '../deps.ts'
import files from './jars.b.ts'
import files from './gkm.b.ts'

const gkm = files['gkm.jar'];
const JNativeHook = files.lib['JNativeHook.jar'];
const gkm = files['gkm.exe'];

export const writeBinaries = async (dir: string) => {
const libDir = join(dir, 'lib');
const installed = await exists(libDir)
if (installed) return;
await ensureDir(libDir)
await Deno.writeFile(join(dir, 'gkm.jar'), gkm)
await Deno.writeFile(join(libDir, 'JNativeHook.jar'), JNativeHook)
await Deno.writeFile(join(dir, 'gkm.exe'), gkm)
}

export const wildTest = (wildcard: string, str: string) => {
const w = wildcard.replace(/[.+^${}()|[\]\\]/g, '\\$&');
const re = new RegExp(`^${w.replace(/\*/g,'.*').replace(/\?/g,'.')}$`,'i');
return re.test(str);
}

export const format = (line:string) => {
const n = line.substring(line.indexOf('name')).slice(0,-1);
const typeKeyword = "event_type:";
const typeValue = n.substring(n.indexOf(typeKeyword) + typeKeyword.length).split(' ')[1].split('(')[0];
let type: string | string[] = typeValue.split(/(?=[A-Z])/).map(e => e.toLocaleLowerCase());
const deviceType = type[0];
type = deviceType == 'key' || deviceType == 'mouse' ? type.join('.') : 'mouse.' + type.join('.');
const data = { value: '', literal: ''};
data.value = typeValue === 'MouseMove' || typeValue === 'Wheel'
? JSON.parse(n.substring(n.indexOf(typeValue) + typeValue.length).replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '))
: n.substring(n.indexOf(typeValue) + typeValue.length).split(/[()]+/).slice(-2)[0].replace('Key', '');
const lit = n.substring(n.indexOf('name') + 'name'.length + 1, n.indexOf(',')).trim();
data.literal = lit === 'None' ? lit : lit.split('"').slice(-2)[0]
return { event: type, data }
}
11 changes: 0 additions & 11 deletions src/jars.b.ts

This file was deleted.

15 changes: 5 additions & 10 deletions src/mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { join, readLines } from '../deps.ts'
import { writeBinaries, wildTest } from './helpers.ts'
import { writeBinaries, wildTest, format } from './helpers.ts'
// TODO: Verify if we're getting loaded from multiples location and prevent creating new child processes?

const name = 'gkm';
Expand All @@ -8,21 +8,16 @@ const folder = Deno.build.os === 'windows'
? join(Deno.env.get('APPDATA') || Deno.cwd(), name)
: join(Deno.env.get('HOME') || Deno.cwd(), '.' + name);

const binFolder = folder + '/bin';

await writeBinaries(binFolder);
await writeBinaries(folder);

export const gkm = async function* () {
const reader = Deno.run({
cmd: [ "java", "-jar", join(binFolder, 'gkm.jar') ],
stdout: 'piped',
stderr: 'piped',
stdin: 'piped'
cmd: [ join(folder, 'gkm.exe') ],
stdout: 'piped'
});

for await (const line of readLines(reader.stdout)) {
const parts = line.split(':');
yield { event: parts[0], data:parts[1]}
yield format(line)
}
}

Expand Down

0 comments on commit a19b2a8

Please sign in to comment.