/* Common keyboard description structure */
struct xkb_desc {
+ unsigned int refcnt;
unsigned int defined;
unsigned short flags;
unsigned short device_spec;
_XFUNCPROTOBEGIN
-_X_EXPORT extern struct xkb_desc *
-xkb_compile_keymap_from_rules(const struct xkb_rule_names *rules);
-
-_X_EXPORT extern struct xkb_desc *
-xkb_compile_keymap_from_components(const struct xkb_component_names * ktcsg);
-
-_X_EXPORT extern struct xkb_desc *
-xkb_compile_keymap_from_file(FILE *inputFile, const char *mapName);
-
-_X_EXPORT extern struct xkb_desc *
-xkb_compile_keymap_from_string(const char *string, const char *mapName);
-
-_X_EXPORT extern void
-xkb_free_keymap(struct xkb_desc *xkb);
-
/*
* Canonicalises component names by prepending the relevant component from
* 'old' to the one in 'names' when the latter has a leading '+' or '|', and
xkb_keysym_t **syms_out);
/**
+ * @defgroup map Keymap management
+ * These utility functions allow you to create and deallocate XKB keymaps.
+ *
+ * @{
+ */
+
+/**
+ * The primary keymap entry point: creates a new XKB keymap from a set of
+ * RMLVO (Rules + Model + Layout + Variant + Option) names.
+ *
+ * You should almost certainly be using this and nothing else to create
+ * keymaps.
+ */
+_X_EXPORT extern struct xkb_desc *
+xkb_map_new_from_names(const struct xkb_rule_names *names);
+
+/**
+ * Deprecated entrypoint for legacy users who need to be able to compile
+ * XKB keymaps by KcCGST (Keycodes + Compat + Geometry + Symbols + Types)
+ * names.
+ *
+ * You should not use this unless you are the X server. This entrypoint
+ * may well disappear in future releases. Please, please, don't use it.
+ *
+ * Geometry will be ignored since xkbcommon does not support it in any way.
+ */
+_X_EXPORT extern struct xkb_desc *
+xkb_map_new_from_kccgst(const struct xkb_component_names *kccgst);
+
+enum xkb_keymap_format {
+ /** The current/classic XKB text format, as generated by xkbcomp -xkb. */
+ XKB_KEYMAP_FORMAT_TEXT_V1 = 1,
+};
+
+/**
+ * Creates an XKB keymap from a full text XKB keymap passed into the
+ * file descriptor.
+ */
+_X_EXPORT extern struct xkb_desc *
+xkb_map_new_from_fd(int fd, enum xkb_keymap_format format);
+
+/**
+ * Creates an XKB keymap from a full text XKB keymap serialised into one
+ * enormous string.
+ */
+_X_EXPORT extern struct xkb_desc *
+xkb_map_new_from_string(const char *string, enum xkb_keymap_format format);
+
+/**
+ * Takes a new reference on a keymap.
+ */
+_X_EXPORT extern void
+xkb_map_ref(struct xkb_desc *xkb);
+
+/**
+ * Releases a reference on a keymap.
+ */
+_X_EXPORT extern void
+xkb_map_unref(struct xkb_desc *xkb);
+
+/** @} */
+
+/**
* @defgroup components XKB state components
* Allows enumeration of state components such as modifiers and groups within
* the current keymap.
struct xkb_desc *xkb;
xkb = _XkbTypedCalloc(1, struct xkb_desc);
- if (xkb)
+ if (xkb) {
xkb->device_spec = XkbUseCoreKbd;
+ xkb->refcnt = 1;
+ }
+
return xkb;
}
xkb_state_new(struct xkb_desc *xkb)
{
struct xkb_state *ret;
+
if (!xkb)
return NULL;
ret->refcnt = 1;
ret->xkb = xkb;
+ xkb_map_ref(xkb);
+
return ret;
}
assert(state->refcnt >= 0);
if (state->refcnt == 0)
return;
+
+ xkb_map_unref(state->xkb);
free(state);
}
err:
ACTION("Failed to compile keymap\n");
if (xkb)
- xkb_free_keymap(xkb);
+ xkb_map_unref(xkb);
return NULL;
}
}
struct xkb_desc *
-xkb_compile_keymap_from_rules(const struct xkb_rule_names *rmlvo)
+xkb_map_new_from_names(const struct xkb_rule_names *rmlvo)
{
XkbRF_VarDefsRec defs;
struct xkb_component_names * names;
return NULL;
}
- xkb = xkb_compile_keymap_from_components(names);
+ xkb = xkb_map_new_from_kccgst(names);
free(names->keymap);
free(names->keycodes);
}
static struct xkb_desc *
-compile_keymap(XkbFile *file, const char *mapName)
+compile_keymap(XkbFile *file)
{
XkbFile *mapToUse;
struct xkb_desc * xkb = NULL;
/* Find map to use */
- mapToUse = XkbChooseMap(file, mapName);
+ mapToUse = XkbChooseMap(file, NULL);
if (!mapToUse)
goto err;
FreeXKBFile(file);
free(scanFile);
XkbFreeIncludePath();
+ XkbcFreeAllAtoms();
return xkb;
}
struct xkb_desc *
-xkb_compile_keymap_from_components(const struct xkb_component_names * ktcsg)
+xkb_map_new_from_kccgst(const struct xkb_component_names *kccgst)
{
XkbFile *file;
- if (!ktcsg) {
+ if (!kccgst) {
ERROR("no components specified\n");
return NULL;
}
- if (ISEMPTY(ktcsg->keycodes)) {
+ if (ISEMPTY(kccgst->keycodes)) {
ERROR("keycodes required to generate XKB keymap\n");
return NULL;
}
- if (ISEMPTY(ktcsg->compat)) {
+ if (ISEMPTY(kccgst->compat)) {
ERROR("compat map required to generate XKB keymap\n");
return NULL;
}
- if (ISEMPTY(ktcsg->types)) {
+ if (ISEMPTY(kccgst->types)) {
ERROR("types required to generate XKB keymap\n");
return NULL;
}
- if (ISEMPTY(ktcsg->symbols)) {
+ if (ISEMPTY(kccgst->symbols)) {
ERROR("symbols required to generate XKB keymap\n");
return NULL;
}
- if (!(file = XkbKeymapFileFromComponents(ktcsg))) {
+ if (!(file = XkbKeymapFileFromComponents(kccgst))) {
ERROR("failed to generate parsed XKB file from components\n");
return NULL;
}
- return compile_keymap(file, NULL);
+ return compile_keymap(file);
}
struct xkb_desc *
-xkb_compile_keymap_from_string(const char *string, const char *mapName)
+xkb_map_new_from_string(const char *string, enum xkb_keymap_format format)
{
XkbFile *file;
+ if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
+ ERROR("unsupported keymap format %d\n", format);
+ return NULL;
+ }
+
if (!string) {
ERROR("no string specified to generate XKB keymap\n");
return NULL;
return NULL;
}
- return compile_keymap(file, mapName);
+ return compile_keymap(file);
}
struct xkb_desc *
-xkb_compile_keymap_from_file(FILE *inputFile, const char *mapName)
+xkb_map_new_from_fd(int fd, enum xkb_keymap_format format)
{
XkbFile *file;
+ FILE *fptr;
- if (!inputFile) {
+ if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
+ ERROR("unsupported keymap format %d\n", format);
+ return NULL;
+ }
+
+ if (fd < 0) {
ERROR("no file specified to generate XKB keymap\n");
return NULL;
}
+ fptr = fdopen(fd, "r");
+ if (!fptr) {
+ ERROR("couldn't associate fd with file pointer\n");
+ return NULL;
+ }
+
setScanState("input", 1);
- if (!XKBParseFile(inputFile, &file) || !file) {
+ if (!XKBParseFile(fptr, &file) || !file) {
ERROR("failed to parse input xkb file\n");
return NULL;
}
- return compile_keymap(file, mapName);
+ return compile_keymap(file);
+}
+
+void
+xkb_map_ref(struct xkb_desc *xkb)
+{
+ xkb->refcnt++;
}
void
-xkb_free_keymap(struct xkb_desc *xkb)
+xkb_map_unref(struct xkb_desc *xkb)
{
+ if (--xkb->refcnt > 0)
+ return;
+
XkbcFreeKeyboard(xkb);
- XkbcFreeAllAtoms();
}
int main(int argc, char *argv[])
{
- char *path, *name;
- FILE *file;
+ char *path;
+ int fd;
struct xkb_desc * xkb;
int i, len, from_string = 0;
/* Require xkb file */
if (argc < 2) {
fprintf(stderr, "Not enough arguments\n");
- fprintf(stderr, "Usage: %s [-s] XKBFILE [NAME]\n",
+ fprintf(stderr, "Usage: %s [-s] XKBFILE\n",
argv[0]);
exit(1);
}
}
path = argv[i];
- name = (argc > i + 1) ? argv[i + 1] : NULL;
- file = fopen(path, "r");
- if (!file) {
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
fprintf(stderr, "Failed to open file \"%s\": %s\n", path,
strerror(errno));
exit(1);
}
if (from_string) {
- len = fread(buffer, 1, sizeof buffer, file);
+ len = read(fd, buffer, sizeof(buffer));
buffer[len] = '\0';
- xkb = xkb_compile_keymap_from_string(buffer, name);
+ xkb = xkb_map_new_from_string(buffer, XKB_KEYMAP_FORMAT_TEXT_V1);
} else {
- xkb = xkb_compile_keymap_from_file(file, name);
+ xkb = xkb_map_new_from_fd(fd, XKB_KEYMAP_FORMAT_TEXT_V1);
}
- fclose(file);
+ close(fd);
if (!xkb) {
fprintf(stderr, "Failed to compile keymap\n");
exit(1);
}
- xkb_free_keymap(xkb);
+ xkb_map_unref(xkb);
return 0;
}
rm -f "$log"
compile $srcdir/basic.xkb
-compile $srcdir/named.xkb
-compile $srcdir/named.xkb de
-compile $srcdir/named.xkb us
+# XXX check we actually get qwertz here ...
compile $srcdir/default.xkb
compile $srcdir/comprehensive-plus-geom.xkb
-
-failcompile $srcdir/basic.xkb foo
-failcompile $srcdir/named.xkb foo
failcompile $srcdir/bad.xkb
+++ /dev/null
-default xkb_keymap "us" {
- xkb_keycodes { include "xfree86+aliases(qwerty)" };
- xkb_types { include "complete" };
- xkb_compat { include "complete" };
- xkb_symbols { include "pc+us" };
- xkb_geometry { include "pc(pc105)" };
-};
-
-xkb_keymap "de" {
- xkb_keycodes { include "xfree86+aliases(qwertz)" };
- xkb_types { include "complete" };
- xkb_compat { include "complete" };
- xkb_symbols { include "pc+de" };
- xkb_geometry { include "pc(pc105)" };
-};
int main(int argc, char *argv[])
{
- struct xkb_component_names ktcsg;
- struct xkb_desc * xkb;
+ struct xkb_component_names kccgst;
+ struct xkb_desc *xkb;
/* Require Kc + T + C + S */
if (argc < 5) {
exit(1);
}
- ktcsg.keymap = NULL;
- ktcsg.keycodes = argv[1];
- ktcsg.types = argv[2];
- ktcsg.compat = argv[3];
- ktcsg.symbols = argv[4];
+ kccgst.keymap = NULL;
+ kccgst.keycodes = argv[1];
+ kccgst.types = argv[2];
+ kccgst.compat = argv[3];
+ kccgst.symbols = argv[4];
- xkb = xkb_compile_keymap_from_components(&ktcsg);
+ xkb = xkb_map_new_from_kccgst(&kccgst);
if (!xkb) {
fprintf(stderr, "Failed to compile keymap\n");
exit(1);
}
- xkb_free_keymap(xkb);
+ xkb_map_unref(xkb);
return 0;
}
int main(int argc, char *argv[])
{
struct xkb_rule_names rmlvo;
- struct xkb_desc * xkb;
+ struct xkb_desc *xkb;
/* Require rmlvo */
if (argc < 6) {
rmlvo.variant = argv[4];
rmlvo.options = argv[5];
- xkb = xkb_compile_keymap_from_rules(&rmlvo);
+ xkb = xkb_map_new_from_names(&rmlvo);
if (!xkb) {
fprintf(stderr, "Failed to compile keymap\n");
exit(1);
}
- xkb_free_keymap(xkb);
+ xkb_map_unref(xkb);
return 0;
}
rmlvo.variant = NULL;
rmlvo.options = NULL;
- xkb = xkb_compile_keymap_from_rules(&rmlvo);
+ xkb = xkb_map_new_from_names(&rmlvo);
if (!xkb) {
fprintf(stderr, "Failed to compile keymap\n");
assert(num_syms == 1 && syms[0] == XK_q);
xkb_state_unref(state);
- xkb_free_keymap(xkb);
+ xkb_map_unref(xkb);
return 0;
}