mirror of
https://github.com/labwc/labwc.git
synced 2026-06-13 14:33:18 -04:00
Merge 13a487fb35 into 579e532908
This commit is contained in:
commit
52cc5e64d6
4 changed files with 155 additions and 4 deletions
|
|
@ -45,6 +45,7 @@ bool keybind_the_same(struct keybind *a, struct keybind *b);
|
|||
|
||||
bool keybind_contains_keycode(struct keybind *keybind, xkb_keycode_t keycode);
|
||||
bool keybind_contains_keysym(struct keybind *keybind, xkb_keysym_t keysym);
|
||||
bool keybind_contains_any_keysym(struct keybind *keybind, const xkb_keysym_t *syms, int nr_syms);
|
||||
|
||||
void keybind_update_keycodes(void);
|
||||
#endif /* LABWC_KEYBIND_H */
|
||||
|
|
|
|||
150
src/action.c
150
src/action.c
|
|
@ -8,6 +8,7 @@
|
|||
#include <unistd.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "action-prompt-codes.h"
|
||||
#include "common/buf.h"
|
||||
|
|
@ -18,6 +19,7 @@
|
|||
#include "common/spawn.h"
|
||||
#include "common/string-helpers.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "config/keybind.h"
|
||||
#include "cycle.h"
|
||||
#include "debug.h"
|
||||
#include "input/keyboard.h"
|
||||
|
|
@ -139,6 +141,7 @@ struct action_arg_list {
|
|||
X(TOGGLE_SHOW_DESKTOP, "ToggleShowDesktop") \
|
||||
X(WARP_CURSOR, "WarpCursor") \
|
||||
X(HIDE_CURSOR, "HideCursor") \
|
||||
X(SEND_KEY, "SendKey") \
|
||||
X(DEBUG_TOGGLE_KEY_STATE_INDICATOR, "DebugToggleKeyStateIndicator")
|
||||
|
||||
/*
|
||||
|
|
@ -535,6 +538,12 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
|||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_SEND_KEY:
|
||||
if (!strcasecmp(argument, "identifier") || !strcasecmp(argument, "key")) {
|
||||
action_arg_add_str(action, argument, content);
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_IF:
|
||||
if (!strcmp(argument, "message.prompt")) {
|
||||
action_arg_add_str(action, "message.prompt", content);
|
||||
|
|
@ -652,6 +661,9 @@ action_is_valid(struct action *action)
|
|||
case ACTION_TYPE_SNAP_TO_REGION:
|
||||
arg_name = "region";
|
||||
break;
|
||||
case ACTION_TYPE_SEND_KEY:
|
||||
arg_name = "identifier";
|
||||
break;
|
||||
case ACTION_TYPE_IF:
|
||||
case ACTION_TYPE_FOR_EACH:
|
||||
return action_branches_are_valid(action);
|
||||
|
|
@ -1054,6 +1066,141 @@ warp_cursor(struct view *view, const char *to, const char *x, const char *y)
|
|||
cursor_update_focus();
|
||||
}
|
||||
|
||||
static void
|
||||
action_key_update_keycodes_iter(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
|
||||
{
|
||||
struct keybind *keybind = (struct keybind *)data;
|
||||
const xkb_keysym_t *syms;
|
||||
|
||||
xkb_layout_index_t layouts = xkb_keymap_num_layouts(keymap);
|
||||
for (xkb_layout_index_t layout = 0; layout < layouts; layout++) {
|
||||
int nr_syms = xkb_keymap_key_get_syms_by_level(keymap, key, layout, 0, &syms);
|
||||
if (!nr_syms) {
|
||||
continue;
|
||||
}
|
||||
if (keybind->keycodes_layout >= 0
|
||||
&& (xkb_layout_index_t)keybind->keycodes_layout != layout) {
|
||||
/* Prevent storing keycodes from multiple layouts */
|
||||
continue;
|
||||
}
|
||||
if (keybind_contains_any_keysym(keybind, syms, nr_syms)) {
|
||||
if (keybind_contains_keycode(keybind, key)) {
|
||||
/* Prevent storing the same keycode twice */
|
||||
continue;
|
||||
}
|
||||
if (keybind->keycodes_len == MAX_KEYCODES) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Already stored %lu keycodes for keybind",
|
||||
keybind->keycodes_len);
|
||||
continue;
|
||||
}
|
||||
keybind->keycodes[keybind->keycodes_len++] = key;
|
||||
keybind->keycodes_layout = layout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
action_key_update_keycodes(struct keybind *keybind, struct xkb_keymap *keymap)
|
||||
{
|
||||
keybind->keycodes_len = 0;
|
||||
keybind->keycodes_layout = -1;
|
||||
|
||||
xkb_keymap_key_for_each(keymap, action_key_update_keycodes_iter, keybind);
|
||||
}
|
||||
|
||||
static bool
|
||||
action_key_parse(const char *key, struct wlr_keyboard_modifiers *modifiers,
|
||||
uint32_t *keycodes, size_t *num_keycodes)
|
||||
{
|
||||
struct wlr_keyboard *kb = wlr_seat_get_keyboard(server.seat.wlr_seat);
|
||||
if (!kb) {
|
||||
return false;
|
||||
}
|
||||
if (!key) {
|
||||
*modifiers = kb->modifiers;
|
||||
*num_keycodes = kb->num_keycodes > MAX_KEYCODES ? MAX_KEYCODES : kb->num_keycodes;
|
||||
for (size_t i = 0; i < *num_keycodes; ++i) {
|
||||
keycodes[i] = kb->keycodes[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!kb->keymap) {
|
||||
return false;
|
||||
}
|
||||
struct keybind *k = NULL;
|
||||
k = keybind_create(key);
|
||||
if (!k) {
|
||||
return false;
|
||||
}
|
||||
|
||||
action_key_update_keycodes(k, kb->keymap);
|
||||
modifiers->depressed = k->modifiers;
|
||||
*num_keycodes = k->keycodes_len;
|
||||
for (size_t i = 0; i < *num_keycodes; ++i) {
|
||||
if (k->keycodes[i] < 8) {
|
||||
keybind_destroy(k);
|
||||
return false;
|
||||
}
|
||||
keycodes[i] = k->keycodes[i] - 8;
|
||||
}
|
||||
keybind_destroy(k);
|
||||
if (modifiers->depressed == 0 && *num_keycodes == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
action_send_key(struct action *action, struct view *view)
|
||||
{
|
||||
struct view *target_view;
|
||||
struct wlr_seat *wlr_seat = server.seat.wlr_seat;
|
||||
struct wlr_keyboard *kb = wlr_seat_get_keyboard(server.seat.wlr_seat);
|
||||
if (!kb) {
|
||||
return;
|
||||
}
|
||||
struct timespec now = {0};
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
uint64_t time_msec = now.tv_sec * 1000 + now.tv_nsec / 1000000;
|
||||
const char *identifier = action_get_str(action, "identifier", NULL);
|
||||
if (!identifier) {
|
||||
return;
|
||||
}
|
||||
uint32_t *sent_keycodes = key_state_pressed_sent_keycodes();
|
||||
int num_sent_keycodes = key_state_nr_pressed_sent_keycodes();
|
||||
const char *key = action_get_str(action, "key", NULL);
|
||||
struct wlr_keyboard_modifiers modifiers = {0};
|
||||
uint32_t keycodes[MAX_KEYCODES];
|
||||
size_t num_keycodes = 0;
|
||||
if (!action_key_parse(key, &modifiers, keycodes, &num_keycodes)) {
|
||||
wlr_log(WLR_ERROR, "Failed to parse key: %s", key);
|
||||
return;
|
||||
}
|
||||
bool sent = false;
|
||||
for_each_view(target_view, &server.views, LAB_VIEW_CRITERIA_NONE) {
|
||||
if (target_view->surface && !strcasecmp(target_view->app_id, identifier)) {
|
||||
wlr_seat_keyboard_notify_enter(wlr_seat, target_view->surface,
|
||||
sent_keycodes, num_sent_keycodes, &modifiers);
|
||||
wlr_seat_keyboard_notify_modifiers(wlr_seat, &modifiers);
|
||||
for (size_t i = 0; i < num_keycodes; i++) {
|
||||
wlr_seat_keyboard_notify_key(wlr_seat, (uint32_t)time_msec,
|
||||
keycodes[i], WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
}
|
||||
for (size_t i = num_keycodes; i > 0; i--) {
|
||||
wlr_seat_keyboard_notify_key(wlr_seat, (uint32_t)time_msec,
|
||||
keycodes[i-1], WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||
}
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
if (sent && view && view->surface) {
|
||||
wlr_seat_keyboard_notify_enter(wlr_seat, view->surface,
|
||||
sent_keycodes, num_sent_keycodes, &kb->modifiers);
|
||||
wlr_seat_keyboard_notify_modifiers(wlr_seat, &kb->modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
run_action(struct view *view, struct action *action,
|
||||
struct cursor_context *ctx)
|
||||
|
|
@ -1447,6 +1594,9 @@ run_action(struct view *view, struct action *action,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_TYPE_SEND_KEY:
|
||||
action_send_key(action, view);
|
||||
break;
|
||||
case ACTION_TYPE_IF: {
|
||||
/* At least one of the queries was matched or there was no query */
|
||||
if (action_get_str(action, "message.prompt", NULL)) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include <string.h>
|
||||
#include <wlr/types/wlr_keyboard_group.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "common/list.h"
|
||||
#include "common/mem.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "labwc.h"
|
||||
|
|
@ -72,7 +71,7 @@ keybind_contains_keysym(struct keybind *keybind, xkb_keysym_t keysym)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
bool
|
||||
keybind_contains_any_keysym(struct keybind *keybind,
|
||||
const xkb_keysym_t *syms, int nr_syms)
|
||||
{
|
||||
|
|
@ -205,7 +204,6 @@ keybind_create(const char *keybind)
|
|||
if (!k) {
|
||||
return NULL;
|
||||
}
|
||||
wl_list_append(&rc.keybinds, &k->link);
|
||||
k->keysyms = xmalloc(k->keysyms_len * sizeof(xkb_keysym_t));
|
||||
memcpy(k->keysyms, keysyms, k->keysyms_len * sizeof(xkb_keysym_t));
|
||||
wl_list_init(&k->actions);
|
||||
|
|
|
|||
|
|
@ -593,6 +593,8 @@ fill_keybind(xmlNode *node)
|
|||
keybind = keybind_create(keyname);
|
||||
if (!keybind) {
|
||||
wlr_log(WLR_ERROR, "Invalid keybind: %s", keyname);
|
||||
} else {
|
||||
wl_list_append(&rc.keybinds, &keybind->link);
|
||||
}
|
||||
}
|
||||
if (!keybind) {
|
||||
|
|
@ -1617,7 +1619,7 @@ load_default_key_bindings(void)
|
|||
if (!k) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wl_list_append(&rc.keybinds, &k->link);
|
||||
action = action_create(current->action);
|
||||
wl_list_append(&k->actions, &action->link);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue