Add /etc/xkb as extra lookup path for system data files This completes the usual triplet of configuration locations available for most processes: - vendor-provided data files in /usr/share/X11/xkb - system-specific data files in /etc/xkb - user-specific data files in $XDG_CONFIG_HOME/xkb The default lookup order user, system, vendor, just like everything else that uses these conventions. For include directives in rules files, the '%E' resolves to that path. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
diff --git a/doc/rules-format.md b/doc/rules-format.md
index 96acbbf..f9fe0d9 100644
--- a/doc/rules-format.md
+++ b/doc/rules-format.md
@@ -73,6 +73,9 @@ Notes:
%H:
The value of the HOME environment variable.
+ %E:
+ The extra lookup path for system-wide XKB data (usually /etc/xkb/rules).
+
%S:
The system-installed rules directory (usually /usr/share/X11/xkb/rules).
```
diff --git a/doc/user-configuration.md b/doc/user-configuration.md
index 17e7179..b8c4d30 100644
--- a/doc/user-configuration.md
+++ b/doc/user-configuration.md
@@ -11,6 +11,8 @@ libxkbcommon searches the following paths for XKB configuration files:
- `$XDG_CONFIG_HOME/xkb/`, or `$HOME/.config/xkb/` if the `$XDG_CONFIG_HOME`
environment variable is not defined
- `$HOME/.xkb/`
+- `$XKB_CONFIG_EXTRA_PATH` if set, otherswise `<sysconfdir>/xkb` (on most
+ distributions this is `/etc/xkb`)
- `$XKB_CONFIG_ROOT` if set, otherwise `<datadir>/X11/xkb/` (path defined by the
`xkeyboard-config` package, on most distributions this is
`/usr/share/X11/xkb`)
diff --git a/meson.build b/meson.build
index e7d75aa..c08b40b 100644
--- a/meson.build
+++ b/meson.build
@@ -47,6 +47,10 @@ if XKBCONFIGROOT == ''
endif
endif
+XKBCONFIGEXTRAPATH = get_option('xkb-config-extra-path')
+if XKBCONFIGEXTRAPATH == ''
+ XKBCONFIGEXTRAPATH = join_paths(get_option('prefix'), get_option('sysconfdir'), 'xkb')
+endif
# The X locale directory for compose.
XLOCALEDIR = get_option('x-locale-root')
@@ -70,6 +74,7 @@ endif
configh_data.set(system_extensions, 1)
system_ext_define = '#define ' + system_extensions
configh_data.set_quoted('DFLT_XKB_CONFIG_ROOT', XKBCONFIGROOT)
+configh_data.set_quoted('DFLT_XKB_CONFIG_EXTRA_PATH', XKBCONFIGEXTRAPATH)
configh_data.set_quoted('XLOCALEDIR', XLOCALEDIR)
configh_data.set_quoted('DEFAULT_XKB_RULES', get_option('default-rules'))
configh_data.set_quoted('DEFAULT_XKB_MODEL', get_option('default-model'))
diff --git a/meson_options.txt b/meson_options.txt
index 5eaa081..04982c6 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -4,6 +4,11 @@ option(
description: 'The XKB config root [default=xkeyboard-config install path]',
)
option(
+ 'xkb-config-extra-path',
+ type: 'string',
+ description: 'Extra lookup path for system-wide XKB data [default=$sysconfdir/xkb]',
+)
+option(
'x-locale-root',
type: 'string',
description: 'The X locale root [default=$datadir/X11/locale]',
diff --git a/src/context.c b/src/context.c
index ef9b774..2abaa9b 100644
--- a/src/context.c
+++ b/src/context.c
@@ -84,6 +84,13 @@ err:
}
const char *
+xkb_context_include_path_get_extra_path(struct xkb_context *ctx)
+{
+ const char *extra = secure_getenv("XKB_CONFIG_EXTRA_PATH");
+ return extra ? extra : DFLT_XKB_CONFIG_EXTRA_PATH;
+}
+
+const char *
xkb_context_include_path_get_system_path(struct xkb_context *ctx)
{
const char *root = secure_getenv("XKB_CONFIG_ROOT");
@@ -96,7 +103,7 @@ xkb_context_include_path_get_system_path(struct xkb_context *ctx)
XKB_EXPORT int
xkb_context_include_path_append_default(struct xkb_context *ctx)
{
- const char *home, *xdg, *root;
+ const char *home, *xdg, *root, *extra;
char *user_path;
int ret = 0;
@@ -126,6 +133,8 @@ xkb_context_include_path_append_default(struct xkb_context *ctx)
}
}
+ extra = xkb_context_include_path_get_extra_path(ctx);
+ ret |= xkb_context_include_path_append(ctx, extra);
root = xkb_context_include_path_get_system_path(ctx);
ret |= xkb_context_include_path_append(ctx, root);
diff --git a/src/context.h b/src/context.h
index 9584dbc..ead2508 100644
--- a/src/context.h
+++ b/src/context.h
@@ -60,6 +60,9 @@ xkb_context_failed_include_path_get(struct xkb_context *ctx,
unsigned int idx);
const char *
+xkb_context_include_path_get_extra_path(struct xkb_context *ctx);
+
+const char *
xkb_context_include_path_get_system_path(struct xkb_context *ctx);
/*
diff --git a/src/registry.c b/src/registry.c
index 956d850..d3d95f5 100644
--- a/src/registry.c
+++ b/src/registry.c
@@ -583,7 +583,7 @@ err:
XKB_EXPORT bool
rxkb_context_include_path_append_default(struct rxkb_context *ctx)
{
- const char *home, *xdg, *root;
+ const char *home, *xdg, *root, *extra;
char *user_path;
bool ret = false;
@@ -618,6 +618,12 @@ rxkb_context_include_path_append_default(struct rxkb_context *ctx)
}
}
+ extra = secure_getenv("XKB_CONFIG_EXTRA_PATH");
+ if (extra != NULL)
+ ret |= rxkb_context_include_path_append(ctx, extra);
+ else
+ ret |= rxkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_EXTRA_PATH);
+
root = secure_getenv("XKB_CONFIG_ROOT");
if (root != NULL)
ret |= rxkb_context_include_path_append(ctx, root);
diff --git a/src/xkbcomp/rules.c b/src/xkbcomp/rules.c
index 3359552..099500a 100644
--- a/src/xkbcomp/rules.c
+++ b/src/xkbcomp/rules.c
@@ -399,6 +399,13 @@ matcher_include(struct matcher *m, struct scanner *parent_scanner,
return;
}
}
+ else if (chr(&s, 'E')) {
+ const char *default_root = xkb_context_include_path_get_extra_path(m->ctx);
+ if (!buf_appends(&s, default_root) || !buf_appends(&s, "/rules")) {
+ scanner_err(&s, "include path after expanding %%E is too long");
+ return;
+ }
+ }
else {
scanner_err(&s, "unknown %% format (%c) in include statement", peek(&s));
return;
diff --git a/test/tool-option-parsing.py b/test/tool-option-parsing.py
index c503176..de638d1 100755
--- a/test/tool-option-parsing.py
+++ b/test/tool-option-parsing.py
@@ -306,5 +306,7 @@ if __name__ == '__main__':
# to override it with a known (empty) directory. Otherwise our test
# behavior depends on the system the test is run on.
os.environ['XDG_CONFIG_HOME'] = tmpdir
+ # This needs to be separated if we do specific extra path testing
+ os.environ['XKB_CONFIG_EXTRA_PATH'] = tmpdir
sys.exit(pytest.main(args=[__file__]))
diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h
index c091e5d..5fabc34 100644
--- a/xkbcommon/xkbcommon.h
+++ b/xkbcommon/xkbcommon.h
@@ -553,7 +553,7 @@ xkb_keysym_to_lower(xkb_keysym_t ks);
*
* The user may set some environment variables which affect the library:
*
- * - `XKB_CONFIG_ROOT`, `XDG_CONFIG_DIR`, `HOME` - see @ref include-path.
+ * - `XKB_CONFIG_ROOT`, `XKB_EXTRA_PATH`, `XDG_CONFIG_DIR`, `HOME` - see @ref include-path.
* - `XKB_LOG_LEVEL` - see xkb_context_set_log_level().
* - `XKB_LOG_VERBOSITY` - see xkb_context_set_log_verbosity().
* - `XKB_DEFAULT_RULES`, `XKB_DEFAULT_MODEL`, `XKB_DEFAULT_LAYOUT`,
@@ -644,6 +644,9 @@ xkb_context_get_user_data(struct xkb_context *context);
* fallback to `$HOME/.config/` if unset.
* - The path `$HOME/.xkb`, where $HOME is the value of the environment
* variable `HOME`.
+ * - The `XKB_EXTRA_PATH` environment variable, if defined, otherwise the
+ * system configuration directory, defined at library configuration time
+ * (usually `/etc/xkb`).
* - The `XKB_CONFIG_ROOT` environment variable, if defined, otherwise
* the system XKB root, defined at library configuration time.
*