blub / netevent Goto Github PK
View Code? Open in Web Editor NEWInput-Event device cloning utility. Use it together with ssh/netcat/... to share input devices among different machines.
License: GNU General Public License v2.0
Input-Event device cloning utility. Use it together with ssh/netcat/... to share input devices among different machines.
License: GNU General Public License v2.0
Thanks for netevent, it is a fantastic project and configuring it is a very pleasant experience compared to similar tools I have used. One thing that could come in handy would be the ability to remap keys on the fly before sending them over the network. Sometimes the keycodes mapped to hardware buttons make no sense on a remote host and it would be nice to avoid having to install yet another translation layer.
Hi,
I'm trying to use netevent on a brand new debian bullseye install, but it fails all the time, with permissions issue on uinput. I've to notice I've used netevent before on a previous bullseye system (which evolved from buster), it worked nice... I use netevent to share my kb/mouse attached to my professional PC (I'm a python dev) with my personal laptop.
daemon settings
$ cat /etc/netevent/netevent.ne2
# Mouse and keyboard
device add mymouse /dev/input/by-id/usb-PixArt_Dell_MS116_USB_Optical_Mouse-event-mouse
# device add mymouse /dev/input/by-id/usb-YSTEK_G_Mouse-event-mouse
device add mykbd /dev/input/by-id/usb-413c_Dell_KB216_Wired_Keyboard-event-kbd
# Add toggle hotkey (on press, and ignore the release event)
hotkey add mykbd key:97:1 grab toggle
hotkey add mykbd key:97:0 nop
# Connect to the two devices via password-less ssh
output add myremote exec:ssh <laptop-user>@<laptop-name>.local netevent create
# Cause grabbing to write to that output
use myremote
uinput perms
$ ls -la /dev/uinput
crw------- 1 root root 10, 223 janv. 21 08:13 /dev/uinput
daemon launching
# netevent daemon -s /etc/netevent/netevent.ne2 ./netevent-command.sock
added device mymouse
added device mykbd
added hotkey 1:97:1 for device 1
added hotkey 1:97:0 for device 1
added output myremote
error: error opening uinput device: Permission denied
interrupted
systemd service file
$ cat /etc/systemd/system/netevent.service
[Unit]
Description=Netevent mouse / keyboard sharing
After=network-online.target
[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/usr/local/bin/netevent daemon -s /etc/netevent/netevent.ne2 /run/netevent.socket
[Install]
WantedBy=multi-user.target
Thanks for you great software and for your help !
Thanks for netevent!
A couple of notes and suggestions:
I tried to use it between a PC (amd64) and a Raspberry Pi (armv6l). It didn't work out of the box. I think the problematic line was
if (!cin.read(evreadpos, sizeof(ev))) {
which should read only strsz[1] bytes if the sizes don't match.
Instead of changing that, I made the following change to make the code a bit more flexible (and not much longer):
Even after this change, I don't think it's fully portable. Even if sizeof(dev) matches, its layout or padding may be different. And different endianness is not handled. It also may not be fully thread-safe; at least atomic access should be used for the shared variables. And maybe more ... But it works for me now.(tm) ;)
Additionally I changed:
Also I found it easier to use socat instead of netcat as suggested, especially on the receiver side, because with "fork" it can handle several connections with one command (and one port). With the following command, you can forward keyboard and mouse (and whatever else you want) all to port 1955. It also works automatically if you restart netevent on the sending side, without a need to restart anything on the other side:
socat tcp-listen:1955,fork exec:"/usr/local/bin/netevent -write"
--- netevent-master/Makefile 2012-04-10 11:45:17.000000000 +0200
+++ netevent-master/Makefile 2015-02-28 08:30:28.000000000 +0100
@@ -1,3 +1,5 @@
+prefix = /usr/local
+bindir = $(prefix)/bin
CXX = g++
CC = gcc
CFLAGS = -Wall -pthread
@@ -26,6 +28,9 @@
devname: build/devname.o
$(CC) -o $@ $^
+install: all
+ install -m 755 -p -t "$(DESTDIR)$(bindir)" netevent devname
+
clean:
-rm -rf build
-rm -f netevent devname
--- netevent-master/main.h 2012-04-10 11:45:17.000000000 +0200
+++ netevent-master/main.h 2015-02-28 08:21:06.000000000 +0100
@@ -15,6 +15,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
#define gerr() std::string err(strerror(errno))
#define cErr gerr(); cerr
@@ -34,6 +35,14 @@
std::string command;
} hotkey_t;
+struct input_event_t {
+ uint64_t tv_sec;
+ uint32_t tv_usec;
+ uint16_t type;
+ uint16_t code;
+ int32_t value;
+};
+
const char *evname(unsigned int e);
int evid(const char *name);
--- netevent-master/reader.cpp 2012-04-10 11:45:17.000000000 +0200
+++ netevent-master/reader.cpp 2015-02-28 08:21:49.000000000 +0100
@@ -82,6 +82,7 @@
cErr << "Failed to open '" << toggle_file << "': " << err << endl;
break;
}
+ memset(dat, 0, sizeof(dat));
read(tfd, dat, sizeof(dat));
close(tfd);
dat[sizeof(dat)-1] = 0;
@@ -157,11 +158,9 @@
cerr << "BusType: " << dev.id.bustype << endl;
// First thing to write is the size of the structures as a 16 bit uint!
- uint16_t strsz[3];
- strsz[0] = sizeof(ev.time);
- strsz[1] = sizeof(ev);
- strsz[2] = sizeof(dev);
- if (!cout.write((const char*)strsz, sizeof(strsz)))
+ uint16_t strsz;
+ strsz = sizeof(dev);
+ if (!cout.write((const char*)&strsz, sizeof(strsz)))
exit(1);
if (cout.eof())
exit(0);
@@ -272,7 +271,13 @@
toggle_hook();
}
else if (on) {
- if (!cout.write((const char*)&ev, sizeof(ev)))
+ input_event_t et;
+ et.tv_sec = ev.time.tv_sec;
+ et.tv_usec = ev.time.tv_usec;
+ et.type = ev.type;
+ et.code = ev.code;
+ et.value = ev.value;
+ if (!cout.write((const char*)&et, sizeof(et)))
exit(1);
if (cout.eof())
exit(0);
--- netevent-master/write.cpp 2012-04-10 11:45:17.000000000 +0200
+++ netevent-master/write.cpp 2015-02-28 08:22:17.000000000 +0100
@@ -11,7 +11,7 @@
};
static const size_t uinput_cnt = sizeof(uinput_file) / sizeof(uinput_file[0]);
-static uint16_t strsz[3];
+static uint16_t strsz;
int spawn_device()
{
@@ -33,26 +33,13 @@
struct uinput_user_dev dev;
struct input_event ev;
- char *evreadpos = (char*)&ev;
- cin.read((char*)strsz, sizeof(strsz));
- if (strsz[2] != sizeof(uinput_user_dev)) {
+ cin.read((char*)&strsz, sizeof(strsz));
+ if (strsz != sizeof(uinput_user_dev)) {
cerr << "Device information field sizes do not match. Sorry." << endl;
return 1;
}
- if (strsz[1] != sizeof(ev)) {
- cerr << "Beware, devices may be incompatible\n" <<
- "Host input_event: size: " << strsz[1] <<
- ", timeval size: " << sizeof(ev) << std::endl;
- }
-
- if ((sizeof(ev) - sizeof(ev.time)) != (strsz[1] - strsz[0]))
- {
- cerr << "input-event sizes are incompatible, sorry." << endl;
- return 1;
- }
-
memset(&dev, 0, sizeof(dev));
cin.read((char*)dev.name, sizeof(dev.name));
cin.read((char*)&dev.id, sizeof(dev.id));
@@ -131,24 +118,19 @@
}
cerr << "Transferring input events." << endl;
- char field[512];
- memset(field, -1, sizeof(field));
- if (sizeof(ev) == strsz[1])
- evreadpos = (char*)&ev;
- else
- evreadpos = (char*)field;
while (true) {
+ input_event_t et;
int dummy;
waitpid(0, &dummy, WNOHANG);
- if (!cin.read(evreadpos, sizeof(ev))) {
+ if (!cin.read((char*)&et, sizeof(et))) {
cerr << "End of data" << endl;
break;
}
- if (evreadpos != (char*)&ev)
- {
- memcpy(((char*)&ev) + sizeof(ev.time), evreadpos + strsz[0], sizeof(ev) - sizeof(ev.time));
- gettimeofday(&ev.time, 0);
- }
+ ev.time.tv_sec = et.tv_sec;
+ ev.time.tv_usec = et.tv_usec;
+ ev.type = et.type;
+ ev.code = et.code;
+ ev.value = et.value;
if (hotkey_hook(ev.type, ev.code, ev.value))
continue;
if (write(fd, &ev, sizeof(ev)) < (ssize_t)sizeof(ev)) {
While packaging netevent
for toltec
I was requested for a release tag. Could you please make one that incorporates recent changes? Thanks
I am trying to share laptop keyboard and touchpad with Raspberry Pi. On the laptop I have Debian jessie running Linux kernel 3.16.0-5-686-pae. On the Raspberry Pi I have Rasbian stretch running Linux kernel 4.14.31+.
I have created a file /etc/netevent.conf which contains these lines:
device add mymouse /dev/input/by-path/platform-i8042-serio-1-event-mouse
device add mykbd /dev/input/by-path/platform-i8042-serio-0-event-kbd
hotkey add mykbd key:69:1 grab toggle
hotkey add mykbd key:69:0 nop
output add myremote exec:ssh pi@pi netevent create
use myremote
To test this configuration I run following command:
$ netevent daemon -s /etc/netevent.conf /tmp/netevent-command.sock
The output of the command is this:
added device mymouse
added device mykbd
added hotkey 1:69:1 for device 1
added hotkey 1:69:0 for device 1
added output myremote
error: protocol error: struct user_input_dev size mismatch
interrupted
Running ./configure
gives me this:
Checking for rst2man.../usr/bin/rst2man
Checking for UI_DEV_SETUP (kernel >= 4.4)....cfgtest.cpp: In function ‘int main()’:
.cfgtest.cpp:4:12: error: ‘UI_DEV_SETUP’ was not declared in this scope
ioctl(0, UI_DEV_SETUP);
^
.cfgtest.cpp:5:12: error: ‘UI_ABS_SETUP’ was not declared in this scope
ioctl(0, UI_ABS_SETUP);
^
no (disabling)
Does all this mean that my current laptop kernel does not support netevent 2 compatible protocol and I should use netevent 1 compatible protocol instead? If yes, then could you be so kind to provide some tips on how to convert my configuration to legacy? Just by adding --legacy
option after netevent create
didn't do it, since obviously it only changes the protocol used on the Raspberry Pi.
I managed to share the keyboard by using netevent cat --legacy
with netcat through ssh tunnel, but I couldn't get the hotkey to work.
PS. This is a very nice tool and project! I'm surprised it isn't more popular. netevent could be a standard tool on every Linux distribution. Good job!
Is it possible allow events to fire also locally when grab is on?
Hi,
I've recently received a Logitech MX Keys keyboard (I'm a lucky man...), but this keyboard does not set any entry in the /dev/input/by-id, so I can not set a device in the netevent configuration file.
Have you any idea on how I can use netevent with this device ?
Thanks !
Hello! This project is by far the most promising one for sharing input devices. It works perfectly for keyboard and trackpoint without any tuning, however, touchpad seems to require some optimization. Moving the cursor around isn't precise enough. Is there any setting I need to pay attention to?
Hello again and thanks again for your effort.
I would love to switch to the new version of netevent, however the deal breaker is that I cannot figure out how to toggle my keyboard leds as the ontoggle command does in the stable-1 version. I find the visual indication indispensable. .Here's an excerpt of what I use there:
/home/<user>/netevent/netevent -nograb -hotkey EV_KEY:70:1 "@toggle" -ontoggle "echo \$GRAB > /home/<user>/.mytmpfs/.netevent_mouse;/home/<user>/netevent/toggle_scrolllock" -read /dev/input/by-id/usb-Logitech_USB_Keyboard-event-kbd | nc 192.168.1.132 1956
toggle_scrolllock is a simple bash script that uses xset to control the led.
I've spent considerable time on it, can you give me a hint? Thanks. I'm trying to drum you up some business ;) https://forum.odroid.com/viewtopic.php?f=52&t=31227
I have an old Debian jessie i386 laptop with ETPS/2 Elantech Touchpad
touchpad, which I'm trying to share with a remote Raspberry Pi 3B.
Configuration file /etc/netevent/pi3-wlan.conf
on local is following:
device add mymouse /dev/input/by-path/platform-i8042-serio-1-event-mouse
device add mykbd /dev/input/by-path/platform-i8042-serio-0-event-kbd
hotkey add mykbd key:69:1 grab toggle
hotkey add mykbd key:69:0 nop
output add myremote exec:ssh pi@pi3-wlan netevent create
use myremote
When I run the command below:
$ netevent daemon -s /etc/netevent/pi3-wlan.conf /tmp/netevent-command.sock
added device mymouse
added device mykbd
added hotkey 1:69:1 for device 1
added hotkey 1:69:0 for device 1
added output myremote
... it gives me the following error message when hotkey is pressed:
ERROR: failed to grab input device: Device or resource busy
So, the touchpad is not grabbed nor shared with the remote system.
According to fuser, only Xorg is using device /dev/input/by-path/platform-i8042-serio-1-event-mouse
, in addition to netevent, when netevent is running.
Sharing a USB mouse (Logitech MX518) on the same local system works just fine, so the problem seems to be related to ETPS/2 Elantech Touchpad
or its features.
Please let me know how I can help resolving this issue.
Hi there,
i'm using netevent in my ssh-rdp project to forward input devices.
Since there seems to be a deprecation going on (d2bbc9c), it would be handy if netevent could somehow output his version so that i can reflect the deprecation in my project and use the new commands only for newer netevent versions.
That way my project would work for new and old netevent versions.
Rest assured that if the deprecation time will be long enough, there would be no need for this request :)
Thanks!
How would one use this with an xrdp session? Appears like I can't find the dev input device to write to.
Hi. I've configured netevent for Android with this build script
cmake_minimum_required(VERSION 3.24)
project(netevent)
set(CMAKE_CXX_STANDARD 20)
add_executable(netevent src/main.cpp src/reader.cpp src/writer.cpp src/socket.cpp src/bitfield.cpp src/daemon.cpp)
target_compile_options(netevent PRIVATE "-DNETEVENT_VERSION=\"2.2.1\"" "-static")
target_link_options(netevent PRIVATE "-static")
And compiled it with this script
#!/bin/sh
ABI=arm64-v8a
NDK=/home/twaik/Android/Sdk/ndk/25.1.8937393
mkdir -p $ABI
touch ./src/config.h
cmake -H$ABI -DCMAKE_SYSTEM_NAME=Android -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_SYSTEM_VERSION=26 -DANDROID_PLATFORM=android-26 -DANDROID_ABI=$ABI \
-DCMAKE_ANDROID_ARCH_ABI=$ABI -DANDROID_NDK=$NDK -DCMAKE_ANDROID_NDK=$NDK -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$ABI -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$ABI -DCMAKE_BUILD_TYPE=Debug -B$ABI -GNinja -S.
I know, this code is pretty rude and straightforward but it works.
I used this command to instantiate device's touchscreen as a touchpad.
/data/local/tmp/netevent cat /dev/input/event4 | /data/local/tmp/netevent create
It works fine on Samsung SM_A042F
, but fails to run on Samsung SM_G780F
with the following error:
error: failed to upload device info: Invalid argument
I do not know if there is a debug mode so I extracted everything I could.
twaik@twaikpc:~$ adb -s RZ8R129GXAA shell /data/local/tmp/netevent show /dev/input/event2
KEY:143:1
SYN:0:0
KEY:143:0
SYN:0:0
ABS:57:30397
ABS:48:3
ABS:50:3
ABS:53:697
ABS:54:1291
KEY:330:1
twaik@twaikpc:~$ adb -s RZ8R129GXAA shell /data/local/tmp/netevent cat /dev/input/event2 | hexdump
0000000 0400 0200 454e 4832 6c65 6f6c 0000 0000
0000010 0000 0000 0000 0000 0000 0000 0100 0000
0000020 5c04 5000 0000 0000 0000 0000 0000 0000
0000030 0000 0000 0000 0000 6573 5f63 6f74 6375
0000040 7368 7263 6565 006e 0000 0000 0000 0000
0000050 0000 0000 0000 0000 0000 0000 0000 0000
*
0000080 0000 0000 0000 0000 1800 0000 0000 0000
0000090 1f00 000b 0002 0003 0000 0000 0000 0000
00000a0 0000 0000 0000 0000 8000 0000 0000 0000
00000b0 0000 0000 0000 0000 0000 0000 0000 0000
00000c0 0400 0000 0000 0000 0000 0000 0000 0000
00000d0 0080 0000 0000 0000 0000 0000 0000 0000
00000e0 0000 0000 0000 0000 0000 0000 0000 4000
00000f0 0000 0000 0000 0000 4000 0003 0000 8000
0000100 4267 4000 0100 0000 0000 0000 0000 0000
0000110 0000 0000 0000 3704 0000 0000 0000 0000
0000120 0000 0000 0000 0000 0000 0000 0000 5f09
0000130 0000 0000 0000 0000 0000 0000 0000 0000
0000140 0000 0000 0000 0900 0000 0000 0000 0000
0000150 0000 0000 0000 0000 0000 0000 0000 ff00
0000160 0000 0000 0000 0000 0000 0000 0000 0000
0000170 0000 0000 0000 ff00 0000 0000 0000 0000
0000180 0000 0000 0000 0000 0000 0000 0000 ff00
0000190 0000 0000 0000 0000 0000 0000 0000 0000
00001a0 0000 0000 0000 3704 0000 0000 0000 0000
00001b0 0000 0000 0000 0000 0000 0000 0000 5f09
00001c0 0000 0000 0000 0000 0000 0000 0000 0000
00001d0 0000 0000 0000 ffff 0000 0000 0000 0000
00001e0 0000 0000 0000 0000 0000 0000 ffff ffff
00001f0 0000 0000 0000 0000 0000 0000 0000 0000
I'm trying to share a local ROCCAT Kone XTD USB mouse with a remote computer. The mouse is grabbed when hotkey is pressed, but there is no mouse movement on the remote side (Xorg).
Following setup is used:
Local Hardware: Desktop Computer (PC) with USB mouse (no touchpad)
Local Operating System: Debian GNU/Linux 9.4 (stretch)
Local Architecture: amd64
Local Linux Kernel Version: 4.9.0-6-amd64
Remote Hardware: Raspberry Pi 3B
Remote Operating System: Raspbian GNU/Linux 9.4 (stretch)
Remote Architecture: armv7l
Remote Linux Kernel Version: 4.9.80-v7+
Configuration file /etc/netevent/pi3-wlan.conf
on local is following:
device add mymouse /dev/input/by-id/usb-ROCCAT_ROCCAT_Kone_XTD_Optical-event-mouse
device add mykbd /dev/input/by-id/usb-ROCCAT_ROCCAT_Ryos_MK_FX-event-kbd
hotkey add mykbd key:119:1 grab toggle
hotkey add mykbd key:119:0 nop
output add myremote exec:ssh pi@pi3-wlan netevent create
use myremote
When I run the command below:
$ netevent daemon -s /etc/netevent/pi3-wlan.conf /tmp/netevent-command.sock
added device mymouse
added device mykbd
added hotkey 1:119:1 for device 1
added hotkey 1:119:0 for device 1
added output myremote
... there are no errors output and everything seems to work fine, except that the mouse pointer does not move on remote Xorg.
evtest
on remote lists ROCCAT ROCCAT Kone XTD Optical
mouse and prints mouse events as the mouse is moved. See evtest.txt as an example output.
Sharing another simpler USB mouse (Logitech MX518) on the same local system works just fine, so the problem seems to be related to ROCCAT Kone XTD mouse or its features. Detaching and reattaching ROCCAT mouse and restarting netevent made no difference.
Please let me know if there is anything I can do to help resolving this issue.
The documented socat command to control the daemon does not work for me.
It works with socat READLINE UNIX-CONNECT:netevent-command.sock
Hi,
I'm currently packaging netevent for Nixos. Would it be possible to provide more recent releases on GitHub than the one currently available ?
Regards,
Rémy
Hi. Have been using stable-1 for months, wonderful!
But I do like the simplicity of the new version. However when I try to run it I always get
error: failed to setup uinput device: Invalid argument
I've traced this back to the fact that my remote machine is stuck on kernel 3.10 (they promise someday to merge into mainline, you know) and the ioctl stuff just isn't there. When I run configure I see
Checking for UI_DEV_SETUP (kernel >= 4.4)
But it seems as if it just assumes it is present.
I'm quite happy with stable-1 forever, but I thought you might like to know of this issue.
Hi, thanks for making this tool!
I've also been wanting to share my MIDI controller attached to one of my Linux machine to another machine but couldn't get it to work. It seems there is no event device created in /dev/input/
for MIDI controllers.
Instead, it gets created by ALSA in /dev/snd/midiC1D0
but netevent does not work with it:
$ netevent show /dev/snd/midiC1D0
error: failed to query device name: Inappropriate ioctl for device
Is it possible to share MIDI controllers between machines?
Hi, first of all thanks for the project. Tried from Ubuntu to Raspbian as a quick test and worked right away.
Now I trying to do so between Raspbian (with a PiCade) to the SteamDeck to get the arcade controller running there.
Unfortunately, and that is probably due to my total lack of familiarity to Arch Linux in general. When I ssh to the SteamDeck, git clone
there, ./configure
then make
I get :
deck@steamdeck netevent)$ make
clang++ -g -Wall -Werror -Wno-unknown-pragmas -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-packed -std=c++14 -I. -c -o src/main.o src/main.cpp -MMD -MT src/main.o -MF src/main.d
src/main.cpp:8:10: fatal error: 'getopt.h' file not found
#include <getopt.h>
^~~~~~~~~~
1 error generated.
make: *** [Makefile:59: src/main.o] Error 1
I tried pacman -Sy base-devel
but that didn't help.
I also checked https://wiki.archlinux.org/title/Steam_Deck but not specific pointer. I looked for packages with said header https://archlinux.org/packages/?q=getopt.h but 0 result.
Any suggestion appreciated.
PS: also asked on https://old.reddit.com/r/linuxquestions/comments/x33w8g/getopth_missing_while_trying_to_build_netevent_on/ in case more generic advice is preferred.
I have an All-In-One that I use as a monitor, but I would like to also use the touchscreen built-in to it with my main desktop...
example output from libinput:
https://youtu.be/dDa6S5QGMug
Sorry to monopolize you, but my ultimate goal here is to use a socket on the remote machine, rather than the exec:ssh... method shown in the examples. Ideally with the ability to separate the create function locally on the remote for example. I find sockets to be a very complex subject and in this case even more perplexing as I understand that unix domain sockets are meant to be used only on the local machine, as communication occurs within the kernel. No matter the syntax I use on both ends, and I have tried many, I get: error: failed to connect to SOME_MAGIC_SYNTAX: No such file or directory
I wonder if you could elaborate on both the create --listen and output add syntax with a real life example?
Also I notice running netevent create --listen leaves netevent running, is this necessary after the socket is created? Easy enough to get rid of if not. The point of all this is I wish to build it into my initram, so that input devices are available immediately, rather than waiting for the OS to load sshd & friends for example. I was successful in doing this with stable-1 branch, however, only with root permissions on uinput, initram just isn't flexible enough for lots of groups and users, needs pam stuff at least, a mess I'd rather not deal with. I can run netevent create as root, kill netevent, fake out the permissions on the socket though (it would have worked for stable-1 uinput permissions too, I now know).
Oh, incidentally, 1 whole day with the events branch, works perfectly. Just a couple of minor things, I cannot get either daemon quit or daemon info to work, but I see they are not displayed on the daemon help screen either, so perhaps they aren't official yet? I don't believe they worked for me on the master branch either, but don't recall for sure. Anyhow, killall works fine and at least in my simple usage, I already know the info ;)
Thank you.
I've been struggling to undesrstand why i wasn't able to use write-events and grab-devices in place of grab.
The reason was I was using hotkey add twice with the same hotkey and netevent didn't processed the second one.
hotkey add DEVICE_NAME EVENT_X "COMMAND_1"
hotkey add DEVICE_NAME EVENT_X "COMMAND_2"
Then i realized that i could do something like:
hotkey add DEVICE_NAME EVENT_X "COMMAND_1 ; [..] ; COMMAND_N"
manpage didn't mention that :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.