fix(stage-tamagotchi): use rdev for keyboard events monitoring (#344)
This commit is contained in:
Generated
+52
-3
@@ -187,6 +187,7 @@ dependencies = [
|
||||
"tauri-plugin-os",
|
||||
"tauri-plugin-positioner",
|
||||
"tauri-plugin-prevent-default",
|
||||
"tauri-plugin-rdev",
|
||||
"tauri-plugin-window-pass-through-on-hover",
|
||||
"tauri-plugin-window-router-link",
|
||||
"tauri-plugin-window-state",
|
||||
@@ -2760,7 +2761,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"block2 0.6.1",
|
||||
"dispatch2",
|
||||
"libc",
|
||||
"objc2 0.6.1",
|
||||
]
|
||||
|
||||
@@ -2771,10 +2774,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"block2 0.6.1",
|
||||
"dispatch2",
|
||||
"libc",
|
||||
"objc2 0.6.1",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
"objc2-metal 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2850,6 +2856,17 @@ dependencies = [
|
||||
"objc2-foundation 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-metal"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f246c183239540aab1782457b35ab2040d4259175bd1d0c58e46ada7b47a874"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"objc2 0.6.1",
|
||||
"objc2-foundation 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.2.2"
|
||||
@@ -2860,7 +2877,7 @@ dependencies = [
|
||||
"block2 0.5.1",
|
||||
"objc2 0.5.2",
|
||||
"objc2-foundation 0.2.2",
|
||||
"objc2-metal",
|
||||
"objc2-metal 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3593,6 +3610,24 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdev"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/Narsil/rdev#c14f2dc5c8100a96c5d7e3013de59d6aa0b9eae2"
|
||||
dependencies = [
|
||||
"core-foundation 0.10.1",
|
||||
"core-foundation-sys",
|
||||
"dispatch",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"objc2 0.6.1",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-foundation 0.3.1",
|
||||
"serde",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "realfft"
|
||||
version = "3.5.0"
|
||||
@@ -4112,9 +4147,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.141"
|
||||
version = "1.0.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
||||
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -5087,6 +5122,20 @@ dependencies = [
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-rdev"
|
||||
version = "0.7.0-beta.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"log",
|
||||
"rdev",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-window-pass-through-on-hover"
|
||||
version = "0.7.0-beta.1"
|
||||
|
||||
@@ -3,6 +3,7 @@ members = [
|
||||
"crates/tauri-plugin-ipc-audio-transcription-ort",
|
||||
"crates/tauri-plugin-ipc-audio-vad-ort",
|
||||
"crates/tauri-plugin-mcp",
|
||||
"crates/tauri-plugin-rdev",
|
||||
"crates/tauri-plugin-window-pass-through-on-hover",
|
||||
"crates/tauri-plugin-window-router-link",
|
||||
"apps/stage-tamagotchi/src-tauri"
|
||||
@@ -23,6 +24,9 @@ path = "./crates/tauri-plugin-ipc-audio-vad-ort"
|
||||
[workspace.dependencies.tauri-plugin-mcp]
|
||||
path = "./crates/tauri-plugin-mcp"
|
||||
|
||||
[workspace.dependencies.tauri-plugin-rdev]
|
||||
path = "./crates/tauri-plugin-rdev"
|
||||
|
||||
[workspace.dependencies.tauri-plugin-window-pass-through-on-hover]
|
||||
path = "./crates/tauri-plugin-window-pass-through-on-hover"
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ tauri-plugin-mcp = { workspace = true }
|
||||
tauri-plugin-ipc-audio-transcription-ort = { workspace = true }
|
||||
tauri-plugin-ipc-audio-vad-ort = { workspace = true }
|
||||
tauri-plugin-prevent-default = "1.3"
|
||||
tauri-plugin-rdev = { workspace = true }
|
||||
tauri-plugin-window-pass-through-on-hover = { workspace = true }
|
||||
tauri-plugin-window-router-link = { workspace = true }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
|
||||
@@ -33,6 +33,7 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_ipc_audio_transcription_ort::init())
|
||||
.plugin(tauri_plugin_ipc_audio_vad_ort::init())
|
||||
.plugin(tauri_plugin_window_pass_through_on_hover::init())
|
||||
.plugin(tauri_plugin_rdev::init())
|
||||
.plugin(tauri_plugin_window_router_link::init(
|
||||
WindowMatcher::new()
|
||||
.register("chat", |app, on_page_load| {
|
||||
@@ -63,7 +64,9 @@ pub fn run() {
|
||||
builder = builder.title_bar_style(tauri::TitleBarStyle::Transparent);
|
||||
}
|
||||
|
||||
let _ = builder.build().unwrap();
|
||||
let window = builder.build().unwrap();
|
||||
#[cfg(debug_assertions)]
|
||||
window.open_devtools();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import type { ShortcutEvent } from '@tauri-apps/plugin-global-shortcut'
|
||||
|
||||
import { register, unregisterAll } from '@tauri-apps/plugin-global-shortcut'
|
||||
import { until } from '@vueuse/shared'
|
||||
import { useMagicKeys } from '@vueuse/core'
|
||||
import { until, whenever } from '@vueuse/shared'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { watch } from 'vue'
|
||||
|
||||
import { useShortcutsStore } from '../stores/shortcuts'
|
||||
import { useAppRuntime } from './runtime'
|
||||
import { useTauriRdevEventTarget } from './tauri-rdev'
|
||||
|
||||
export function useTauriGlobalShortcuts() {
|
||||
const { shortcuts } = storeToRefs(useShortcutsStore())
|
||||
const { platform, isInitialized } = useAppRuntime()
|
||||
const eventTarget = useTauriRdevEventTarget()
|
||||
const keys = useMagicKeys({ target: eventTarget })
|
||||
|
||||
watch(shortcuts, async () => {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
@@ -18,25 +19,13 @@ export function useTauriGlobalShortcuts() {
|
||||
return
|
||||
}
|
||||
|
||||
await unregisterAll()
|
||||
|
||||
for (const handler of shortcuts.value) {
|
||||
if (!handler.shortcut) {
|
||||
return
|
||||
}
|
||||
|
||||
await register(handler.shortcut
|
||||
.replaceAll('Meta', 'CommandOrControl')
|
||||
.replaceAll('meta', 'CommandOrControl')
|
||||
.replaceAll('Ctrl', 'CommandOrControl')
|
||||
.replaceAll('ctrl', 'CommandOrControl')
|
||||
.replaceAll('Option', 'OptionOrAlt')
|
||||
.replaceAll('option', 'OptionOrAlt'), (event: ShortcutEvent) => {
|
||||
if (event.state !== 'Pressed') {
|
||||
return
|
||||
}
|
||||
|
||||
handler.handle(event).catch((error) => {
|
||||
whenever(keys[handler.shortcut], async () => {
|
||||
handler.handle().catch((error) => {
|
||||
console.error('Error handling shortcut', error)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import type { AiriTamagotchiEvents } from './tauri'
|
||||
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
|
||||
import { KeyCode, mapKeyCode, mapKeyKey } from '../tauri/rdev'
|
||||
import { useTauriEvent } from './tauri'
|
||||
|
||||
export function useTauriRdevEventTarget(): EventTarget {
|
||||
const unListenFuncs: (() => void)[] = []
|
||||
const eventTarget = new EventTarget()
|
||||
|
||||
const { listen } = useTauriEvent<AiriTamagotchiEvents>()
|
||||
|
||||
async function setup() {
|
||||
unListenFuncs.push(await listen('tauri-plugins:tauri-plugin-rdev:keyup', (event) => {
|
||||
if (typeof event.payload.event_type.KeyRelease === 'object' && 'Unknown' in event.payload.event_type.KeyRelease) {
|
||||
if (event.payload.event_type.KeyRelease.Unknown === 62) {
|
||||
event.payload.event_type = { KeyRelease: KeyCode.ControlLeft }
|
||||
}
|
||||
}
|
||||
if (typeof event.payload.event_type.KeyRelease !== 'string') {
|
||||
console.warn('unknown key release event:', event.payload.event_type.KeyRelease)
|
||||
return
|
||||
}
|
||||
|
||||
const e = new KeyboardEvent('keyup', {
|
||||
key: mapKeyKey[event.payload.event_type.KeyRelease],
|
||||
code: mapKeyCode[event.payload.event_type.KeyRelease],
|
||||
metaKey: mapKeyKey[event.payload.event_type.KeyRelease] === 'Meta',
|
||||
ctrlKey: mapKeyKey[event.payload.event_type.KeyRelease] === 'Control',
|
||||
altKey: mapKeyKey[event.payload.event_type.KeyRelease] === 'Alt',
|
||||
shiftKey: mapKeyKey[event.payload.event_type.KeyRelease] === 'Shift',
|
||||
})
|
||||
|
||||
eventTarget.dispatchEvent(e)
|
||||
}))
|
||||
|
||||
unListenFuncs.push(await listen('tauri-plugins:tauri-plugin-rdev:keydown', (event) => {
|
||||
if (typeof event.payload.event_type.KeyPress === 'object' && 'Unknown' in event.payload.event_type.KeyPress) {
|
||||
if (event.payload.event_type.KeyPress.Unknown === 62) {
|
||||
event.payload.event_type = { KeyPress: KeyCode.ControlLeft }
|
||||
}
|
||||
}
|
||||
if (typeof event.payload.event_type.KeyPress !== 'string') {
|
||||
console.warn('unknown key release event:', event.payload.event_type.KeyPress)
|
||||
return
|
||||
}
|
||||
|
||||
const e = new KeyboardEvent('keydown', {
|
||||
key: mapKeyKey[event.payload.event_type.KeyPress],
|
||||
code: mapKeyCode[event.payload.event_type.KeyPress],
|
||||
metaKey: mapKeyKey[event.payload.event_type.KeyPress] === 'Meta',
|
||||
ctrlKey: mapKeyKey[event.payload.event_type.KeyPress] === 'Control',
|
||||
altKey: mapKeyKey[event.payload.event_type.KeyPress] === 'Alt',
|
||||
shiftKey: mapKeyKey[event.payload.event_type.KeyPress] === 'Shift',
|
||||
})
|
||||
|
||||
eventTarget.dispatchEvent(e)
|
||||
}))
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
unListenFuncs.forEach(unListen => unListen())
|
||||
unListenFuncs.length = 0
|
||||
}
|
||||
|
||||
onMounted(() => setup())
|
||||
onUnmounted(() => cleanup())
|
||||
|
||||
if (import.meta.hot) { // For better DX
|
||||
import.meta.hot.on('vite:beforeUpdate', () => cleanup())
|
||||
import.meta.hot.on('vite:afterUpdate', async () => await setup())
|
||||
}
|
||||
|
||||
return eventTarget
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import type { EventCallback, EventName, UnlistenFn } from '@tauri-apps/api/event
|
||||
import type { Monitor } from '@tauri-apps/api/window'
|
||||
|
||||
import type { InvokeMethods, InvokeMethodShape } from '../tauri/invoke'
|
||||
import type { KeyCode } from '../tauri/rdev'
|
||||
|
||||
import { withRetry } from '@moeru/std'
|
||||
import { computedAsync, until } from '@vueuse/core'
|
||||
@@ -51,11 +52,23 @@ interface Events {
|
||||
}
|
||||
|
||||
export interface AiriTamagotchiEvents extends Events {
|
||||
// from tauri-plugin-window-pass-through-on-hover
|
||||
'tauri-plugins:tauri-plugin-window-pass-through-on-hover:cursor-position': Point
|
||||
'tauri-plugins:tauri-plugin-window-pass-through-on-hover:window-frame': WindowFrame
|
||||
'tauri-plugins:tauri-plugin-window-pass-through-on-hover:pass-through-enabled': boolean
|
||||
|
||||
// from tauri-plugin-ipc-audio-transcription-ort
|
||||
'tauri-plugins:tauri-plugin-ipc-audio-transcription-ort:load-model-silero-vad-progress': [boolean, string, number, number, number]
|
||||
// from tauri-plugin-ipc-audio-vad-ort
|
||||
'tauri-plugins:tauri-plugin-ipc-audio-vad-ort:load-model-whisper-progress': [boolean, string, number, number, number]
|
||||
|
||||
// from tauri-plugin-rdev
|
||||
'tauri-plugins:tauri-plugin-rdev:keydown': { time: { secs_since_epoch: number, nanos_since_epoch: number }, name: string, event_type: { KeyPress: KeyCode | { Unknown: number } } } // similar to 'keydown' events from DOM elements
|
||||
'tauri-plugins:tauri-plugin-rdev:keyup': { time: { secs_since_epoch: number, nanos_since_epoch: number }, name: string, event_type: { KeyRelease: KeyCode | { Unknown: number } } } // similar to 'keyup' events from DOM elements
|
||||
'tauri-plugins:tauri-plugin-rdev:mousedown': { time: { secs_since_epoch: number, nanos_since_epoch: number }, name: string, event_type: { ButtonPress: string } } // similar to 'mousedown' events from DOM elements
|
||||
'tauri-plugins:tauri-plugin-rdev:mouseup': { time: { secs_since_epoch: number, nanos_since_epoch: number }, name: string, event_type: { ButtonRelease: string } } // similar to 'mouseup' events from DOM elements
|
||||
|
||||
// MCP
|
||||
'mcp_plugin_destroyed': undefined
|
||||
}
|
||||
|
||||
@@ -301,3 +314,8 @@ export function useTauriWindow() {
|
||||
closeWindow,
|
||||
}
|
||||
}
|
||||
|
||||
export function createTauriEventTarget(): EventTarget {
|
||||
const eventTarget = new EventTarget()
|
||||
return eventTarget
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
<script setup lang="ts">
|
||||
import { useMagicKeys } from '@vueuse/core'
|
||||
import { computed, defineComponent, h } from 'vue'
|
||||
|
||||
import { useTauriRdevEventTarget } from '../../composables/tauri-rdev'
|
||||
|
||||
const eventTarget = useTauriRdevEventTarget()
|
||||
const {
|
||||
shift,
|
||||
control,
|
||||
escape,
|
||||
tab,
|
||||
v,
|
||||
u,
|
||||
e,
|
||||
s,
|
||||
v_u_e,
|
||||
u_s_e,
|
||||
Shift_Alt_i,
|
||||
Shift_Alt_r,
|
||||
shift_Alt_n,
|
||||
current,
|
||||
} = useMagicKeys({ target: eventTarget })
|
||||
const keys = computed(() => Array.from(current))
|
||||
|
||||
const Key = defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
render() {
|
||||
return h('div', {
|
||||
class: [
|
||||
'font-mono px-4 py-2 rounded',
|
||||
this.value
|
||||
? 'opacity-100 text-primary bg-primary bg-opacity-15'
|
||||
: 'opacity-50 bg-gray-600 bg-opacity-10 dark:(bg-gray-400 bg-opacity-10)',
|
||||
],
|
||||
}, this.$slots.default?.())
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col md:flex-row">
|
||||
<img
|
||||
class="m-auto h-38 transform py-8 transition duration-500"
|
||||
:class="{ 'opacity-0': !v_u_e, 'rotate-180': shift }"
|
||||
>
|
||||
|
||||
<div>
|
||||
<div class="mb-5 mt-0 text-center">
|
||||
Press the following keys to test out
|
||||
</div>
|
||||
<div class="flex justify-center gap-3">
|
||||
<Key :value="v">
|
||||
V
|
||||
</Key>
|
||||
<Key :value="u">
|
||||
u
|
||||
</Key>
|
||||
<Key :value="e">
|
||||
e
|
||||
</Key>
|
||||
<div class="mx-1" />
|
||||
<Key :value="u">
|
||||
U
|
||||
</Key>
|
||||
<Key :value="s">
|
||||
s
|
||||
</Key>
|
||||
<Key :value="e">
|
||||
e
|
||||
</Key>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex justify-center gap-3">
|
||||
<Key :value="escape">
|
||||
Escape
|
||||
</Key>
|
||||
<Key :value="shift">
|
||||
Shift
|
||||
</Key>
|
||||
<Key :value="control">
|
||||
Control
|
||||
</Key>
|
||||
<Key :value="tab">
|
||||
Tab
|
||||
</Key>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex justify-center gap-3">
|
||||
<Key :value="v_u_e">
|
||||
Vue
|
||||
</Key>
|
||||
<Key :value="u_s_e">
|
||||
Use
|
||||
</Key>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex flex-col items-center gap-3">
|
||||
<Key :value="Shift_Alt_i">
|
||||
Shift + Alt + I
|
||||
</Key>
|
||||
<Key :value="Shift_Alt_r">
|
||||
Shift + Alt + R
|
||||
</Key>
|
||||
<Key :value="shift_Alt_n">
|
||||
Shift + Alt + N
|
||||
</Key>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 text-center">
|
||||
<div>Keys Pressed</div>
|
||||
<div class="mt-2 min-h-1.5em flex justify-center space-x-1">
|
||||
<code
|
||||
v-for="key in keys"
|
||||
:key="key"
|
||||
class="font-mono"
|
||||
>
|
||||
{{ key }}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img
|
||||
class="m-auto h-38 transform py-8 transition duration-500"
|
||||
:class="{ 'opacity-0': !u_s_e, 'rotate-180': shift }"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { ShortcutEvent } from '@tauri-apps/plugin-global-shortcut'
|
||||
import type { MaybeRefOrGetter, UseStorageOptions } from '@vueuse/core'
|
||||
|
||||
import { useLocalStorage } from '@vueuse/core'
|
||||
@@ -77,11 +76,7 @@ export const useShortcutsStore = defineStore('shortcuts', () => {
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/move', 'Shift+Alt+N'), // Shift + Alt + N
|
||||
group: 'window',
|
||||
type: 'move',
|
||||
handle: async (event: ShortcutEvent) => {
|
||||
if (event.state !== 'Pressed') {
|
||||
return
|
||||
}
|
||||
|
||||
handle: async () => {
|
||||
windowStore.setMode(WindowControlMode.MOVE)
|
||||
windowStore.toggleControl()
|
||||
},
|
||||
@@ -91,7 +86,7 @@ export const useShortcutsStore = defineStore('shortcuts', () => {
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/resize', 'Shift+Alt+R'), // Shift + Alt + R
|
||||
group: 'window',
|
||||
type: 'resize',
|
||||
handle: async (_: ShortcutEvent) => {
|
||||
handle: async () => {
|
||||
windowStore.setMode(WindowControlMode.RESIZE)
|
||||
windowStore.toggleControl()
|
||||
},
|
||||
@@ -101,7 +96,7 @@ export const useShortcutsStore = defineStore('shortcuts', () => {
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/debug', 'Shift+Alt+I'), // Shift + Alt + I
|
||||
group: 'window',
|
||||
type: 'ignore-mouse-event',
|
||||
handle: async (_: ShortcutEvent) => {
|
||||
handle: async () => {
|
||||
windowStore.isIgnoringMouseEvent = !windowStore.isIgnoringMouseEvent
|
||||
if (windowStore.isIgnoringMouseEvent) {
|
||||
await startClickThrough()
|
||||
|
||||
@@ -0,0 +1,407 @@
|
||||
// rdev enums
|
||||
export enum KeyCode {
|
||||
// Alt key on Linux and Windows (option key on macOS)
|
||||
Alt = 'Alt',
|
||||
AltGr = 'AltGr',
|
||||
Backspace = 'Backspace',
|
||||
CapsLock = 'CapsLock',
|
||||
ControlLeft = 'ControlLeft',
|
||||
ControlRight = 'ControlRight',
|
||||
Delete = 'Delete',
|
||||
DownArrow = 'DownArrow',
|
||||
End = 'End',
|
||||
Escape = 'Escape',
|
||||
F1 = 'F1',
|
||||
F10 = 'F10',
|
||||
F11 = 'F11',
|
||||
F12 = 'F12',
|
||||
F13 = 'F13',
|
||||
F14 = 'F14',
|
||||
F15 = 'F15',
|
||||
F16 = 'F16',
|
||||
F17 = 'F17',
|
||||
F18 = 'F18',
|
||||
F19 = 'F19',
|
||||
F20 = 'F20',
|
||||
F21 = 'F21',
|
||||
F22 = 'F22',
|
||||
F23 = 'F23',
|
||||
F24 = 'F24',
|
||||
F2 = 'F2',
|
||||
F3 = 'F3',
|
||||
F4 = 'F4',
|
||||
F5 = 'F5',
|
||||
F6 = 'F6',
|
||||
F7 = 'F7',
|
||||
F8 = 'F8',
|
||||
F9 = 'F9',
|
||||
Home = 'Home',
|
||||
LeftArrow = 'LeftArrow',
|
||||
/// also known as "windows", "super", and "command"
|
||||
MetaLeft = 'MetaLeft',
|
||||
/// also known as "windows", "super", and "command"
|
||||
MetaRight = 'MetaRight',
|
||||
PageDown = 'PageDown',
|
||||
PageUp = 'PageUp',
|
||||
Return = 'Return',
|
||||
RightArrow = 'RightArrow',
|
||||
ShiftLeft = 'ShiftLeft',
|
||||
ShiftRight = 'ShiftRight',
|
||||
Space = 'Space',
|
||||
Tab = 'Tab',
|
||||
UpArrow = 'UpArrow',
|
||||
PrintScreen = 'PrintScreen',
|
||||
ScrollLock = 'ScrollLock',
|
||||
Pause = 'Pause',
|
||||
NumLock = 'NumLock',
|
||||
BackQuote = 'BackQuote',
|
||||
Num1 = 'Num1',
|
||||
Num2 = 'Num2',
|
||||
Num3 = 'Num3',
|
||||
Num4 = 'Num4',
|
||||
Num5 = 'Num5',
|
||||
Num6 = 'Num6',
|
||||
Num7 = 'Num7',
|
||||
Num8 = 'Num8',
|
||||
Num9 = 'Num9',
|
||||
Num0 = 'Num0',
|
||||
Minus = 'Minus',
|
||||
Equal = 'Equal',
|
||||
KeyQ = 'KeyQ',
|
||||
KeyW = 'KeyW',
|
||||
KeyE = 'KeyE',
|
||||
KeyR = 'KeyR',
|
||||
KeyT = 'KeyT',
|
||||
KeyY = 'KeyY',
|
||||
KeyU = 'KeyU',
|
||||
KeyI = 'KeyI',
|
||||
KeyO = 'KeyO',
|
||||
KeyP = 'KeyP',
|
||||
LeftBracket = 'LeftBracket',
|
||||
RightBracket = 'RightBracket',
|
||||
KeyA = 'KeyA',
|
||||
KeyS = 'KeyS',
|
||||
KeyD = 'KeyD',
|
||||
KeyF = 'KeyF',
|
||||
KeyG = 'KeyG',
|
||||
KeyH = 'KeyH',
|
||||
KeyJ = 'KeyJ',
|
||||
KeyK = 'KeyK',
|
||||
KeyL = 'KeyL',
|
||||
SemiColon = 'SemiColon',
|
||||
Quote = 'Quote',
|
||||
BackSlash = 'BackSlash',
|
||||
IntlBackslash = 'IntlBackslash',
|
||||
KeyZ = 'KeyZ',
|
||||
KeyX = 'KeyX',
|
||||
KeyC = 'KeyC',
|
||||
KeyV = 'KeyV',
|
||||
KeyB = 'KeyB',
|
||||
KeyN = 'KeyN',
|
||||
KeyM = 'KeyM',
|
||||
Comma = 'Comma',
|
||||
Dot = 'Dot',
|
||||
Slash = 'Slash',
|
||||
Insert = 'Insert',
|
||||
KpReturn = 'KpReturn',
|
||||
KpMinus = 'KpMinus',
|
||||
KpPlus = 'KpPlus',
|
||||
KpMultiply = 'KpMultiply',
|
||||
KpDivide = 'KpDivide',
|
||||
Kp0 = 'Kp0',
|
||||
Kp1 = 'Kp1',
|
||||
Kp2 = 'Kp2',
|
||||
Kp3 = 'Kp3',
|
||||
Kp4 = 'Kp4',
|
||||
Kp5 = 'Kp5',
|
||||
Kp6 = 'Kp6',
|
||||
Kp7 = 'Kp7',
|
||||
Kp8 = 'Kp8',
|
||||
Kp9 = 'Kp9',
|
||||
KpDelete = 'KpDelete',
|
||||
Function = 'Function',
|
||||
VolumeUp = 'VolumeUp',
|
||||
VolumeDown = 'VolumeDown',
|
||||
VolumeMute = 'VolumeMute',
|
||||
BrightnessUp = 'BrightnessUp',
|
||||
BrightnessDown = 'BrightnessDown',
|
||||
PreviousTrack = 'PreviousTrack',
|
||||
PlayPause = 'PlayPause',
|
||||
PlayCd = 'PlayCd',
|
||||
NextTrack = 'NextTrack',
|
||||
Unknown = 'Unknown',
|
||||
}
|
||||
|
||||
// Follows the exact order
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values#code_values_on_windows
|
||||
export const mapKeyCode: Record<KeyCode, string> = {
|
||||
[KeyCode.Escape]: 'Escape',
|
||||
[KeyCode.Kp0]: 'Digit0',
|
||||
[KeyCode.Kp1]: 'Digit1',
|
||||
[KeyCode.Kp2]: 'Digit2',
|
||||
[KeyCode.Kp3]: 'Digit3',
|
||||
[KeyCode.Kp4]: 'Digit4',
|
||||
[KeyCode.Kp5]: 'Digit5',
|
||||
[KeyCode.Kp6]: 'Digit6',
|
||||
[KeyCode.Kp7]: 'Digit7',
|
||||
[KeyCode.Kp8]: 'Digit8',
|
||||
[KeyCode.Kp9]: 'Digit9',
|
||||
[KeyCode.Minus]: 'Minus',
|
||||
[KeyCode.Equal]: 'Equal',
|
||||
[KeyCode.Backspace]: 'Backspace',
|
||||
[KeyCode.Tab]: 'Tab',
|
||||
[KeyCode.KeyQ]: 'KeyQ',
|
||||
[KeyCode.KeyW]: 'KeyW',
|
||||
[KeyCode.KeyE]: 'KeyE',
|
||||
[KeyCode.KeyR]: 'KeyR',
|
||||
[KeyCode.KeyT]: 'KeyT',
|
||||
[KeyCode.KeyY]: 'KeyY',
|
||||
[KeyCode.KeyU]: 'KeyU',
|
||||
[KeyCode.KeyI]: 'KeyI',
|
||||
[KeyCode.KeyO]: 'KeyO',
|
||||
[KeyCode.KeyP]: 'KeyP',
|
||||
[KeyCode.LeftBracket]: 'BracketLeft',
|
||||
[KeyCode.RightBracket]: 'BracketRight',
|
||||
[KeyCode.Return]: 'Enter',
|
||||
[KeyCode.ControlLeft]: 'ControlLeft',
|
||||
[KeyCode.KeyA]: 'KeyA',
|
||||
[KeyCode.KeyS]: 'KeyS',
|
||||
[KeyCode.KeyD]: 'KeyD',
|
||||
[KeyCode.KeyF]: 'KeyF',
|
||||
[KeyCode.KeyG]: 'KeyG',
|
||||
[KeyCode.KeyH]: 'KeyH',
|
||||
[KeyCode.KeyJ]: 'KeyJ',
|
||||
[KeyCode.KeyK]: 'KeyK',
|
||||
[KeyCode.KeyL]: 'KeyL',
|
||||
[KeyCode.SemiColon]: 'SemiColon',
|
||||
[KeyCode.Quote]: 'Quote',
|
||||
[KeyCode.BackQuote]: 'BackQuote',
|
||||
[KeyCode.ShiftLeft]: 'ShiftLeft',
|
||||
[KeyCode.BackSlash]: 'BackSlash',
|
||||
[KeyCode.KeyZ]: 'KeyZ',
|
||||
[KeyCode.KeyX]: 'KeyX',
|
||||
[KeyCode.KeyC]: 'KeyC',
|
||||
[KeyCode.KeyV]: 'KeyV',
|
||||
[KeyCode.KeyB]: 'KeyB',
|
||||
[KeyCode.KeyN]: 'KeyN',
|
||||
[KeyCode.KeyM]: 'KeyM',
|
||||
[KeyCode.Comma]: 'Comma',
|
||||
[KeyCode.Dot]: 'Period',
|
||||
[KeyCode.Slash]: 'Slash',
|
||||
[KeyCode.ShiftRight]: 'ShiftRight',
|
||||
[KeyCode.KpMultiply]: 'NumpadMultiply',
|
||||
[KeyCode.Alt]: 'Alt',
|
||||
[KeyCode.Space]: 'Space',
|
||||
[KeyCode.CapsLock]: 'CapsLock',
|
||||
[KeyCode.F1]: 'F1',
|
||||
[KeyCode.F2]: 'F2',
|
||||
[KeyCode.F3]: 'F3',
|
||||
[KeyCode.F4]: 'F4',
|
||||
[KeyCode.F5]: 'F5',
|
||||
[KeyCode.F6]: 'F6',
|
||||
[KeyCode.F7]: 'F7',
|
||||
[KeyCode.F8]: 'F8',
|
||||
[KeyCode.F9]: 'F9',
|
||||
[KeyCode.F10]: 'F10',
|
||||
[KeyCode.ScrollLock]: 'ScrollLock',
|
||||
[KeyCode.Num7]: 'Numpad7',
|
||||
[KeyCode.Num8]: 'Numpad8',
|
||||
[KeyCode.Num9]: 'Numpad9',
|
||||
[KeyCode.KpMinus]: 'NumpadSubtract',
|
||||
[KeyCode.Num4]: 'Numpad4',
|
||||
[KeyCode.Num5]: 'Numpad5',
|
||||
[KeyCode.Num6]: 'Numpad6',
|
||||
[KeyCode.KpPlus]: 'NumpadAdd',
|
||||
[KeyCode.Num1]: 'Numpad1',
|
||||
[KeyCode.Num2]: 'Numpad2',
|
||||
[KeyCode.Num3]: 'Numpad3',
|
||||
[KeyCode.Num0]: 'Numpad0',
|
||||
// Numpad Decimal?
|
||||
[KeyCode.IntlBackslash]: 'IntlBackslash',
|
||||
[KeyCode.F11]: 'F11',
|
||||
[KeyCode.F12]: 'F12',
|
||||
// NumpadEqual?
|
||||
[KeyCode.F13]: 'F13',
|
||||
[KeyCode.F14]: 'F14',
|
||||
[KeyCode.F15]: 'F15',
|
||||
[KeyCode.F16]: 'F16',
|
||||
[KeyCode.F17]: 'F17',
|
||||
[KeyCode.F18]: 'F18',
|
||||
[KeyCode.F19]: 'F19',
|
||||
[KeyCode.F20]: 'F20',
|
||||
[KeyCode.F21]: 'F21',
|
||||
[KeyCode.F22]: 'F22',
|
||||
[KeyCode.F23]: 'F23',
|
||||
[KeyCode.F24]: 'F24',
|
||||
// NumpadComma?
|
||||
[KeyCode.PreviousTrack]: 'MediaTrackPrevious',
|
||||
[KeyCode.NextTrack]: 'MediaTrackNext',
|
||||
[KeyCode.KpReturn]: 'NumpadEnter',
|
||||
[KeyCode.ControlRight]: 'ControlRight',
|
||||
[KeyCode.VolumeMute]: 'VolumeMute',
|
||||
[KeyCode.PlayPause]: 'MediaPlayPause',
|
||||
[KeyCode.VolumeDown]: 'VolumeDown',
|
||||
[KeyCode.VolumeUp]: 'VolumeUp',
|
||||
[KeyCode.KpDivide]: 'NumpadDivide',
|
||||
[KeyCode.PrintScreen]: 'PrintScreen',
|
||||
[KeyCode.AltGr]: 'AltGr',
|
||||
[KeyCode.NumLock]: 'NumLock',
|
||||
[KeyCode.Pause]: 'Pause',
|
||||
[KeyCode.Home]: 'Home',
|
||||
[KeyCode.UpArrow]: 'ArrowUp',
|
||||
[KeyCode.PageUp]: 'PageUp',
|
||||
[KeyCode.LeftArrow]: 'ArrowLeft',
|
||||
[KeyCode.RightArrow]: 'ArrowRight',
|
||||
[KeyCode.End]: 'End',
|
||||
[KeyCode.DownArrow]: 'ArrowDown',
|
||||
[KeyCode.PageDown]: 'PageDown',
|
||||
[KeyCode.Insert]: 'Insert',
|
||||
[KeyCode.Delete]: 'Delete',
|
||||
// also known as "windows", "super", and "command"
|
||||
[KeyCode.MetaLeft]: 'MetaLeft',
|
||||
// also known as "windows", "super", and "command"
|
||||
[KeyCode.MetaRight]: 'MetaRight',
|
||||
|
||||
[KeyCode.KpDelete]: 'NumpadDelete',
|
||||
[KeyCode.Function]: 'Function',
|
||||
[KeyCode.BrightnessUp]: 'BrightnessUp',
|
||||
[KeyCode.BrightnessDown]: 'BrightnessDown',
|
||||
[KeyCode.PlayCd]: 'PlayCd',
|
||||
[KeyCode.Unknown]: 'Unknown',
|
||||
}
|
||||
|
||||
export const mapKeyKey: Record<KeyCode, string> = {
|
||||
[KeyCode.Escape]: 'Escape',
|
||||
[KeyCode.Kp0]: '0',
|
||||
[KeyCode.Kp1]: '1',
|
||||
[KeyCode.Kp2]: '2',
|
||||
[KeyCode.Kp3]: '3',
|
||||
[KeyCode.Kp4]: '4',
|
||||
[KeyCode.Kp5]: '5',
|
||||
[KeyCode.Kp6]: '6',
|
||||
[KeyCode.Kp7]: '7',
|
||||
[KeyCode.Kp8]: '8',
|
||||
[KeyCode.Kp9]: '9',
|
||||
[KeyCode.Minus]: '-',
|
||||
[KeyCode.Equal]: '=',
|
||||
[KeyCode.Backspace]: 'Backspace',
|
||||
[KeyCode.Tab]: 'Tab',
|
||||
[KeyCode.KeyQ]: 'q',
|
||||
[KeyCode.KeyW]: 'w',
|
||||
[KeyCode.KeyE]: 'e',
|
||||
[KeyCode.KeyR]: 'r',
|
||||
[KeyCode.KeyT]: 't',
|
||||
[KeyCode.KeyY]: 'y',
|
||||
[KeyCode.KeyU]: 'u',
|
||||
[KeyCode.KeyI]: 'i',
|
||||
[KeyCode.KeyO]: 'o',
|
||||
[KeyCode.KeyP]: 'p',
|
||||
[KeyCode.LeftBracket]: '[',
|
||||
[KeyCode.RightBracket]: ']',
|
||||
[KeyCode.Return]: 'Enter',
|
||||
[KeyCode.ControlLeft]: 'Control',
|
||||
[KeyCode.KeyA]: 'a',
|
||||
[KeyCode.KeyS]: 's',
|
||||
[KeyCode.KeyD]: 'd',
|
||||
[KeyCode.KeyF]: 'f',
|
||||
[KeyCode.KeyG]: 'g',
|
||||
[KeyCode.KeyH]: 'h',
|
||||
[KeyCode.KeyJ]: 'j',
|
||||
[KeyCode.KeyK]: 'k',
|
||||
[KeyCode.KeyL]: 'l',
|
||||
[KeyCode.SemiColon]: ';',
|
||||
[KeyCode.Quote]: '\'',
|
||||
[KeyCode.BackQuote]: '`',
|
||||
[KeyCode.ShiftLeft]: 'Shift',
|
||||
[KeyCode.BackSlash]: '\\',
|
||||
[KeyCode.KeyZ]: 'z',
|
||||
[KeyCode.KeyX]: 'x',
|
||||
[KeyCode.KeyC]: 'c',
|
||||
[KeyCode.KeyV]: 'v',
|
||||
[KeyCode.KeyB]: 'b',
|
||||
[KeyCode.KeyN]: 'n',
|
||||
[KeyCode.KeyM]: 'm',
|
||||
[KeyCode.Comma]: ',',
|
||||
[KeyCode.Dot]: '.',
|
||||
[KeyCode.Slash]: '/',
|
||||
[KeyCode.ShiftRight]: 'Shift',
|
||||
[KeyCode.KpMultiply]: '*',
|
||||
[KeyCode.Alt]: 'Alt',
|
||||
[KeyCode.Space]: ' ',
|
||||
[KeyCode.CapsLock]: 'CapsLock',
|
||||
[KeyCode.F1]: 'F1',
|
||||
[KeyCode.F2]: 'F2',
|
||||
[KeyCode.F3]: 'F3',
|
||||
[KeyCode.F4]: 'F4',
|
||||
[KeyCode.F5]: 'F5',
|
||||
[KeyCode.F6]: 'F6',
|
||||
[KeyCode.F7]: 'F7',
|
||||
[KeyCode.F8]: 'F8',
|
||||
[KeyCode.F9]: 'F9',
|
||||
[KeyCode.F10]: 'F10',
|
||||
[KeyCode.ScrollLock]: 'ScrollLock',
|
||||
[KeyCode.Num7]: '7',
|
||||
[KeyCode.Num8]: '8',
|
||||
[KeyCode.Num9]: '9',
|
||||
[KeyCode.KpMinus]: '-',
|
||||
[KeyCode.Num4]: '4',
|
||||
[KeyCode.Num5]: '5',
|
||||
[KeyCode.Num6]: '6',
|
||||
[KeyCode.KpPlus]: '+',
|
||||
[KeyCode.Num1]: '1',
|
||||
[KeyCode.Num2]: '2',
|
||||
[KeyCode.Num3]: '3',
|
||||
[KeyCode.Num0]: '0',
|
||||
// Numpad Decimal?
|
||||
[KeyCode.IntlBackslash]: 'IntlBackslash',
|
||||
[KeyCode.F11]: 'F11',
|
||||
[KeyCode.F12]: 'F12',
|
||||
// NumpadEqual?
|
||||
[KeyCode.F13]: 'F13',
|
||||
[KeyCode.F14]: 'F14',
|
||||
[KeyCode.F15]: 'F15',
|
||||
[KeyCode.F16]: 'F16',
|
||||
[KeyCode.F17]: 'F17',
|
||||
[KeyCode.F18]: 'F18',
|
||||
[KeyCode.F19]: 'F19',
|
||||
[KeyCode.F20]: 'F20',
|
||||
[KeyCode.F21]: 'F21',
|
||||
[KeyCode.F22]: 'F22',
|
||||
[KeyCode.F23]: 'F23',
|
||||
[KeyCode.F24]: 'F24',
|
||||
// NumpadComma?
|
||||
[KeyCode.PreviousTrack]: 'MediaTrackPrevious',
|
||||
[KeyCode.NextTrack]: 'MediaTrackNext',
|
||||
[KeyCode.KpReturn]: 'Enter',
|
||||
[KeyCode.ControlRight]: 'Control',
|
||||
[KeyCode.VolumeMute]: 'VolumeMute',
|
||||
[KeyCode.PlayPause]: 'MediaPlayPause',
|
||||
[KeyCode.VolumeDown]: 'VolumeDown',
|
||||
[KeyCode.VolumeUp]: 'VolumeUp',
|
||||
[KeyCode.KpDivide]: '/',
|
||||
[KeyCode.PrintScreen]: 'PrintScreen',
|
||||
[KeyCode.AltGr]: 'Alt',
|
||||
[KeyCode.NumLock]: 'NumLock',
|
||||
[KeyCode.Pause]: 'Pause',
|
||||
[KeyCode.Home]: 'Home',
|
||||
[KeyCode.UpArrow]: 'ArrowUp',
|
||||
[KeyCode.PageUp]: 'PageUp',
|
||||
[KeyCode.LeftArrow]: 'ArrowLeft',
|
||||
[KeyCode.RightArrow]: 'ArrowRight',
|
||||
[KeyCode.End]: 'End',
|
||||
[KeyCode.DownArrow]: 'ArrowDown',
|
||||
[KeyCode.PageDown]: 'PageDown',
|
||||
[KeyCode.Insert]: 'Insert',
|
||||
[KeyCode.Delete]: 'Delete',
|
||||
// also known as "windows", "super", and "command"
|
||||
[KeyCode.MetaLeft]: 'Meta',
|
||||
// also known as "windows", "super", and "command"
|
||||
[KeyCode.MetaRight]: 'Meta',
|
||||
|
||||
[KeyCode.KpDelete]: 'Delete',
|
||||
[KeyCode.Function]: 'Function',
|
||||
[KeyCode.BrightnessUp]: 'BrightnessUp',
|
||||
[KeyCode.BrightnessDown]: 'BrightnessDown',
|
||||
[KeyCode.PlayCd]: 'PlayCd',
|
||||
[KeyCode.Unknown]: 'Unknown',
|
||||
}
|
||||
@@ -8,6 +8,7 @@ repository = "https://github.com/moeru-ai/airi"
|
||||
edition = "2024"
|
||||
rust-version = "1.85.0"
|
||||
links = "tauri-plugin-ipc-audio-transcription-ort"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "tauri_plugin_ipc_audio_transcription_ort"
|
||||
|
||||
@@ -8,6 +8,7 @@ repository = "https://github.com/moeru-ai/airi"
|
||||
edition = "2024"
|
||||
rust-version = "1.85.0"
|
||||
links = "tauri-plugin-ipc-audio-vad-ort"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "tauri_plugin_ipc_audio_vad_ort"
|
||||
|
||||
Generated
+4732
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "tauri-plugin-rdev"
|
||||
version.workspace = true
|
||||
description = "Integration of github.com/Narsil/rdev for Tauri"
|
||||
authors = [ "Neko Ayaka <neko@ayaka.moe>" ]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/moeru-ai/airi"
|
||||
edition = "2024"
|
||||
rust-version = "1.85.0"
|
||||
links = "tauri-plugin-rdev"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "tauri_plugin_rdev"
|
||||
crate-type = [
|
||||
"staticlib",
|
||||
"cdylib",
|
||||
"rlib"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
tauri = "2.3.1"
|
||||
tokio = { version = "1", features = [ "full" ] }
|
||||
anyhow = "1"
|
||||
rdev = { git = "https://github.com/Narsil/rdev", version = "0.6.0", features = ["serialize"] }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.142"
|
||||
log = "0.4.27"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-plugin = { version = "2.2", features = [ "build" ] }
|
||||
@@ -0,0 +1 @@
|
||||
fn main() {}
|
||||
@@ -0,0 +1,126 @@
|
||||
use std::sync::{Mutex, atomic::Ordering};
|
||||
|
||||
use log::error;
|
||||
use rdev::{Event, EventType, listen};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
use tauri::{
|
||||
Emitter,
|
||||
Manager,
|
||||
Runtime,
|
||||
plugin::{Builder as PluginBuilder, TauriPlugin},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum DeviceKind {
|
||||
MousePress,
|
||||
MouseRelease,
|
||||
MouseMove,
|
||||
KeyboardPress,
|
||||
KeyboardRelease,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct DeviceEvent {
|
||||
kind: DeviceKind,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct PluginState {
|
||||
window_labels: Vec<String>,
|
||||
}
|
||||
|
||||
const PLUGIN_NAME: &str = "rdev";
|
||||
|
||||
// Code referenced from
|
||||
// https://github.com/liwenka1/bongo-cat-next/blob/891c3380e1d4a8cfe8452668632be8bd5086b46c/src-tauri/src/core/device.rs#L7
|
||||
static IS_RUNNING: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
|
||||
fn start_listen<R: tauri::Runtime>(app: tauri::AppHandle<R>) {
|
||||
#[cfg(target_os = "macos")]
|
||||
rdev::set_is_main_thread(false);
|
||||
|
||||
// Events needed by
|
||||
// https://github.com/vueuse/vueuse/blob/f8c4e0a128e2d8df52cca0299a08bfd4dd8638da/packages/core/useMagicKeys/index.ts#L153C3-L153C19
|
||||
_ = listen(move |event: Event| {
|
||||
let event_name = match event.event_type {
|
||||
EventType::KeyPress(_) => "tauri-plugins:tauri-plugin-rdev:keydown",
|
||||
EventType::KeyRelease(_) => "tauri-plugins:tauri-plugin-rdev:keyup",
|
||||
EventType::ButtonPress(_) => "tauri-plugins:tauri-plugin-rdev:mousedown",
|
||||
EventType::ButtonRelease(_) => "tauri-plugins:tauri-plugin-rdev:mouseup",
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let state = app.state::<Mutex<PluginState>>();
|
||||
let state = match state.lock() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
error!("PluginState mutex is poisoned: {}", e);
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
for label in &state.window_labels {
|
||||
if let Err(e) = app.emit_to(label, event_name, &event) {
|
||||
error!(
|
||||
"Failed to emit rdev event '{}' to window '{}': {}",
|
||||
event_name, label, e
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
.map_err(|e| {
|
||||
error!("Failed to start rdev listener: {:?}", e);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
PluginBuilder::new(PLUGIN_NAME)
|
||||
.setup(|app, _| {
|
||||
app.manage(Mutex::new(PluginState {
|
||||
window_labels: vec![],
|
||||
}));
|
||||
|
||||
// Code referenced from
|
||||
// https://github.com/liwenka1/bongo-cat-next/blob/891c3380e1d4a8cfe8452668632be8bd5086b46c/src-tauri/src/core/device.rs#L7
|
||||
if IS_RUNNING.load(Ordering::SeqCst) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
IS_RUNNING.store(true, Ordering::SeqCst);
|
||||
|
||||
let app = app.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
start_listen(app);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.on_window_ready(|window| {
|
||||
let app = window.app_handle();
|
||||
let state = app.state::<Mutex<PluginState>>();
|
||||
let mut state = state.lock().unwrap();
|
||||
|
||||
state
|
||||
.window_labels
|
||||
.push(window.label().to_string());
|
||||
|
||||
let window_cloned = window.clone();
|
||||
|
||||
window.on_window_event(move |event| match event {
|
||||
tauri::WindowEvent::CloseRequested { .. } => {
|
||||
let app = window_cloned.app_handle();
|
||||
let state = app.state::<Mutex<PluginState>>();
|
||||
let mut state = state.lock().unwrap();
|
||||
|
||||
state
|
||||
.window_labels
|
||||
.retain(|label| label != window_cloned.label());
|
||||
},
|
||||
_ => {},
|
||||
});
|
||||
})
|
||||
.build()
|
||||
}
|
||||
@@ -110,6 +110,7 @@ words:
|
||||
- jszip
|
||||
- Kawaii
|
||||
- kebabcase
|
||||
- keyup
|
||||
- Keyyable
|
||||
- kirakira
|
||||
- kwaa
|
||||
@@ -142,6 +143,8 @@ words:
|
||||
- modnet
|
||||
- moeru
|
||||
- Morioki
|
||||
- mousedown
|
||||
- mouseup
|
||||
- msvc
|
||||
- Myriam
|
||||
- ndarray
|
||||
@@ -186,6 +189,7 @@ words:
|
||||
- pthread
|
||||
- quanlai
|
||||
- qwen
|
||||
- rdev
|
||||
- rehype
|
||||
- reka
|
||||
- Replayable
|
||||
|
||||
Reference in New Issue
Block a user