aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86/common/xf86Xinput.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xfree86/common/xf86Xinput.c')
-rw-r--r--xorg-server/hw/xfree86/common/xf86Xinput.c119
1 files changed, 107 insertions, 12 deletions
diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c
index f637cfe19..57db056d8 100644
--- a/xorg-server/hw/xfree86/common/xf86Xinput.c
+++ b/xorg-server/hw/xfree86/common/xf86Xinput.c
@@ -57,9 +57,11 @@
#include <X11/Xatom.h>
#include "xf86.h"
#include "xf86Priv.h"
+#include "xf86Config.h"
#include "xf86Xinput.h"
#include "XIstubs.h"
#include "xf86Optrec.h"
+#include "xf86Parser.h"
#include "mipointer.h"
#include "xf86InPriv.h"
#include "compiler.h"
@@ -74,6 +76,11 @@
#include "exglobals.h"
#include "eventstr.h"
+#include <string.h> /* InputClassMatches */
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+
#include "extnsionst.h"
#include "windowstr.h" /* screenIsSaved */
@@ -466,6 +473,85 @@ AddOtherInputDevices(void)
{
}
+/*
+ * Classes without any Match statements match all devices. Otherwise, all
+ * statements must match.
+ */
+static Bool
+InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
+{
+ if (iclass->match_product &&
+ (!attrs->product || !strstr(attrs->product, iclass->match_product)))
+ return False;
+ if (iclass->match_vendor &&
+ (!attrs->vendor || !strstr(attrs->vendor, iclass->match_vendor)))
+ return False;
+ if (iclass->match_device &&
+#ifdef HAVE_FNMATCH_H
+ (!attrs->device ||
+ fnmatch(iclass->match_device, attrs->device, 0) != 0))
+#else
+ (!attrs->device || !strstr(attrs->device, iclass->match_device)))
+#endif
+ return False;
+ if (iclass->is_keyboard.set &&
+ iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
+ return False;
+ if (iclass->is_pointer.set &&
+ iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER))
+ return False;
+ if (iclass->is_joystick.set &&
+ iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK))
+ return False;
+ if (iclass->is_tablet.set &&
+ iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET))
+ return False;
+ if (iclass->is_touchpad.set &&
+ iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD))
+ return False;
+ if (iclass->is_touchscreen.set &&
+ iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN))
+ return False;
+ return True;
+}
+
+/*
+ * Merge in any InputClass configurations. Each InputClass section can
+ * add to the original device configuration as well as any previous
+ * InputClass sections.
+ */
+static int
+MergeInputClasses(IDevPtr idev, InputAttributes *attrs)
+{
+ XF86ConfInputClassPtr cl;
+ XF86OptionPtr classopts;
+
+ for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
+ if (!InputClassMatches(cl, attrs))
+ continue;
+
+ xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n",
+ idev->identifier, cl->identifier);
+ if (cl->driver && !idev->driver) {
+ idev->driver = xstrdup(cl->driver);
+ if (!idev->driver) {
+ xf86Msg(X_ERROR, "Could not allocate memory while merging "
+ "InputClass configuration");
+ return BadAlloc;
+ }
+ }
+
+ classopts = xf86optionListDup(cl->option_lst);
+ if (idev->commonOptions)
+ idev->commonOptions = xf86optionListMerge(classopts,
+ idev->commonOptions);
+ else
+ idev->commonOptions = classopts;
+ }
+
+ return Success;
+}
+
/**
* Create a new input device, activate and enable it.
*
@@ -568,7 +654,8 @@ unwind:
}
int
-NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
+NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
+ DeviceIntPtr *pdev)
{
IDevRec *idev = NULL;
InputOption *option = NULL;
@@ -605,9 +692,9 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
}
}
- /* Right now, the only automatic config we know of is HAL. */
if (strcmp(option->key, "_source") == 0 &&
- strcmp(option->value, "server/hal") == 0) {
+ (strcmp(option->value, "server/hal") == 0 ||
+ strcmp(option->value, "server/udev") == 0)) {
is_auto = 1;
if (!xf86Info.autoAddDevices) {
rval = BadMatch;
@@ -615,6 +702,23 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
}
}
}
+
+ for (option = options; option; option = option->next) {
+ /* Steal option key/value strings from the provided list.
+ * We need those strings, the InputOption list doesn't. */
+ idev->commonOptions = xf86addNewOption(idev->commonOptions,
+ option->key, option->value);
+ option->key = NULL;
+ option->value = NULL;
+ }
+
+ /* Apply InputClass settings */
+ if (attrs) {
+ rval = MergeInputClasses(idev, attrs);
+ if (rval != Success)
+ goto unwind;
+ }
+
if (!idev->driver || !idev->identifier) {
xf86Msg(X_ERROR, "No input driver/identifier specified (ignoring)\n");
rval = BadRequest;
@@ -626,15 +730,6 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
return BadMatch;
}
- for (option = options; option; option = option->next) {
- /* Steal option key/value strings from the provided list.
- * We need those strings, the InputOption list doesn't. */
- idev->commonOptions = xf86addNewOption(idev->commonOptions,
- option->key, option->value);
- option->key = NULL;
- option->value = NULL;
- }
-
rval = xf86NewInputDevice(idev, pdev,
(!is_auto || (is_auto && xf86Info.autoEnableDevices)));
if (rval == Success)