sort by location
This commit is contained in:
@@ -13,8 +13,16 @@
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FCNTL_H)
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
Preference<bool> g_bInputLinuxOrderByLocation( "InputLinuxOrderByLocation", false );
|
||||
|
||||
RString getDevice(RString inputDir, RString type)
|
||||
{
|
||||
RString result = "";
|
||||
@@ -78,13 +86,73 @@ LinuxInputManager::LinuxInputManager()
|
||||
LOG->Info("LinuxInputManager: %s seems to have no eventNN or jsNN.", dName.c_str() );
|
||||
}
|
||||
|
||||
// Sort devices for more consistent numbering.
|
||||
std::sort(m_vsPendingEventDevices.begin(), m_vsPendingEventDevices.end(), cmpDevices);
|
||||
std::sort(m_vsPendingJoystickDevices.begin(), m_vsPendingJoystickDevices.end(), cmpDevices);
|
||||
if(g_bInputLinuxOrderByLocation)
|
||||
{
|
||||
// use Presort to sort the devices by unique location (like USB port/hub number.)
|
||||
PresortPhysical(m_vsPendingEventDevices, "event");
|
||||
PresortPhysical(m_vsPendingJoystickDevices, "js");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sort devices for more consistent numbering.
|
||||
std::sort(m_vsPendingEventDevices.begin(), m_vsPendingEventDevices.end(), cmpDevices);
|
||||
std::sort(m_vsPendingJoystickDevices.begin(), m_vsPendingJoystickDevices.end(), cmpDevices);
|
||||
}
|
||||
|
||||
closedir(sysClassInput);
|
||||
}
|
||||
|
||||
|
||||
static bool presort_cmpDevices(LinuxInputSort a, LinuxInputSort b)
|
||||
{
|
||||
return a.UniqueString < b.UniqueString;
|
||||
}
|
||||
|
||||
void LinuxInputManager::PresortPhysical(std::vector<RString>& sortingArray, RString sortBy)
|
||||
{
|
||||
m_vPreSort.clear();
|
||||
|
||||
for (RString &dev : sortingArray)
|
||||
{
|
||||
LinuxInputSort entry;
|
||||
|
||||
entry.DeviceName = dev;
|
||||
entry.UniqueString = "";
|
||||
|
||||
int m_iFD = open(getDevice(dev, sortBy.c_str()).c_str(), O_RDWR);
|
||||
|
||||
if(m_iFD >= 0)
|
||||
{
|
||||
char szLocation[1024];
|
||||
|
||||
// EVIOCGPHYS can return values like "usb-0000:0d:00.3-4"
|
||||
// telling us where the device is located physically on the computer.
|
||||
if(ioctl(m_iFD, EVIOCGPHYS(sizeof(szLocation)), szLocation) != -1)
|
||||
{
|
||||
entry.UniqueString += szLocation;
|
||||
}
|
||||
|
||||
close(m_iFD);
|
||||
}
|
||||
|
||||
// in the event we didn't get a unique location from ioctl
|
||||
// default to the name so that sorting by number still works as intended.
|
||||
entry.UniqueString += entry.DeviceName;
|
||||
|
||||
m_vPreSort.push_back(entry);
|
||||
}
|
||||
|
||||
std::sort(m_vPreSort.begin(), m_vPreSort.end(), presort_cmpDevices);
|
||||
|
||||
sortingArray.clear();
|
||||
|
||||
for (LinuxInputSort &dev : m_vPreSort)
|
||||
{
|
||||
// LOG->Info("%s -> %s", dev.DeviceName.c_str(), dev.UniqueString.c_str());
|
||||
sortingArray.push_back(dev.DeviceName);
|
||||
}
|
||||
}
|
||||
|
||||
void LinuxInputManager::InitDriver(InputHandler_Linux_Event* driver)
|
||||
{
|
||||
m_EventDriver = driver;
|
||||
|
||||
@@ -10,6 +10,13 @@ class InputHandler_Linux_Event;
|
||||
// Enumerates the input devices on the system and dispatches them to
|
||||
// IH_Linux_Event and IH_Linux_Joystick as appropriate.
|
||||
|
||||
// Helper struct for keeping track of inputs.
|
||||
struct LinuxInputSort
|
||||
{
|
||||
RString DeviceName;
|
||||
RString UniqueString;
|
||||
};
|
||||
|
||||
class LinuxInputManager
|
||||
{
|
||||
public:
|
||||
@@ -18,6 +25,9 @@ public:
|
||||
void InitDriver(InputHandler_Linux_Event* drv);
|
||||
~LinuxInputManager();
|
||||
private:
|
||||
std::vector<LinuxInputSort> m_vPreSort;
|
||||
void PresortPhysical(std::vector<RString>& sortingArray, RString sortBy);
|
||||
|
||||
bool m_bEventEnabled;
|
||||
InputHandler_Linux_Event* m_EventDriver;
|
||||
std::vector<RString> m_vsPendingEventDevices;
|
||||
|
||||
Reference in New Issue
Block a user