Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actions/locks xkb extension v3 #527

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bench/key-proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ main(void)
ctx = test_get_context(0);
assert(ctx);

keymap = test_compile_rules(ctx, "evdev", "pc104", "us,ru,il,de",
keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1,
"evdev", "pc104", "us,ru,il,de",
",,,neo", "grp:menu_toggle");
assert(keymap);

Expand Down
3 changes: 2 additions & 1 deletion bench/rulescomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ main(int argc, char *argv[])

bench_start(&bench);
for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
keymap = test_compile_rules(ctx, "evdev", "evdev", "us", "", "");
keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1,
"evdev", "evdev", "us", "", "");
assert(keymap);
xkb_keymap_unref(keymap);
}
Expand Down
12 changes: 11 additions & 1 deletion doc/message-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ NOTE: This file has been generated automatically by “update-message-registry.p
-->

This page lists the warnings and errors generated by xkbcommon.
There are currently 61 entries.
There are currently 62 entries.

@todo The documentation of the log messages is a work in progress.

Expand Down Expand Up @@ -57,6 +57,7 @@ There are currently 61 entries.
| [XKB-623] | `invalid-real-modifier` | Invalid _real_ modifier | Error |
| [XKB-645] | `unknown-char-escape-sequence` | Warn on unknown escape sequence in string literal | Warning |
| [XKB-661] | `invalid-included-file` | The target file of an include statement could not be processed | Error |
| [XKB-689] | `incompatible-keymap-export-format` | The keymap has features that cannot be exported in the target format | Error |
| [XKB-693] | `incompatible-actions-and-keysyms-count` | A level has a different number of keysyms and actions | Error |
| [XKB-700] | `multiple-groups-at-once` | Warn if a key defines multiple groups at once | Warning |
| [XKB-711] | `unsupported-symbols-field` | A legacy X11 symbol field is not supported | Warning |
Expand Down Expand Up @@ -597,6 +598,14 @@ xkbcommon support the following escape sequences in string literals:
<dt>Summary</dt><dd>The target file of an include statement could not be processed</dd>
</dl>

### XKB-689 – Incompatible keymap export format {#XKB-689}

<dl>
<dt>Since</dt><dd>1.8.0</dd>
<dt>Type</dt><dd>Error</dd>
<dt>Summary</dt><dd>The keymap has features that cannot be exported in the target format</dd>
</dl>

### XKB-693 – Incompatible actions and keysyms count {#XKB-693}

<dl>
Expand Down Expand Up @@ -794,6 +803,7 @@ The modifiers used in `map` or `preserve` entries should be declared using the e
[XKB-623]: @ref XKB-623
[XKB-645]: @ref XKB-645
[XKB-661]: @ref XKB-661
[XKB-689]: @ref XKB-689
[XKB-693]: @ref XKB-693
[XKB-700]: @ref XKB-700
[XKB-711]: @ref XKB-711
Expand Down
5 changes: 5 additions & 0 deletions doc/message-registry.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@
added: ALWAYS
type: error
description: "The target file of an include statement could not be processed"
- id: "incompatible-keymap-export-format"
code: 689
added: 1.8.0
type: error
description: "The keymap has features that cannot be exported in the target format"
- id: "incompatible-actions-and-keysyms-count"
code: 693
added: 1.8.0
Expand Down
35 changes: 29 additions & 6 deletions include/xkbcommon/xkbcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,12 @@ enum xkb_keymap_compile_flags {
XKB_KEYMAP_COMPILE_NO_FLAGS = 0
};

/** The possible keymap formats. */
enum xkb_keymap_format {
/** The current/classic XKB text format, as generated by `xkbcomp -xkb`. */
XKB_KEYMAP_FORMAT_TEXT_V1 = 1
};

/**
* Create a keymap from RMLVO names.
*
Expand All @@ -891,19 +897,36 @@ enum xkb_keymap_compile_flags {
* @returns A keymap compiled according to the RMLVO names, or NULL if
* the compilation failed.
*
* @sa xkb_rule_names
* @sa xkb_rule_names xkb_keymap_new_from_names2
* @memberof xkb_keymap
*/
struct xkb_keymap *
xkb_keymap_new_from_names(struct xkb_context *context,
const struct xkb_rule_names *names,
enum xkb_keymap_compile_flags flags);

/** The possible keymap formats. */
enum xkb_keymap_format {
/** The current/classic XKB text format, as generated by xkbcomp -xkb. */
XKB_KEYMAP_FORMAT_TEXT_V1 = 1
};
/**
* Create a keymap from RMLVO names using a specific keymap format.
*
* The primary keymap entry point: creates a new XKB keymap from a set of
* RMLVO (Rules + Model + Layouts + Variants + Options) names.
*
* @param context The context in which to create the keymap.
* @param names The RMLVO names to use. See xkb_rule_names.
* @param format The text format of the keymap file to compile.
* @param flags Optional flags for the keymap, or 0.
*
* @returns A keymap compiled according to the RMLVO names, or NULL if
* the compilation failed.
*
* @sa xkb_rule_names xkb_keymap_new_from_names
* @memberof xkb_keymap
*/
struct xkb_keymap *
xkb_keymap_new_from_names2(struct xkb_context *context,
const struct xkb_rule_names *names,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags flags);

/**
* Create a keymap from a keymap file.
Expand Down
24 changes: 19 additions & 5 deletions src/keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ get_keymap_format_ops(enum xkb_keymap_format format)
{
static const struct xkb_keymap_format_ops *keymap_format_ops[] = {
[XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops,
[XKB_KEYMAP_FORMAT_TEXT_V1_1] = &text_v1_keymap_format_ops,
};

if ((int) format < 0 || (int) format >= (int) ARRAY_SIZE(keymap_format_ops))
Expand All @@ -119,15 +120,19 @@ get_keymap_format_ops(enum xkb_keymap_format format)
}

XKB_EXPORT struct xkb_keymap *
xkb_keymap_new_from_names(struct xkb_context *ctx,
const struct xkb_rule_names *rmlvo_in,
enum xkb_keymap_compile_flags flags)
xkb_keymap_new_from_names2(struct xkb_context *ctx,
const struct xkb_rule_names *rmlvo_in,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags flags)
{
struct xkb_keymap *keymap;
struct xkb_rule_names rmlvo;
const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
const struct xkb_keymap_format_ops *ops;

/* HACK: remove once not experimental anymore */
if (!isempty(xkb_context_getenv(ctx, "XKB_EXPERIMENTAL_LOCKS")))
format = XKB_KEYMAP_FORMAT_TEXT_V1_1;

ops = get_keymap_format_ops(format);
if (!ops || !ops->keymap_new_from_names) {
log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID,
Expand Down Expand Up @@ -159,6 +164,15 @@ xkb_keymap_new_from_names(struct xkb_context *ctx,
return keymap;
}

XKB_EXPORT struct xkb_keymap *
xkb_keymap_new_from_names(struct xkb_context *ctx,
const struct xkb_rule_names *rmlvo_in,
enum xkb_keymap_compile_flags flags)
{
return xkb_keymap_new_from_names2(ctx, rmlvo_in,
XKB_KEYMAP_FORMAT_TEXT_V1, flags);
}

XKB_EXPORT struct xkb_keymap *
xkb_keymap_new_from_string(struct xkb_context *ctx,
const char *string,
Expand Down Expand Up @@ -269,7 +283,7 @@ xkb_keymap_get_as_string(struct xkb_keymap *keymap,
return NULL;
}

return ops->keymap_get_as_string(keymap);
return ops->keymap_get_as_string(keymap, format);
}

/**
Expand Down
10 changes: 9 additions & 1 deletion src/keymap.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ enum xkb_action_flags {
ACTION_ABSOLUTE_Y = (1 << 7),
ACTION_ACCEL = (1 << 8),
ACTION_SAME_SCREEN = (1 << 9),
ACTION_LOCK_ON_RELEASE = (1 << 10),
ACTION_UNLOCK_ON_PRESS = (1 << 11),
};

enum xkb_action_controls {
Expand Down Expand Up @@ -523,9 +525,15 @@ struct xkb_keymap_format_ops {
bool (*keymap_new_from_string)(struct xkb_keymap *keymap,
const char *string, size_t length);
bool (*keymap_new_from_file)(struct xkb_keymap *keymap, FILE *file);
char *(*keymap_get_as_string)(struct xkb_keymap *keymap);
char *(*keymap_get_as_string)(struct xkb_keymap *keymap,
enum xkb_keymap_format format);
};

extern const struct xkb_keymap_format_ops text_v1_keymap_format_ops;

/* NOTE: meant to be added to enum xkb_keymap_format */
/** Extension that introduces the options `lockOnRelease` and
* `unlockOnPress`. */
#define XKB_KEYMAP_FORMAT_TEXT_V1_1 2

#endif
2 changes: 2 additions & 0 deletions src/messages-codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ enum xkb_message_code {
XKB_WARNING_UNKNOWN_CHAR_ESCAPE_SEQUENCE = 645,
/** The target file of an include statement could not be processed */
XKB_ERROR_INVALID_INCLUDED_FILE = 661,
/** The keymap has features that cannot be exported in the target format */
XKB_ERROR_INCOMPATIBLE_KEYMAP_EXPORT_FORMAT = 689,
/** A level has a different number of keysyms and actions */
XKB_ERROR_INCOMPATIBLE_ACTIONS_AND_KEYSYMS_COUNT = 693,
/** Warn if a key defines multiple groups at once */
Expand Down
33 changes: 29 additions & 4 deletions src/state.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,11 @@ xkb_filter_group_set_func(struct xkb_state *state,
static void
xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
{
/* XKB 1.1 extension: lock on release
* Do nothing on press */
if (filter->action.group.flags & ACTION_LOCK_ON_RELEASE)
return;

apply_group_delta(filter, state, locked_group);
}

Expand All @@ -298,8 +303,15 @@ xkb_filter_group_lock_func(struct xkb_state *state,
const struct xkb_key *key,
enum xkb_key_direction direction)
{
if (key != filter->key)
if (key != filter->key) {
if (filter->action.group.flags & ACTION_LOCK_ON_RELEASE &&
direction == XKB_KEY_DOWN) {
/* XKB extension: lock on release
* Another key has been pressed: cancel group change on release */
filter->action.group.flags &= ~ACTION_LOCK_ON_RELEASE;
}
return XKB_FILTER_CONTINUE;
}

if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
Expand All @@ -308,6 +320,11 @@ xkb_filter_group_lock_func(struct xkb_state *state,
if (--filter->refcnt > 0)
return XKB_FILTER_CONSUME;

if (filter->action.group.flags & ACTION_LOCK_ON_RELEASE) {
/* XKB extension: lock on release */
apply_group_delta(filter, state, locked_group);
}

filter->func = NULL;
return XKB_FILTER_CONTINUE;
}
Expand Down Expand Up @@ -491,9 +508,17 @@ xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
{
filter->priv = (state->components.locked_mods &
filter->action.mods.mods.mask);
state->set_mods |= filter->action.mods.mods.mask;
if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
state->components.locked_mods |= filter->action.mods.mods.mask;
if (filter->priv && (filter->action.mods.flags & ACTION_UNLOCK_ON_PRESS)) {
/* XKB extension: Unlock on second press */
state->clear_mods |= filter->action.mods.mods.mask;
if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
state->components.locked_mods &= ~filter->priv;
filter->priv = 0;
} else {
state->set_mods |= filter->action.mods.mods.mask;
if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
state->components.locked_mods |= filter->action.mods.mods.mask;
}
}

static bool
Expand Down
Loading
Loading