Add tag matching to input attributes.

Tags may be a list of comma-separated strings that match against a MatchTag
InputClass section. If any of the tags specified for a device match against
the MatchTag of the section, this match is evaluated true and passed on to
the next match condition.

Tags are specified as "input.tags" (hal) or "ID_INPUT.tags" (udev), the
value of the tags is case-sensitive and require an exact match (not a
substring match).

i.e. "quirk" will not match "QUIRK", "need_quirk" or "quirk_needed".

Example configuration:
udev:
    ENV{ID_INPUT.tags}="foo,bar"

hal:
    <merge key="input.tags" type="string">foo,bar</merge>

xorg.conf:
    Section "InputClass"
            Identifier "foobar quirks"
            MatchTag "foo|foobar"
            Option "Foobar" "on"
    EndSection

Where the xorg.conf section matches against any device with the tag "foo"
or tag "foobar" set.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Dan Nicholson <dbn.lists@gmail.com>
Reviewed-by: Dan Nicholson <dbn.lists@gmail.com>
This commit is contained in:
Peter Hutterer 2010-02-10 15:36:50 +10:00
parent 3ac43df5d4
commit c6d9bc092c
8 changed files with 68 additions and 0 deletions

View File

@ -164,6 +164,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
attrs.product = xstrdup(name); attrs.product = xstrdup(name);
attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor"); attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor");
attrs.tags = xstrtokenize(get_prop_string(hal_ctx, udi, "input.tags"), ",");
if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL)) if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL))
attrs.flags |= ATTR_KEYBOARD; attrs.flags |= ATTR_KEYBOARD;
@ -391,6 +392,14 @@ unwind:
xfree(attrs.product); xfree(attrs.product);
xfree(attrs.vendor); xfree(attrs.vendor);
xfree(attrs.device); xfree(attrs.device);
if (attrs.tags) {
char **tag = attrs.tags;
while (*tag) {
xfree(*tag);
tag++;
}
xfree(attrs.tags);
}
if (xkb_opts.layout) if (xkb_opts.layout)
xfree(xkb_opts.layout); xfree(xkb_opts.layout);

View File

@ -84,6 +84,7 @@ device_added(struct udev_device *udev_device)
add_option(&options, "path", path); add_option(&options, "path", path);
add_option(&options, "device", path); add_option(&options, "device", path);
attrs.device = path; attrs.device = path;
attrs.tags = xstrtokenize(udev_device_get_property_value(udev_device, "ID_INPUT.tags"), ",");
config_info = Xprintf("udev:%s", syspath); config_info = Xprintf("udev:%s", syspath);
if (!config_info) if (!config_info)
@ -150,6 +151,15 @@ device_added(struct udev_device *udev_device)
xfree(tmpo); xfree(tmpo);
} }
if (attrs.tags) {
char **tag = attrs.tags;
while (*tag) {
xfree(*tag);
tag++;
}
xfree(attrs.tags);
}
return; return;
} }

View File

@ -545,6 +545,24 @@ InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
if (!match) if (!match)
return FALSE; return FALSE;
} }
if (iclass->match_tag) {
if (!attrs->tags)
return FALSE;
for (cur = iclass->match_tag, match = FALSE; *cur && !match; cur++) {
const char *tag;
for(tag = *attrs->tags; *tag; tag++) {
if (!strcmp(tag, *cur)) {
match = TRUE;
break;
}
}
}
if (!match)
return FALSE;
}
if (iclass->is_keyboard.set && if (iclass->is_keyboard.set &&
iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
return FALSE; return FALSE;

View File

@ -1054,6 +1054,15 @@ This entry can be used to check if the device file matches the
pathname pattern. Multiple patterns can be matched by separating arguments pathname pattern. Multiple patterns can be matched by separating arguments
with a '|' character. with a '|' character.
.TP 7 .TP 7
.BI "MatchTag \*q" matchtag \*q
This entry can be used to check if tags assigned by the config backend
matches the
.RI \*q matchtag \*q
pattern. Multiple patterns can be matched by separating arguments
with a '|' character. A match is found if at least one of the tags given in
.RI \*q matchtag \*q
matches at least one of the tags assigned by the backend.
.TP 7
.BI "MatchIsKeyboard \*q" bool \*q .BI "MatchIsKeyboard \*q" bool \*q
.TP 7 .TP 7
.BI "MatchIsPointer \*q" bool \*q .BI "MatchIsPointer \*q" bool \*q

View File

@ -47,6 +47,7 @@ xf86ConfigSymTabRec InputClassTab[] =
{MATCH_PRODUCT, "matchproduct"}, {MATCH_PRODUCT, "matchproduct"},
{MATCH_VENDOR, "matchvendor"}, {MATCH_VENDOR, "matchvendor"},
{MATCH_DEVICE_PATH, "matchdevicepath"}, {MATCH_DEVICE_PATH, "matchdevicepath"},
{MATCH_TAG, "matchtag"},
{MATCH_IS_KEYBOARD, "matchiskeyboard"}, {MATCH_IS_KEYBOARD, "matchiskeyboard"},
{MATCH_IS_POINTER, "matchispointer"}, {MATCH_IS_POINTER, "matchispointer"},
{MATCH_IS_JOYSTICK, "matchisjoystick"}, {MATCH_IS_JOYSTICK, "matchisjoystick"},
@ -107,6 +108,11 @@ xf86parseInputClassSection(void)
Error(QUOTE_MSG, "MatchDevicePath"); Error(QUOTE_MSG, "MatchDevicePath");
ptr->match_device = xstrtokenize(val.str, TOKEN_SEP); ptr->match_device = xstrtokenize(val.str, TOKEN_SEP);
break; break;
case MATCH_TAG:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchTag");
ptr->match_tag = xstrtokenize(val.str, TOKEN_SEP);
break;
case MATCH_IS_KEYBOARD: case MATCH_IS_KEYBOARD:
if (xf86getSubToken(&(ptr->comment)) != STRING) if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchIsKeyboard"); Error(QUOTE_MSG, "MatchIsKeyboard");
@ -211,6 +217,14 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
*list); *list);
fprintf(cf, "\"\n"); fprintf(cf, "\"\n");
} }
if (ptr->match_tag) {
fprintf(cf, "\tMatchTag \"");
for (list = ptr->match_tag; *list; list++)
fprintf(cf, "%s%s",
list == ptr->match_tag ? "" : TOKEN_SEP,
*list);
fprintf(cf, "\"\n");
}
if (ptr->is_keyboard.set) if (ptr->is_keyboard.set)
fprintf(cf, "\tIsKeyboard \"%s\"\n", fprintf(cf, "\tIsKeyboard \"%s\"\n",
ptr->is_keyboard.val ? "yes" : "no"); ptr->is_keyboard.val ? "yes" : "no");
@ -259,6 +273,11 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr)
free(*list); free(*list);
free(ptr->match_device); free(ptr->match_device);
} }
if (ptr->match_tag) {
for (list = ptr->match_tag; *list; list++)
free(*list);
free(ptr->match_tag);
}
TestFree(ptr->comment); TestFree(ptr->comment);
xf86optionListFree(ptr->option_lst); xf86optionListFree(ptr->option_lst);

View File

@ -346,6 +346,7 @@ typedef struct
char **match_product; char **match_product;
char **match_vendor; char **match_vendor;
char **match_device; char **match_device;
char **match_tag;
xf86TriState is_keyboard; xf86TriState is_keyboard;
xf86TriState is_pointer; xf86TriState is_pointer;
xf86TriState is_joystick; xf86TriState is_joystick;

View File

@ -279,6 +279,7 @@ typedef enum {
MATCH_PRODUCT, MATCH_PRODUCT,
MATCH_VENDOR, MATCH_VENDOR,
MATCH_DEVICE_PATH, MATCH_DEVICE_PATH,
MATCH_TAG,
MATCH_IS_KEYBOARD, MATCH_IS_KEYBOARD,
MATCH_IS_POINTER, MATCH_IS_POINTER,
MATCH_IS_JOYSTICK, MATCH_IS_JOYSTICK,

View File

@ -215,6 +215,7 @@ typedef struct _InputAttributes {
char *product; char *product;
char *vendor; char *vendor;
char *device; char *device;
char **tags; /* null-terminated */
uint32_t flags; uint32_t flags;
} InputAttributes; } InputAttributes;