From 8b4ff2af45cba7d81a25e8c3941a9ca21e8133f4 Mon Sep 17 00:00:00 2001
From: Ingo Ruhnke <grumbel@gmx.de>
Date: Sun, 30 Jan 2011 03:20:29 +0100
Subject: [PATCH] Added --no-extra-events option

---
 TODO                         | 13 +++++-------
 doc/xboxdrv.xml              | 37 ++++++++++++++++++++++++++++++++---
 src/command_line_options.cpp |  7 +++++++
 src/options.cpp              |  1 +
 src/options.hpp              |  1 +
 src/uinput.cpp               | 38 ++++++++++++++++++++++--------------
 src/uinput.hpp               |  3 ++-
 src/xboxdrv.cpp              |  2 +-
 src/xboxdrv_daemon.cpp       |  2 +-
 9 files changed, 75 insertions(+), 29 deletions(-)

diff --git a/TODO b/TODO
index 9966656..8507a60 100644
--- a/TODO
+++ b/TODO
@@ -42,14 +42,6 @@ $ dput my-ppa ../xboxdrv_0.7.1-1~lucid1_source.changes
 Stuff to do before 0.7.1 release:
 =================================
 
-* -trigger=trigger is broken
-
-* remove uinput.send_rel_repetitive() replace with just EventHandler::update()
-
-* mapping trigger=REL_WHEEL:5:100 doesn't work
-
-* make dummy joystick axis, mouse button creation optional
-
 * --ui-axismap LT=KEY_A:KEY_B:1 
 
 Here KEY_B is the key you want to send and KEY_A is a random other key
@@ -63,6 +55,9 @@ disable LT and RT
   [xboxdrv]
   ui-buttonmap = A=BTN_A,B=BTN_B,...
 
+  - in general cleanup config handling, turn almost everything into
+    proper functions and use the same functions for both cmdline and ini
+
 * how exactly does daemon interact with wireless pads?! allow --wid --id for daemon
 
 * fix device name of mimic_xpad
@@ -128,6 +123,8 @@ disable LT and RT
 Stuff to do before 0.7.2 release:
 =================================
 
+* remove uinput.send_rel_repetitive() replace with just EventHandler::update()
+
 * add --device-usbid TYPE.SLOT=VENDOR:PRODUCT:VERSION
 
 * allow multiple controllers in non-daemon mode
diff --git a/doc/xboxdrv.xml b/doc/xboxdrv.xml
index 25c47a5..bc33440 100644
--- a/doc/xboxdrv.xml
+++ b/doc/xboxdrv.xml
@@ -1449,13 +1449,44 @@ pos = (1.0f - (1.0f - pos) ** t) ** (1 / t);]]></programlisting>
               and sort events to each of them. Thus mouse related
               events like BTN_LEFT or REL_X will go to a virtual mouse
               device, while ABS_X events would go to a virtual
-              joystick device. This option disables that automatism
-              and all events will go to the same virtual device.
-              Manual assignment to a specific device is still possible.
+              joystick device and KEY_ESC would go to a virtual
+              keyboard device.
+            </para>
+            <para>
+              This option disables that automatism and all events will
+              go to the same virtual device.
+            </para>
+            <para>
+              Manual assignment to a specific device (i.e.
+              KEY_ESC@keyboard, BTN_A@joystick, ...) is still possible.
             </para>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><option>--no-extra-events</option></term>
+          <listitem>
+            <para>
+              By default xboxdrv will allocate multiple uinput devices
+              and sort events to each of them. Thus mouse related
+              events like BTN_LEFT or REL_X will go to a virtual mouse
+              device, while ABS_X events would go to a virtual
+              joystick device and KEY_ESC would go to a virtual
+              keyboard device.
+            </para>
+            <para>
+              To make sure sure that a mouse, keyboard or joystick
+              device is properly detected by Xorg, the kernel or
+              libraries such SDL xboxdrv will insert extra dummy
+              events. For example a mouse device needs REL_X and REL_Y
+              events to be detected as such, but a configuration that
+              only wants to emulate the mouse buttons won't provide
+              those, thus xboxdrv will add them automatically.
+              The <option>--no-extra-events</option> option will
+              switch this behaviour off.
+            </para>
+          </listitem>
+
         <varlistentry>
           <term><option>--name NAME</option></term>
           <listitem>
diff --git a/src/command_line_options.cpp b/src/command_line_options.cpp
index 3e5af8b..3f251f8 100644
--- a/src/command_line_options.cpp
+++ b/src/command_line_options.cpp
@@ -56,6 +56,7 @@ enum {
   OPTION_NO_UINPUT,
   OPTION_MIMIC_XPAD,
   OPTION_NO_EXTRA_DEVICES,
+  OPTION_NO_EXTRA_EVENTS,
   OPTION_TYPE,
   OPTION_FORCE_FEEDBACK,
   OPTION_RUMBLE_GAIN,
@@ -269,6 +270,7 @@ CommandLineParser::init_argp()
     .add_text("Uinput Configuration Options: ")
     .add_option(OPTION_NO_UINPUT,          0, "no-uinput",   "", "do not try to start uinput event dispatching")
     .add_option(OPTION_NO_EXTRA_DEVICES,   0, "no-extra-devices",  "", "Do not create separate virtual keyboard and mouse devices, just use a single virtual device")
+    .add_option(OPTION_NO_EXTRA_EVENTS,    0, "no-extra-events",  "", "Do not create dummy events to facilitate device type detection")
     .add_option(OPTION_NAME,               0, "name",            "NAME", "Changes the name prefix used for devices in the current slot")
     .add_option(OPTION_DEVICE_NAME,        0, "device-name",     "DEVID=NAME", "Changes the descriptive name the given device")
     .add_option(OPTION_UI_CLEAR,           0, "ui-clear",         "",     "Removes all existing uinput bindings")
@@ -336,6 +338,7 @@ CommandLineParser::init_ini(Options* opts)
     ("next", boost::bind(&Options::next_config, boost::ref(opts)), boost::function<void ()>())
     ("next-controller", boost::bind(&Options::next_controller, boost::ref(opts)), boost::function<void ()>())
     ("extra-devices", &opts->extra_devices)
+    ("extra-events", &opts->extra_events)
 
     ("deadzone", boost::bind(&CommandLineParser::set_deadzone, this, _1))
     ("deadzone-trigger", boost::bind(&CommandLineParser::set_deadzone_trigger, this, _1))
@@ -741,6 +744,10 @@ CommandLineParser::parse_args(int argc, char** argv, Options* options)
       case OPTION_NO_EXTRA_DEVICES:
         opts.extra_devices = false;
         break;
+
+      case OPTION_NO_EXTRA_EVENTS:
+        opts.extra_events = false;
+        break;
             
       case OPTION_DPAD_ONLY:
         opts.set_dpad_only();
diff --git a/src/options.cpp b/src/options.cpp
index fd96ba8..ef3c5c4 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -69,6 +69,7 @@ Options::Options() :
   controller_slot(0),
   config_slot(0),
   extra_devices(true),
+  extra_events(true),
   uinput_device_names(),
   usb_debug(false)
 {
diff --git a/src/options.hpp b/src/options.hpp
index 0d6ca19..180021d 100644
--- a/src/options.hpp
+++ b/src/options.hpp
@@ -114,6 +114,7 @@ public:
   int config_slot;
 
   bool extra_devices;
+  bool extra_events;
 
   std::map<uint32_t, std::string> uinput_device_names;
 
diff --git a/src/uinput.cpp b/src/uinput.cpp
index a8c2772..bd2bc73 100644
--- a/src/uinput.cpp
+++ b/src/uinput.cpp
@@ -22,11 +22,12 @@
 
 #include "log.hpp"
 
-UInput::UInput() :
+UInput::UInput(bool extra_events) :
   m_uinput_devs(),
   m_device_names(),
   m_rel_repeat_lst(),
-  m_mutex()
+  m_mutex(),
+  m_extra_events(extra_events)
 {
 }
 
@@ -144,23 +145,30 @@ UInput::create_uinput_device(uint32_t device_id)
     log_debug("create device: " << device_id);
     LinuxUinput::DeviceType device_type;
 
-    switch (device_id)
+    if (!m_extra_events)
     {
-      case DEVICEID_JOYSTICK:
-        device_type = LinuxUinput::kJoystickDevice;
-        break;
+      device_type = LinuxUinput::kGenericDevice;
+    }
+    else
+    {
+      switch (device_id)
+      {
+        case DEVICEID_JOYSTICK:
+          device_type = LinuxUinput::kJoystickDevice;
+          break;
 
-      case DEVICEID_MOUSE:
-        device_type = LinuxUinput::kMouseDevice;
-        break;
+        case DEVICEID_MOUSE:
+          device_type = LinuxUinput::kMouseDevice;
+          break;
       
-      case DEVICEID_KEYBOARD:
-        device_type = LinuxUinput::kKeyboardDevice;
-        break;
+        case DEVICEID_KEYBOARD:
+          device_type = LinuxUinput::kKeyboardDevice;
+          break;
 
-      default:
-        device_type = LinuxUinput::kGenericDevice;
-        break;
+        default:
+          device_type = LinuxUinput::kGenericDevice;
+          break;
+      }
     }
 
     std::string dev_name = get_device_name(device_id);
diff --git a/src/uinput.hpp b/src/uinput.hpp
index 4eb58bb..7b78685 100644
--- a/src/uinput.hpp
+++ b/src/uinput.hpp
@@ -64,9 +64,10 @@ private:
   std::map<UIEvent, RelRepeat> m_rel_repeat_lst;
 
   boost::mutex m_mutex;
+  bool m_extra_events;
 
 public:
-  UInput();
+  UInput(bool extra_events);
   ~UInput();
 
   void update(int msec_delta);
diff --git a/src/xboxdrv.cpp b/src/xboxdrv.cpp
index c590d63..066a351 100644
--- a/src/xboxdrv.cpp
+++ b/src/xboxdrv.cpp
@@ -447,7 +447,7 @@ Xboxdrv::run_main(const Options& opts)
     {
       if (!opts.quiet)
         std::cout << "Starting with uinput" << std::endl;
-      uinput = std::auto_ptr<UInput>(new UInput());
+      uinput = std::auto_ptr<UInput>(new UInput(opts.extra_events));
       uinput->set_device_names(opts.uinput_device_names);
     }
     else
diff --git a/src/xboxdrv_daemon.cpp b/src/xboxdrv_daemon.cpp
index 51e21e8..c835eb1 100644
--- a/src/xboxdrv_daemon.cpp
+++ b/src/xboxdrv_daemon.cpp
@@ -205,7 +205,7 @@ XboxdrvDaemon::init_uinput(const Options& opts)
   {
     log_info("starting with UInput");
 
-    m_uinput.reset(new UInput());
+    m_uinput.reset(new UInput(opts.extra_events));
     m_uinput->set_device_names(opts.uinput_device_names);
 
     // create controller slots