/*
- * Copyright 2009 Dan Nicholson
+ * Copyright © 2009 Dan Nicholson
+ * Copyright © 2012 Intel Corporation
+ * Copyright © 2012 Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
- * Except as contained in this notice, the names of the authors or their
- * institutions shall not be used in advertising or otherwise to promote the
- * sale, use or other dealings in this Software without prior written
- * authorization from the authors.
+ * Author: Dan Nicholson <dbn.lists@gmail.com>
+ * Daniel Stone <daniel@fooishbar.org>
+ * Ran Benita <ran234@gmail.com>
*/
+#include "config.h"
+
#include "xkbcomp-priv.h"
static void
ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
{
- xkb_mod_index_t i;
- xkb_mod_mask_t vmask = mods->mods >> XkbNumModifiers;
-
- /* The effective mask is only real mods for now. */
- mods->mask = mods->mods & 0xff;
-
- for (i = 0; i < XkbNumVirtualMods; i++) {
- if (!(vmask & (1 << i)))
- continue;
- mods->mask |= keymap->vmods[i];
- }
+ mods->mask = mod_mask_get_effective(keymap, mods->mods);
}
static void
UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
- xkb_mod_mask_t rmodmask)
+ xkb_mod_mask_t modmap)
{
- unsigned int flags;
- struct xkb_mods *mods;
-
switch (act->type) {
- case XkbSA_SetMods:
- case XkbSA_LatchMods:
- case XkbSA_LockMods:
- flags = act->mods.flags;
- mods = &act->mods.mods;
+ case ACTION_TYPE_MOD_SET:
+ case ACTION_TYPE_MOD_LATCH:
+ case ACTION_TYPE_MOD_LOCK:
+ if (act->mods.flags & ACTION_MODS_LOOKUP_MODMAP)
+ act->mods.mods.mods = modmap;
+ ComputeEffectiveMask(keymap, &act->mods.mods);
break;
-
- case XkbSA_ISOLock:
- flags = act->iso.flags;
- mods = &act->iso.mods;
- break;
-
default:
- return;
- }
-
- if (flags & XkbSA_UseModMapMods) {
- /* XXX: what's that. */
- mods->mods &= 0xff;
- mods->mods |= rmodmask;
+ break;
}
- ComputeEffectiveMask(keymap, mods);
}
+static const struct xkb_sym_interpret default_interpret = {
+ .sym = XKB_KEY_NoSymbol,
+ .repeat = true,
+ .match = MATCH_ANY_OR_NONE,
+ .mods = 0,
+ .virtual_mod = XKB_MOD_INVALID,
+ .action = { .type = ACTION_TYPE_NONE },
+};
+
/**
* Find an interpretation which applies to this particular level, either by
* finding an exact match for the symbol and modifier combination, or a
* generic XKB_KEY_NoSymbol match.
*/
-static struct xkb_sym_interpret *
-FindInterpForKey(struct xkb_keymap *keymap, struct xkb_key *key,
- xkb_group_index_t group, xkb_level_index_t level)
+static const struct xkb_sym_interpret *
+FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key,
+ xkb_layout_index_t group, xkb_level_index_t level)
{
- struct xkb_sym_interpret *interp;
const xkb_keysym_t *syms;
int num_syms;
- num_syms = xkb_key_get_syms_by_level(keymap, key, group, level, &syms);
+ num_syms = xkb_keymap_key_get_syms_by_level(keymap, key->keycode, group,
+ level, &syms);
if (num_syms == 0)
return NULL;
/*
* There may be multiple matchings interprets; we should always return
* the most specific. Here we rely on compat.c to set up the
- * sym_interpret array from the most specific to the least specific,
+ * sym_interprets array from the most specific to the least specific,
* such that when we find a match we return immediately.
*/
- darray_foreach(interp, keymap->sym_interpret) {
- uint32_t mods;
- bool found;
+ for (unsigned i = 0; i < keymap->num_sym_interprets; i++) {
+ const struct xkb_sym_interpret *interp = &keymap->sym_interprets[i];
+
+ xkb_mod_mask_t mods;
+ bool found = false;
if ((num_syms > 1 || interp->sym != syms[0]) &&
interp->sym != XKB_KEY_NoSymbol)
continue;
- if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
- mods = key->modmap;
- else
+ if (interp->level_one_only && level != 0)
mods = 0;
+ else
+ mods = key->modmap;
- switch (interp->match & XkbSI_OpMask) {
- case XkbSI_NoneOf:
+ switch (interp->match) {
+ case MATCH_NONE:
found = !(interp->mods & mods);
break;
- case XkbSI_AnyOfOrNone:
+ case MATCH_ANY_OR_NONE:
found = (!mods || (interp->mods & mods));
break;
- case XkbSI_AnyOf:
- found = !!(interp->mods & mods);
+ case MATCH_ANY:
+ found = (interp->mods & mods);
break;
- case XkbSI_AllOf:
+ case MATCH_ALL:
found = ((interp->mods & mods) == interp->mods);
break;
- case XkbSI_Exactly:
+ case MATCH_EXACTLY:
found = (interp->mods == mods);
break;
- default:
- found = false;
- break;
}
if (found)
return interp;
}
- return NULL;
+ return &default_interpret;
}
static bool
ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
{
- xkb_mod_mask_t vmodmask = 0;
- xkb_group_index_t group;
- xkb_level_index_t width, level;
+ xkb_mod_mask_t vmodmap = 0;
+ xkb_layout_index_t group;
+ xkb_level_index_t level;
/* If we've been told not to bind interps to this key, then don't. */
- if (key->explicit & XkbExplicitInterpretMask)
+ if (key->explicit & EXPLICIT_INTERP)
return true;
for (group = 0; group < key->num_groups; group++) {
- width = XkbKeyGroupWidth(keymap, key, group);
- for (level = 0; level < width; level++) {
- struct xkb_sym_interpret *interp;
+ for (level = 0; level < XkbKeyNumLevels(key, group); level++) {
+ const struct xkb_sym_interpret *interp;
interp = FindInterpForKey(keymap, key, group, level);
+ if (!interp)
+ continue;
/* Infer default key behaviours from the base level. */
- if (group == 0 && level == 0) {
- if (!(key->explicit & XkbExplicitAutoRepeatMask) &&
- (!interp || (interp->flags & XkbSI_AutoRepeat)))
+ if (group == 0 && level == 0)
+ if (!(key->explicit & EXPLICIT_REPEAT) && interp->repeat)
key->repeats = true;
- }
- if (!interp)
- continue;
-
- if ((group == 0 && level == 0) ||
- !(interp->match & XkbSI_LevelOneOnly)) {
+ if ((group == 0 && level == 0) || !interp->level_one_only)
if (interp->virtual_mod != XKB_MOD_INVALID)
- vmodmask |= (1 << interp->virtual_mod);
- }
-
- if (interp->act.type != XkbSA_NoAction) {
- if (!key->actions) {
- key->actions = calloc(key->num_groups * key->width,
- sizeof(*key->actions));
- if (!key->actions)
- return false;
- }
+ vmodmap |= (1u << interp->virtual_mod);
- *XkbKeyActionEntry(key, group, level) = interp->act;
- }
+ if (interp->action.type != ACTION_TYPE_NONE)
+ key->groups[group].levels[level].action = interp->action;
}
}
- if (!(key->explicit & XkbExplicitVModMapMask))
- key->vmodmap = vmodmask;
+ if (!(key->explicit & EXPLICIT_VMODMAP))
+ key->vmodmap = vmodmap;
return true;
}
static bool
UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
{
- xkb_mod_index_t vmod;
- xkb_led_index_t led;
- unsigned int i, j;
struct xkb_key *key;
+ struct xkb_mod *mod;
+ struct xkb_led *led;
+ unsigned int i, j;
/* Find all the interprets for the key and bind them to actions,
* which will also update the vmodmap. */
- xkb_foreach_key(key, keymap)
+ xkb_keys_foreach(key, keymap)
if (!ApplyInterpsToKey(keymap, key))
return false;
- /* Update keymap->vmods, the virtual -> real mod mapping. */
- for (vmod = 0; vmod < XkbNumVirtualMods; vmod++)
- keymap->vmods[vmod] = 0;
-
- xkb_foreach_key(key, keymap) {
- if (!key->vmodmap)
- continue;
-
- for (vmod = 0; vmod < XkbNumVirtualMods; vmod++) {
- if (!(key->vmodmap & (1 << vmod)))
- continue;
- keymap->vmods[vmod] |= key->modmap;
- }
- }
+ /* Update keymap->mods, the virtual -> real mod mapping. */
+ xkb_keys_foreach(key, keymap)
+ xkb_mods_enumerate(i, mod, &keymap->mods)
+ if (key->vmodmap & (1u << i))
+ mod->mapping |= key->modmap;
/* Now update the level masks for all the types to reflect the vmods. */
for (i = 0; i < keymap->num_types; i++) {
ComputeEffectiveMask(keymap, &keymap->types[i].mods);
for (j = 0; j < keymap->types[i].num_entries; j++) {
- ComputeEffectiveMask(keymap, &keymap->types[i].map[j].mods);
- ComputeEffectiveMask(keymap, &keymap->types[i].map[j].preserve);
+ ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].mods);
+ ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].preserve);
}
}
/* Update action modifiers. */
- xkb_foreach_key(key, keymap) {
- if (!key->actions)
- continue;
-
- for (i = 0; i < key->num_groups * key->width; i++)
- UpdateActionMods(keymap, &key->actions[i], key->modmap);
- }
+ xkb_keys_foreach(key, keymap)
+ for (i = 0; i < key->num_groups; i++)
+ for (j = 0; j < XkbKeyNumLevels(key, i); j++)
+ UpdateActionMods(keymap, &key->groups[i].levels[j].action,
+ key->modmap);
- /* Update vmod -> indicator maps. */
- for (led = 0; led < XkbNumIndicators; led++)
- ComputeEffectiveMask(keymap, &keymap->indicators[led].mods);
+ /* Update vmod -> led maps. */
+ xkb_leds_foreach(led, keymap)
+ ComputeEffectiveMask(keymap, &led->mods);
/* Find maximum number of groups out of all keys in the keymap. */
- xkb_foreach_key(key, keymap)
+ xkb_keys_foreach(key, keymap)
keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
return true;
CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
{
bool ok;
- const char *main_name;
XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
enum xkb_file_type type;
struct xkb_context *ctx = keymap->ctx;
- main_name = file->name ? file->name : "(unnamed)";
-
/* Collect section files and check for duplicates. */
for (file = (XkbFile *) file->defs; file;
file = (XkbFile *) file->common.next) {
if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
file->file_type > LAST_KEYMAP_FILE_TYPE) {
- log_err(ctx, "Cannot define %s in a keymap file\n",
- xkb_file_type_to_string(file->file_type));
+ if (file->file_type == FILE_TYPE_GEOMETRY) {
+ log_vrb(ctx, 1,
+ XKB_WARNING_UNSUPPORTED_GEOMETRY_SECTION,
+ "Geometry sections are not supported; ignoring\n");
+ } else {
+ log_err(ctx, XKB_LOG_MESSAGE_NO_ID,
+ "Cannot define %s in a keymap file\n",
+ xkb_file_type_to_string(file->file_type));
+ }
continue;
}
if (files[file->file_type]) {
- log_err(ctx,
+ log_err(ctx, XKB_LOG_MESSAGE_NO_ID,
"More than one %s section in keymap file; "
"All sections after the first ignored\n",
xkb_file_type_to_string(file->file_type));
continue;
}
- if (!file->topName) {
- free(file->topName);
- file->topName = strdup(main_name);
- }
-
files[file->file_type] = file;
}
type <= LAST_KEYMAP_FILE_TYPE;
type++) {
if (files[type] == NULL) {
- log_err(ctx, "Required section %s missing from keymap\n",
+ log_err(ctx, XKB_LOG_MESSAGE_NO_ID,
+ "Required section %s missing from keymap\n",
xkb_file_type_to_string(type));
ok = false;
}
for (type = FIRST_KEYMAP_FILE_TYPE;
type <= LAST_KEYMAP_FILE_TYPE;
type++) {
- log_dbg(ctx, "Compiling %s \"%s\"\n",
- xkb_file_type_to_string(type), files[type]->topName);
+ log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID,
+ "Compiling %s \"%s\"\n",
+ xkb_file_type_to_string(type), files[type]->name);
ok = compile_file_fns[type](files[type], keymap, merge);
if (!ok) {
- log_err(ctx, "Failed to compile %s\n",
+ log_err(ctx, XKB_LOG_MESSAGE_NO_ID,
+ "Failed to compile %s\n",
xkb_file_type_to_string(type));
return false;
}