initial commit
This commit is contained in:
commit
1c606d0274
36 changed files with 9908 additions and 0 deletions
159
modifier.c
Normal file
159
modifier.c
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Management of keys that can be latched or locked.
|
||||
*
|
||||
* Copyright (c) 2024, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include "ufkbd.h"
|
||||
|
||||
static int mod_key_id(xkb_keysym_t sym)
|
||||
{
|
||||
if (sym == XKB_KEY_Shift_L || sym == XKB_KEY_Shift_R)
|
||||
return UFKBD_MOD_SHIFT;
|
||||
else if (sym == XKB_KEY_Control_L || sym == XKB_KEY_Control_R)
|
||||
return UFKBD_MOD_CTRL;
|
||||
else if (sym == XKB_KEY_Alt_L || sym == XKB_KEY_Alt_R)
|
||||
return UFKBD_MOD_ALT;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline enum ufkbd_mod_state get_mod_state(const struct ufkbd_ctx *ctx, int id)
|
||||
{
|
||||
int shift = id % 16 * 2;
|
||||
|
||||
return (ctx->mods[id / 16] >> shift) & 0x3;
|
||||
}
|
||||
|
||||
static inline void set_mod_state(struct ufkbd_ctx *ctx, int id, enum ufkbd_mod_state state)
|
||||
{
|
||||
int shift = id % 16 * 2;
|
||||
|
||||
ctx->mods[id / 16] = (ctx->mods[id / 16] & ~(0x3 << shift))
|
||||
| state << shift;
|
||||
}
|
||||
|
||||
bool ufkbd_is_modifier(struct ufkbd_press *press)
|
||||
{
|
||||
xkb_keysym_t sym;
|
||||
int part, mod;
|
||||
|
||||
part = press->part;
|
||||
sym = press->key->keysyms[part];
|
||||
|
||||
mod = mod_key_id(sym);
|
||||
|
||||
return mod != -1;
|
||||
}
|
||||
|
||||
enum ufkbd_mod_state ufkbd_modifier_get_state(const struct ufkbd_ctx *ctx,
|
||||
const struct ufkbd_key *key,
|
||||
int part)
|
||||
{
|
||||
xkb_keysym_t sym;
|
||||
int mod;
|
||||
|
||||
sym = key->keysyms[part];
|
||||
|
||||
mod = mod_key_id(sym);
|
||||
if (mod == -1)
|
||||
return UFKBD_MOD_RELEASED;
|
||||
|
||||
return get_mod_state(ctx, mod);
|
||||
}
|
||||
|
||||
void ufkbd_modifier_press(struct ufkbd_ctx *ctx, struct ufkbd_press *press)
|
||||
{
|
||||
xkb_keysym_t sym;
|
||||
enum ufkbd_mod_state curr;
|
||||
int part, mod;
|
||||
|
||||
part = press->part;
|
||||
sym = press->key->keysyms[part];
|
||||
|
||||
// If this fails, the key is not a modifier key.
|
||||
mod = mod_key_id(sym);
|
||||
if (mod == -1)
|
||||
return;
|
||||
|
||||
curr = get_mod_state(ctx, mod);
|
||||
if (curr == UFKBD_MOD_RELEASED) {
|
||||
set_mod_state(ctx, mod, UFKBD_MOD_PRESSED);
|
||||
ctx->drv->send_mod(ctx->drv_data, mod, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ufkbd_modifier_cancel(struct ufkbd_ctx *ctx, struct ufkbd_press *press)
|
||||
{
|
||||
xkb_keysym_t sym;
|
||||
enum ufkbd_mod_state curr;
|
||||
int part, mod;
|
||||
|
||||
part = press->part;
|
||||
sym = press->key->keysyms[part];
|
||||
|
||||
mod = mod_key_id(sym);
|
||||
if (mod == -1)
|
||||
return;
|
||||
|
||||
curr = get_mod_state(ctx, mod);
|
||||
if (curr == UFKBD_MOD_PRESSED) {
|
||||
set_mod_state(ctx, mod, UFKBD_MOD_RELEASED);
|
||||
ctx->drv->send_mod(ctx->drv_data, mod, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ufkbd_modifier_release(struct ufkbd_ctx *ctx, struct ufkbd_press *press)
|
||||
{
|
||||
struct timespec now = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = 0,
|
||||
};
|
||||
enum ufkbd_mod_state curr;
|
||||
xkb_keysym_t sym;
|
||||
int part, mod;
|
||||
|
||||
part = press->part;
|
||||
sym = press->key->keysyms[part];
|
||||
|
||||
mod = mod_key_id(sym);
|
||||
if (mod == -1)
|
||||
return;
|
||||
|
||||
curr = get_mod_state(ctx, mod);
|
||||
|
||||
if (curr == UFKBD_MOD_PRESSED) {
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
|
||||
if (now.tv_sec > press->repeat.tv_sec
|
||||
|| (now.tv_sec == press->repeat.tv_sec
|
||||
&& now.tv_nsec > press->repeat.tv_nsec))
|
||||
set_mod_state(ctx, mod, UFKBD_MOD_LOCKED);
|
||||
else
|
||||
set_mod_state(ctx, mod, UFKBD_MOD_LATCHED);
|
||||
} else if (curr == UFKBD_MOD_LATCHED || curr == UFKBD_MOD_LOCKED) {
|
||||
set_mod_state(ctx, mod, UFKBD_MOD_RELEASED);
|
||||
ctx->drv->send_mod(ctx->drv_data, mod, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ufkbd_modifier_unlatch_all(struct ufkbd_ctx *ctx)
|
||||
{
|
||||
enum ufkbd_mod_state curr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UFKBD_MOD_MAX; i++) {
|
||||
curr = get_mod_state(ctx, i);
|
||||
if (curr == UFKBD_MOD_LATCHED) {
|
||||
set_mod_state(ctx, i, UFKBD_MOD_RELEASED);
|
||||
ctx->drv->send_mod(ctx->drv_data, i, false);
|
||||
} else if (curr == UFKBD_MOD_PRESSED) {
|
||||
// This modifier key should go up on first release.
|
||||
set_mod_state(ctx, i, UFKBD_MOD_LOCKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue