Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
Minor QoL fixes
Got rid of std::shared_ptr
Enable coredumps because it's hard to do with sudo
Fix usb-gadget compilation problems (use constexpr).
Constant cleanup (replace most KEYD_ constants).
  • Loading branch information
Nekotekina committed Jan 24, 2025
1 parent ea452a7 commit afba44b
Show file tree
Hide file tree
Showing 20 changed files with 334 additions and 589 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: all clean install deb uninstall debug man compose test-harness
VERSION=3.0.5
VERSION=3.0.6
COMMIT=$(shell git describe --no-match --always --abbrev=7 --dirty)
VKBD=uinput
VKBD?=uinput
PREFIX?=/usr/local

CONFIG_DIR?=/etc/keyd
Expand Down
48 changes: 9 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ keyd++ is a fork of keyd and has some additional features at the moment:
# Installation

*Note:* master serves as the development branch, things may occasionally break.
Checkout latest tag instead, as described below.

## From Source

Expand All @@ -80,12 +81,16 @@ sudo apt install build-essentials git
# Clone with git clone or download sources manually to keyd directory
git clone https://github.com/keyd-cpp/keyd.git
cd keyd
# Specify your favourite compiler and options (optional)
# Checkout latest tag (optional but recommended)
git stash && git fetch && git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
# Specify compatible C++ compiler and options (optional)
export CXX=clang++-18 CXXFLAGS=-s
# First time install
make && sudo make install && sudo systemctl enable --now keyd
# Second time install (update example)
make && sudo make install && sudo systemctl daemon-reload && sudo systemctl restart keyd
# To update local master branch with latest commits (git pull may not work):
git stash && git fetch && git checkout master && git reset --hard origin/master
```

# Quickstart
Expand All @@ -112,6 +117,9 @@ capslock = overload(control, esc)
# When capslock is pressed with other modifiers, disable esc.
**capslock = layer(control)
# Turns insert into Shift-Insert (paste from primary selection)
insert = S-insert
# Remaps the escape key (without modifiers) to capslock
esc = capslock
```
Expand Down Expand Up @@ -180,41 +188,3 @@ You will probably want to put `keyd-application-mapper -d` somewhere in your
display server initialization logic (e.g ~/.xinitrc) unless you are running Gnome.

See the man page for more details.

## SBC support

Experimental support for single board computers (SBCs) via usb-gadget
has been added courtesy of Giorgi Chavchanidze.

See [usb-gadget.md](src/vkbd/usb-gadget.md) for details.

## Packages

Third party packages for the some distributions.

# Example config

Many users will probably not be interested in taking full advantage of keyd.
For those who seek simple quality of life improvements I can recommend the
following config:

[ids]

k:*

[main]

**shift = oneshot(shift)
**meta = oneshot(meta)
**control = oneshot(control)
**alt = oneshot(alt)
**altgr = oneshot(altgr)

capslock = overload(control, esc)
**capslock = layer(control)
insert = S-insert

This overloads the capslock key to function as both escape (when tapped) and
control (when held) and remaps all modifiers to 'oneshot' keys. Thus to produce
the letter A you can now simply tap shift and then a instead of having to hold
it. Finally it remaps insert to S-insert (paste on X11).
2 changes: 1 addition & 1 deletion docs/keyd.scdoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ keyd(1)
between emitted events.

*do [-t <timeout>] [<exp>]*
Execute the supplied expression. See MACROS for the format of <exp>. If no arguments are given, the expression is read from STDIN. If supplied, <timeout> corresponds to the macro_sequence_timeout. This macro expression is _not_ allowed to execute shell commands.
Execute the supplied expression. See MACROS for the format of <exp>. If no arguments are given, the expression is read from STDIN. If supplied, <timeout> corresponds to the macro_sequence_timeout.

# OPTIONS

Expand Down
12 changes: 6 additions & 6 deletions scripts/generate_xcompose
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ open('src/unicode.cpp', 'w').write(f'''
void unicode_get_sequence(int idx, uint8_t codes[4])
{{
uint8_t chars[] = {{
KEYD_0, KEYD_1, KEYD_2, KEYD_3, KEYD_4, KEYD_5, KEYD_6, KEYD_7,
KEYD_8, KEYD_9, KEYD_A, KEYD_B, KEYD_C, KEYD_D, KEYD_E, KEYD_F,
KEYD_G, KEYD_H, KEYD_I, KEYD_J, KEYD_K, KEYD_L, KEYD_M, KEYD_N,
KEYD_O, KEYD_P, KEYD_Q, KEYD_R, KEYD_S, KEYD_T, KEYD_U, KEYD_V,
KEYD_W, KEYD_X, KEYD_Y, KEYD_Z
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F,
KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N,
KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V,
KEY_W, KEY_X, KEY_Y, KEY_Z
}};
codes[0] = KEYD_CANCEL;
codes[0] = KEY_CANCEL;
codes[1] = chars[idx / (36 * 36) % 36];
codes[2] = chars[idx / 36 % 36];
codes[3] = chars[idx % 36];
Expand Down
2 changes: 1 addition & 1 deletion src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,7 @@ bool config_parse(struct config *config, const char *path)
aliases.modifiers[MOD_SUPER] = {KEY_LEFTMETA, KEY_RIGHTMETA};
aliases.modifiers[MOD_SHIFT] = {KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
aliases.modifiers[MOD_CTRL] = {KEY_LEFTCTRL, KEY_RIGHTCTRL};
aliases.modifiers[MOD_ALT_GR] = {KEYD_RIGHTALT};
aliases.modifiers[MOD_ALT_GR] = {KEY_RIGHTALT};

// First pass
size_t chksum0 = 0;
Expand Down
26 changes: 12 additions & 14 deletions src/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#endif

static int ipcfd = -1;
static std::shared_ptr<struct vkbd> vkbd;
static struct vkbd* vkbd;
static std::vector<std::unique_ptr<keyboard>> configs;
extern std::array<device, 128> device_table;

Expand Down Expand Up @@ -88,19 +88,19 @@ static void clear_vkbd()
{
for (size_t i = 0; i < keystate.size(); i++) {
if (keystate[i]) {
vkbd_send_key(vkbd.get(), i, 0);
vkbd_send_key(vkbd, i, 0);
keystate[i] = 0;
}
}

vkbd_flush(vkbd.get());
vkbd_flush(vkbd);
}

static void send_key(uint16_t code, uint8_t state)
{
if (code < keystate.size())
keystate[code] = state;
vkbd_send_key(vkbd.get(), code, state);
vkbd_send_key(vkbd, code, state);
}

static void add_listener(::listener con)
Expand Down Expand Up @@ -375,7 +375,6 @@ static int input(char *buf, [[maybe_unused]] size_t sz, uint32_t timeout)
size_t i;
uint32_t codepoint;
uint8_t codes[4];
auto vkbd = ::vkbd.get();

int csz;

Expand All @@ -392,23 +391,23 @@ static int input(char *buf, [[maybe_unused]] size_t sz, uint32_t timeout)
found = 1;
if (!parse_key_sequence(s, &code, &mods) && code) {
if (mods & (1 << MOD_SHIFT)) {
vkbd_send_key(vkbd, KEYD_LEFTSHIFT, 1);
vkbd_send_key(vkbd, KEY_LEFTSHIFT, 1);
vkbd_send_key(vkbd, code, 1);
vkbd_send_key(vkbd, code, 0);
vkbd_send_key(vkbd, KEYD_LEFTSHIFT, 0);
vkbd_send_key(vkbd, KEY_LEFTSHIFT, 0);
} else {
vkbd_send_key(vkbd, code, 1);
vkbd_send_key(vkbd, code, 0);
}
} else if ((char)codepoint == ' ') {
vkbd_send_key(vkbd, KEYD_SPACE, 1);
vkbd_send_key(vkbd, KEYD_SPACE, 0);
vkbd_send_key(vkbd, KEY_SPACE, 1);
vkbd_send_key(vkbd, KEY_SPACE, 0);
} else if ((char)codepoint == '\n') {
vkbd_send_key(vkbd, KEYD_ENTER, 1);
vkbd_send_key(vkbd, KEYD_ENTER, 0);
vkbd_send_key(vkbd, KEY_ENTER, 1);
vkbd_send_key(vkbd, KEY_ENTER, 0);
} else if ((char)codepoint == '\t') {
vkbd_send_key(vkbd, KEYD_TAB, 1);
vkbd_send_key(vkbd, KEYD_TAB, 0);
vkbd_send_key(vkbd, KEY_TAB, 1);
vkbd_send_key(vkbd, KEY_TAB, 0);
} else {
found = 0;
}
Expand Down Expand Up @@ -619,7 +618,6 @@ static int event_handler(struct event *ev)
static int64_t last_time = 0;
static int timeout = 0;
struct key_event kev = {};
auto vkbd = ::vkbd.get();

timeout -= ev->timestamp - last_time;
last_time = ev->timestamp;
Expand Down
21 changes: 11 additions & 10 deletions src/evloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ static int aux_fd = -1;
// Expected to terminate if fd 0 or -1
std::array<device, 128> device_table{};

static void panic_check(uint16_t code, uint8_t pressed)
static void panic_check(const device_event* ev)
{
if (ev->type != DEV_KEY)
return;
static uint8_t enter, backspace, escape;
switch (code) {
case KEYD_ENTER:
enter = pressed;
switch (ev->code) {
case KEY_ENTER:
enter = ev->pressed;
break;
case KEYD_BACKSPACE:
backspace = pressed;
case KEY_BACKSPACE:
backspace = ev->pressed;
break;
case KEYD_ESC:
escape = pressed;
case KEY_ESC:
escape = ev->pressed;
break;
}

Expand Down Expand Up @@ -110,8 +112,7 @@ int evloop(int (*event_handler)(struct event* ev), bool monitor)
removed = 1;
break;
} else {
//Handle device event
panic_check(devev->code, devev->pressed);
panic_check(devev);

ev.type = EV_DEV_EVENT;
ev.devev = devev;
Expand Down
23 changes: 12 additions & 11 deletions src/keyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,16 @@ static void clear_mod(struct keyboard *kbd, uint16_t code)
* additional control sequences.
*/
int guard = (((kbd->last_pressed_output_code == code) &&
(code == KEYD_LEFTMETA ||
code == KEYD_LEFTALT ||
code == KEYD_RIGHTALT)) &&
(code == KEY_LEFTMETA ||
code == KEY_LEFTALT ||
code == KEY_RIGHTALT)) &&
!kbd->inhibit_modifier_guard &&
!kbd->config.disable_modifier_guard);

if (guard && !kbd->keystate[KEYD_LEFTCTRL]) {
send_key(kbd, KEYD_LEFTCTRL, 1);
if (guard && !kbd->keystate[KEY_LEFTCTRL]) {
send_key(kbd, KEY_LEFTCTRL, 1);
send_key(kbd, code, 0);
send_key(kbd, KEYD_LEFTCTRL, 0);
send_key(kbd, KEY_LEFTCTRL, 0);
} else {
send_key(kbd, code, 0);
}
Expand Down Expand Up @@ -214,7 +214,7 @@ static uint8_t what_mods(struct keyboard* kbd, uint16_t code)
return mods;
}

static void execute_macro(struct keyboard *kbd, int16_t dl, uint16_t idx, uint16_t orig_code)
static uint64_t execute_macro(struct keyboard *kbd, int16_t dl, uint16_t idx, uint16_t orig_code)
{
auto& macro = kbd->config.macros[idx & INT16_MAX];
/* Minimize redundant modifier strokes for simple key sequences. */
Expand All @@ -227,10 +227,11 @@ static void execute_macro(struct keyboard *kbd, int16_t dl, uint16_t idx, uint16
update_mods(kbd, dl, macro[0].mods.mods, macro[0].mods.wildc);
send_key(kbd, code, 1);
send_key(kbd, code, 0);
return 0;
} else {
// Completely disable mods if no wildcard is set
update_mods(kbd, dl, 0, (kbd->config.compat || idx & 0x8000) ? 0xff : 0);
macro_execute(kbd->output.send_key, macro, kbd->config.macro_sequence_timeout, &kbd->config);
return macro_execute(kbd->output.send_key, macro, kbd->config.macro_sequence_timeout, &kbd->config) / 1000;
}
}

Expand Down Expand Up @@ -843,7 +844,7 @@ static int64_t process_descriptor(struct keyboard *kbd, uint16_t code, const str

clear_oneshot(kbd, "macro");

execute_macro(kbd, dl, macro_idx, code);
timeout += execute_macro(kbd, dl, macro_idx, code);
kbd->active_macro = macro_idx;
kbd->active_macro_layer = dl;

Expand Down Expand Up @@ -1290,8 +1291,8 @@ static int64_t process_event(struct keyboard *kbd, uint16_t code, int pressed, i
kbd->active_macro = -1;
update_mods(kbd, -1, 0);
} else if (time >= kbd->macro_timeout) {
execute_macro(kbd, kbd->active_macro_layer, kbd->active_macro, code);
kbd->macro_timeout = time+kbd->macro_repeat_interval;
auto add = execute_macro(kbd, kbd->active_macro_layer, kbd->active_macro, code);
kbd->macro_timeout = add + time + kbd->macro_repeat_interval;
schedule_timeout(kbd, kbd->macro_timeout);
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/keyd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <dlfcn.h>
#include <elf.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <charconv>
#include <numeric>
#include <exception>
Expand Down Expand Up @@ -47,6 +48,9 @@ static void call_init(int argc, char **argv, char **envp)
auto& dyn = _DYNAMIC[i];
if (dyn.d_tag == DT_NULL)
break;
if (dyn.d_tag == DT_INIT) {
init = decltype(init)(dyn.d_un.d_ptr + reloc);
}
if (dyn.d_tag == DT_INIT_ARRAY) {
inits = decltype(inits)(dyn.d_un.d_ptr + reloc);
}
Expand All @@ -67,6 +71,10 @@ extern "C" int __libc_start_main(int (*main)(int, char **, char **), int argc, c
void (*rtld_fini)(void),
void *stack_end)
{
// Enable coredumps early if possible
constexpr rlimit lim{rlim_t(-1), rlim_t(-1)};
setrlimit(RLIMIT_CORE, &lim);

// Some debug stuff ignored (please check twice with glibc sources)
(void)init; // Should be null
(void)fini; // Should be null
Expand Down Expand Up @@ -639,6 +647,9 @@ struct {

int main(int argc, char *argv[], char*[])
{
constexpr rlimit lim{rlim_t(-1), rlim_t(-1)};
setrlimit(RLIMIT_CORE, &lim);

aux_pool_size = 0x200'000;

if (auto dbg = getenv("KEYD_DEBUG"))
Expand Down
Loading

0 comments on commit afba44b

Please sign in to comment.