Add overload2 (#309)

master
Raheman Vaiya 4 years ago
parent 0ec11fb4b0
commit b1fdaa4d01
  1. 2
      Makefile
  2. 1
      src/config.c
  3. 1
      src/config.h
  4. 106
      src/keyboard.c
  5. 12
      src/keyboard.h
  6. 1
      t/meta.t
  7. 7
      t/test.conf

@ -1,4 +1,4 @@
.PHONY: all clean install uninstall debug man compose
.PHONY: all clean install uninstall debug man compose test-harness
DESTDIR=
PREFIX=/usr

@ -51,6 +51,7 @@ static struct {
{ "toggle2", OP_TOGGLE2, { ARG_LAYER, ARG_MACRO } },
{ "layer", OP_LAYER, { ARG_LAYER } },
{ "overload", OP_OVERLOAD, { ARG_LAYER, ARG_DESCRIPTOR } },
{ "overload2", OP_OVERLOAD2, { ARG_LAYER, ARG_DESCRIPTOR, ARG_TIMEOUT } },
{ "timeout", OP_TIMEOUT, { ARG_DESCRIPTOR, ARG_TIMEOUT, ARG_DESCRIPTOR } },
{ "macro2", OP_MACRO2, { ARG_TIMEOUT, ARG_TIMEOUT, ARG_MACRO } },
{ "setlayout", OP_LAYOUT, { ARG_LAYOUT } },

@ -31,6 +31,7 @@ enum op {
OP_LAYOUT,
OP_CLEAR,
OP_OVERLOAD,
OP_OVERLOAD2,
OP_TOGGLE,
OP_TOGGLE2,

@ -84,9 +84,10 @@ static void send_key(struct keyboard *kbd, uint8_t code, uint8_t pressed)
if (pressed)
kbd->last_pressed_output_code = code;
kbd->keystate[code] = pressed;
kbd->output(code, pressed);
if (kbd->keystate[code] != pressed) {
kbd->keystate[code] = pressed;
kbd->output(code, pressed);
}
}
static void set_mods(struct keyboard *kbd, uint8_t mods)
@ -363,6 +364,25 @@ static long process_descriptor(struct keyboard *kbd, uint8_t code,
update_mods(kbd, -1, 0);
}
break;
case OP_OVERLOAD2:
if (pressed) {
uint8_t layer = d->args[0].idx;
struct descriptor *action = &kbd->config.descriptors[d->args[1].idx];
timeout = d->args[2].idx;
kbd->overload2.active = 1;
kbd->overload2.code = code;
kbd->overload2.layer = layer;
kbd->overload2.action = action;
kbd->overload2.dl = dl;
kbd->overload2.n = 0;
} else {
deactivate_layer(kbd, d->args[0].idx);
update_mods(kbd, -1, 0);
}
break;
case OP_LAYOUT:
if (pressed)
@ -599,6 +619,49 @@ struct keyboard *new_keyboard(struct config *config,
return kbd;
}
static int resolve_overload2(struct keyboard *kbd, int time, int hold)
{
int timeout = 0;
int timeout_ts;
struct key_event queue[ARRAY_SIZE(kbd->overload2.queued)];
int n = kbd->overload2.n;
kbd->overload2.active = 0;
memcpy(queue, kbd->overload2.queued, sizeof(struct key_event)*n);
if (hold) {
activate_layer(kbd, kbd->overload2.code, kbd->overload2.layer);
update_mods(kbd, -1, 0);
} else {
process_descriptor(kbd,
kbd->overload2.code,
kbd->overload2.action,
kbd->overload2.dl, 1);
process_descriptor(kbd,
kbd->overload2.code,
kbd->overload2.action,
kbd->overload2.dl, 0);
cache_set(kbd, kbd->overload2.code, NULL, -1);
}
if (!n)
return 0;
timeout = kbd_process_events(kbd, queue, n);
timeout_ts = queue[n-1].timestamp + timeout;
if (timeout_ts <= time) {
struct key_event ev = {.code = 0, .timestamp = timeout_ts};
return kbd_process_events(kbd, &ev, 1);
}
return timeout_ts - time;
}
/*
* `code` may be 0 in the event of a timeout.
*
@ -606,16 +669,19 @@ struct keyboard *new_keyboard(struct config *config,
* of kbd_process_key_event must take place. A return value of 0 permits the
* main loop to call at liberty.
*/
static long process_event(struct keyboard *kbd, uint8_t code, int pressed, int timestamp)
static long process_event(struct keyboard *kbd, uint8_t code, int pressed, int time)
{
int dl = -1;
struct descriptor d;
int timeleft = kbd->timeout - (timestamp - kbd->last_event_ts);
kbd->last_event_ts = timestamp;
int timeleft = kbd->timeout - (time - kbd->last_event_ts);
kbd->last_event_ts = time;
/* timeout */
if (!code) {
if (kbd->overload2.active)
return resolve_overload2(kbd, time, 1);
if (kbd->active_macro) {
execute_macro(kbd, kbd->active_macro_layer, kbd->active_macro);
return kbd->macro_repeat_timeout;
@ -632,6 +698,32 @@ static long process_event(struct keyboard *kbd, uint8_t code, int pressed, int t
return process_descriptor(kbd, code, d, dl, 1);
}
} else {
if (kbd->overload2.active) {
if (kbd->overload2.code == code) {
return resolve_overload2(kbd, time, 0);
} else {
assert(kbd->overload2.n < ARRAY_SIZE(kbd->overload2.queued));
struct key_event *ev = &kbd->overload2.queued[kbd->overload2.n++];
ev->code = code;
ev->pressed = pressed;
ev->timestamp = time;
//TODO: make this optional (overload3)
if (!pressed) {
size_t i;
for (i = 0; i < kbd->overload2.n; i++)
if (kbd->overload2.queued[i].code == code &&
kbd->overload2.queued[i].pressed) {
return resolve_overload2(kbd, time, 1);
}
}
return timeleft;
}
}
if (kbd->pending_timeout.active) {
int dl = kbd->pending_timeout.dl;
uint8_t code = kbd->pending_timeout.code;
@ -685,7 +777,7 @@ long kbd_process_events(struct keyboard *kbd, const struct key_event *events, si
while (i != n) {
const struct key_event *ev = &events[i];
if (timeout && timeout_ts < ev->timestamp) {
if (timeout > 0 && timeout_ts < ev->timestamp) {
timeout = process_event(kbd, 0, 0, timeout_ts);
} else {
timeout = process_event(kbd, ev->code, ev->pressed, ev->timestamp);

@ -52,6 +52,18 @@ struct keyboard {
int timeout;
int last_event_ts;
struct {
uint8_t active;
uint8_t code;
uint8_t layer;
struct descriptor *action;
uint8_t dl;
struct key_event queued[32];
uint8_t n;
} overload2;
struct {
long activation_time;

@ -7,7 +7,6 @@ a down
a up
rightmeta up
meta down
control down
meta up

@ -20,12 +20,12 @@ w = oneshot(customshift)
7 = overload(meta, oneshot(control))
8 = timeout(overload(control, a), 1, b)
9 = M-C-S-x
q = toggle(M-C-A)
l = layer(test)
t = overload(o, esc, 2)
m = macro(C-h one)
c = oneshot(control)
s = layer(shift)
o = overload2(control, a, 10)
; = overload2(shift, b, 10)
- = toggle(dvorak)
= = timeout(a, 300, b)
\ = 😄
@ -34,7 +34,6 @@ s = layer(shift)
[layout2:layout]
a = c
- = layout(main)
[control]
@ -58,7 +57,7 @@ c = macro(leftcontrol n)
o = oneshot(o)
a = b
b = toggle(test)
c = reset()
c = clear()
[o:C]

Loading…
Cancel
Save