SL-13610 [MAC] WIP List HID available devices in joystick selection
Doesn't filter the list yet, just shows full list of usb devices Selecting visible devices doesn't work yetmaster
parent
702e4c7dc1
commit
9b27b6e509
|
|
@ -44,8 +44,8 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s
|
|||
bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root, LLDir::ALL_SKINS);
|
||||
if (!success)
|
||||
{
|
||||
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
|
||||
LL_ERRS() << "Couldn't load string table " << xml_filename << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
//gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
|
||||
LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,7 +196,13 @@ public:
|
|||
|
||||
// windows only DirectInput8 for joysticks
|
||||
virtual void* getDirectInput8() { return NULL; };
|
||||
virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; };
|
||||
virtual bool getInputDevices(U32 device_type_filter,
|
||||
std::function<void(std::string&, LLSD::Binary&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
virtual S32 getRefreshRate() { return mRefreshRate; }
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <errno.h>
|
||||
#include "llopenglview-objc.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
#include "llappdelegate-objc.h"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,13 @@
|
|||
#include <CoreServices/CoreServices.h>
|
||||
#include <CoreGraphics/CGDisplayConfiguration.h>
|
||||
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <IOKit/hid/IOHIDUsageTables.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/usb/IOUSBLib.h>
|
||||
|
||||
extern BOOL gDebugWindowProc;
|
||||
BOOL gHiDPISupport = TRUE;
|
||||
|
||||
|
|
@ -212,13 +219,16 @@ bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
|
|||
|
||||
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character)
|
||||
{
|
||||
if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
|
||||
//if (mask!=MASK_NONE)
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Y');
|
||||
}
|
||||
else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Z');
|
||||
if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Y');
|
||||
}
|
||||
else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Z');
|
||||
}
|
||||
}
|
||||
|
||||
mRawKeyEvent = event;
|
||||
|
|
@ -1803,6 +1813,299 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Device and Element Interfaces
|
||||
|
||||
typedef enum HIDElementTypeMask
|
||||
{
|
||||
kHIDElementTypeInput = 1 << 1,
|
||||
kHIDElementTypeOutput = 1 << 2,
|
||||
kHIDElementTypeFeature = 1 << 3,
|
||||
kHIDElementTypeCollection = 1 << 4,
|
||||
kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature,
|
||||
kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection
|
||||
}HIDElementTypeMask;
|
||||
|
||||
struct hu_element_t
|
||||
{
|
||||
unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h
|
||||
long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage
|
||||
long usagePage; // usage page from IOUSBHIDParser.h which defines general usage
|
||||
void* cookie; // unique value( within device of specific vendorID and productID ) which identifies element, will NOT change
|
||||
long min; // reported min value possible
|
||||
long max; // reported max value possible
|
||||
long scaledMin; // reported scaled min value possible
|
||||
long scaledMax; // reported scaled max value possible
|
||||
long size; // size in bits of data return from element
|
||||
unsigned char relative; // are reports relative to last report( deltas )
|
||||
unsigned char wrapping; // does element wrap around( one value higher than max is min )
|
||||
unsigned char nonLinear; // are the values reported non-linear relative to element movement
|
||||
unsigned char preferredState; // does element have a preferred state( such as a button )
|
||||
unsigned char nullState; // does element have null state
|
||||
long units; // units value is reported in( not used very often )
|
||||
long unitExp; // exponent for units( also not used very often )
|
||||
char name[256]; // name of element( c string )
|
||||
|
||||
// runtime variables
|
||||
long initialCenter; // center value at start up
|
||||
unsigned char hasCenter; // whether or not to use center for calibration
|
||||
long minReport; // min returned value
|
||||
long maxReport; // max returned value( calibrate call )
|
||||
long userMin; // user set value to scale to( scale call )
|
||||
long userMax;
|
||||
|
||||
struct hu_element_t* pPrevious; // previous element( NULL at list head )
|
||||
struct hu_element_t* pChild; // next child( only of collections )
|
||||
struct hu_element_t* pSibling; // next sibling( for elements and collections )
|
||||
|
||||
long depth;
|
||||
};
|
||||
|
||||
struct HidDevice
|
||||
{ // interface to device, NULL = no interface
|
||||
char mProduct[256]; // name of product
|
||||
long mlocalID; // long representing location in USB( or other I/O ) chain which device is pluged into, can identify specific device on machine
|
||||
long mUsage; // usage page from IOUSBHID Parser.h which defines general usage
|
||||
long mUsagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* hu_BuildDevice( inHIDDevice )
|
||||
*
|
||||
* Purpose: given a IO device object build a flat device record including device info and all elements
|
||||
*
|
||||
* Notes: handles NULL lists properly
|
||||
*
|
||||
* Inputs: inHIDDevice - the I/O device object
|
||||
*
|
||||
* Returns: hu_device_t* - the address of the new device record
|
||||
*/
|
||||
|
||||
|
||||
static void populate_device_info( io_object_t io_obj_p, CFDictionaryRef device_dic, HidDevice* devicep )
|
||||
{
|
||||
CFMutableDictionaryRef io_properties = nil;
|
||||
io_registry_entry_t entry1;
|
||||
io_registry_entry_t entry2;
|
||||
kern_return_t rc;
|
||||
|
||||
// Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also
|
||||
// get dictionary for usb properties: step up two levels and get CF dictionary for USB properties
|
||||
// try to get parent1
|
||||
rc = IORegistryEntryGetParentEntry( io_obj_p, kIOServicePlane, &entry1 );
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
rc = IORegistryEntryGetParentEntry( entry1, kIOServicePlane, &entry2 );
|
||||
|
||||
IOObjectRelease( entry1 );
|
||||
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
rc = IORegistryEntryCreateCFProperties( entry2, &io_properties, kCFAllocatorDefault, kNilOptions );
|
||||
// either way, release parent2
|
||||
IOObjectRelease( entry2 );
|
||||
}
|
||||
}
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
// IORegistryEntryCreateCFProperties() succeeded
|
||||
if ( io_properties != nil )
|
||||
{
|
||||
CFTypeRef dict_element = 0;
|
||||
// get device info
|
||||
// try hid dictionary first, if fail then go to usb dictionary
|
||||
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR(kIOHIDProductKey) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "USB Product Name" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFStringGetCString((CFStringRef)dict_element, devicep->mProduct, 256, kCFStringEncodingUTF8);
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mProduct" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDLocationIDKey ) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "locationID" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mlocalID );
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mLocalID" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsagePageKey ) );
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsagePage );
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mUsagePage" << LL_ENDL;
|
||||
}
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsageKey ) );
|
||||
if ( dict_element )
|
||||
{
|
||||
if ( !CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsage ) )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mUsage" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
CFRelease(io_properties);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate fields" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HidDevice populate_device( io_object_t io_obj )
|
||||
{
|
||||
void* interfacep = nullptr;
|
||||
HidDevice device;
|
||||
memset( &device, 0, sizeof( HidDevice ) );
|
||||
CFMutableDictionaryRef device_dic = 0;
|
||||
kern_return_t result = IORegistryEntryCreateCFProperties( io_obj, &device_dic, kCFAllocatorDefault, kNilOptions );
|
||||
|
||||
if ( KERN_SUCCESS == result
|
||||
&& device_dic )
|
||||
{
|
||||
IOReturn io_result = kIOReturnSuccess;
|
||||
HRESULT query_result = S_OK;
|
||||
SInt32 the_score = 0;
|
||||
IOCFPlugInInterface **the_interface = NULL;
|
||||
|
||||
|
||||
io_result = IOCreatePlugInInterfaceForService( io_obj, kIOHIDDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID, &the_interface, &the_score );
|
||||
if ( io_result == kIOReturnSuccess )
|
||||
{
|
||||
query_result = ( *the_interface )->QueryInterface( the_interface, CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ), ( LPVOID * ) & ( interfacep ) );
|
||||
if ( query_result != S_OK )
|
||||
{
|
||||
LL_WARNS("Joystick") << "QueryInterface failed" << LL_ENDL;
|
||||
}
|
||||
IODestroyPlugInInterface( the_interface );
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOCreatePlugInInterfaceForService failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
if ( interfacep )
|
||||
{
|
||||
result = ( *( IOHIDDeviceInterface** )interfacep )->open( interfacep, 0 );
|
||||
|
||||
if ( result != kIOReturnSuccess)
|
||||
{
|
||||
LL_WARNS("Joystick") << "open failed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
// extract needed fields
|
||||
populate_device_info( io_obj, device_dic, &device );
|
||||
|
||||
// Release interface
|
||||
if ( interfacep )
|
||||
{
|
||||
( *( IOHIDDeviceInterface** ) interfacep )->close( interfacep );
|
||||
|
||||
( *( IOHIDDeviceInterface** ) interfacep )->Release( interfacep );
|
||||
|
||||
interfacep = NULL;
|
||||
}
|
||||
|
||||
CFRelease( device_dic );
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "populate_device failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void get_devices(std::list<HidDevice> &list_of_devices,
|
||||
io_iterator_t inIODeviceIterator)
|
||||
{
|
||||
IOReturn result = kIOReturnSuccess; // assume success( optimist! )
|
||||
io_object_t io_obj = 0;
|
||||
|
||||
while ( 0 != (io_obj = IOIteratorNext( inIODeviceIterator ) ) )
|
||||
{
|
||||
HidDevice device = populate_device( io_obj );
|
||||
|
||||
list_of_devices.push_back(device);
|
||||
|
||||
// release the device object, it is no longer needed
|
||||
result = IOObjectRelease( io_obj );
|
||||
if ( KERN_SUCCESS != result )
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOObjectRelease failed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLWindowMacOSX::getInputDevices(U32 device_type_filter,
|
||||
std::function<void(std::string&, LLSD::Binary&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata)
|
||||
{
|
||||
CFMutableDictionaryRef device_dict_ref;
|
||||
IOReturn result = kIOReturnSuccess; // assume success( optimist! )
|
||||
|
||||
// Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error.
|
||||
|
||||
// A dictionary to match devices to?
|
||||
device_dict_ref = IOServiceMatching( kIOHIDDeviceKey );
|
||||
|
||||
// BUG FIX! one reference is consumed by IOServiceGetMatchingServices
|
||||
CFRetain( device_dict_ref );
|
||||
io_iterator_t io_iter = 0;
|
||||
|
||||
// create an IO object iterator
|
||||
result = IOServiceGetMatchingServices( kIOMasterPortDefault, device_dict_ref, &io_iter );
|
||||
if ( kIOReturnSuccess != result )
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOServiceGetMatchingServices failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
if ( io_iter )
|
||||
{
|
||||
// add all existing devices
|
||||
std::list<HidDevice> device_list;
|
||||
|
||||
get_devices(device_list, io_iter);
|
||||
|
||||
std::list<HidDevice>::iterator iter;
|
||||
|
||||
for (iter = device_list.begin(); iter != device_list.end(); ++iter)
|
||||
{
|
||||
S32 size = sizeof(long);
|
||||
LLSD::Binary data; //just an std::vector
|
||||
data.resize(size);
|
||||
memcpy(&data[0], &iter->mlocalID, size);
|
||||
std::string label(iter->mProduct);
|
||||
|
||||
osx_callback(label, data, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease( device_dict_ref );
|
||||
return false; // todo: should be true once UI part gets done
|
||||
}
|
||||
|
||||
LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
{
|
||||
LLSD result = LLSD::emptyMap();
|
||||
|
|
|
|||
|
|
@ -112,6 +112,11 @@ public:
|
|||
void interruptLanguageTextInput() override;
|
||||
void spawnWebBrowser(const std::string& escaped_url, bool async) override;
|
||||
F32 getSystemUISize() override;
|
||||
|
||||
bool getInputDevices(U32 device_type_filter,
|
||||
std::function<void(std::string&, LLSD::Binary&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata) override;
|
||||
|
||||
static std::vector<std::string> getDisplaysResolutionList();
|
||||
|
||||
|
|
|
|||
|
|
@ -4495,7 +4495,10 @@ void* LLWindowWin32::getDirectInput8()
|
|||
return &gDirectInput8;
|
||||
}
|
||||
|
||||
bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata)
|
||||
bool LLWindowWin32::getInputDevices(U32 device_type_filter
|
||||
std::function<void(std::string&, LLSD::Binary&, void*)> osx_callback,
|
||||
void * di8_devices_callback,
|
||||
void* userdata)
|
||||
{
|
||||
if (gDirectInput8 != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -129,7 +129,10 @@ public:
|
|||
static void setDPIAwareness();
|
||||
|
||||
/*virtual*/ void* getDirectInput8();
|
||||
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata);
|
||||
/*virtual*/ bool getInputDevices(U32 device_type_filter,
|
||||
std::function<void(std::string&, LLSD::Binary&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata);
|
||||
|
||||
U32 getRawWParam() { return mRawWParam; }
|
||||
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
|
|||
|
||||
if (!LLXMLNode::parseFile(filename, root, NULL))
|
||||
{
|
||||
LL_WARNS() << "Problem reading UI description file: " << filename << LL_ENDL;
|
||||
LL_WARNS() << "Problem reading UI description file: " << filename << " " << errno << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -599,6 +599,9 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
|
|||
switch(filter)
|
||||
{
|
||||
case FFLOAD_ALL:
|
||||
case FFLOAD_EXE:
|
||||
allowedv->push_back("app");
|
||||
allowedv->push_back("exe");
|
||||
allowedv->push_back("wav");
|
||||
allowedv->push_back("bvh");
|
||||
allowedv->push_back("anim");
|
||||
|
|
@ -617,9 +620,6 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
|
|||
allowedv->push_back("tpic");
|
||||
allowedv->push_back("png");
|
||||
break;
|
||||
case FFLOAD_EXE:
|
||||
allowedv->push_back("app");
|
||||
allowedv->push_back("exe");
|
||||
break;
|
||||
case FFLOAD_WAV:
|
||||
allowedv->push_back("wav");
|
||||
|
|
|
|||
|
|
@ -250,6 +250,12 @@ void LLFloaterJoystick::refresh()
|
|||
initFromSettings();
|
||||
}
|
||||
|
||||
void LLFloaterJoystick::addDeviceCallback(std::string &name, LLSD::Binary& value, void* userdata)
|
||||
{
|
||||
LLFloaterJoystick * floater = (LLFloaterJoystick*)userdata;
|
||||
floater->mJoysticksCombo->add(name, value, ADD_BOTTOM, 1);
|
||||
}
|
||||
|
||||
void LLFloaterJoystick::addDevice(std::string &name, LLSD& value)
|
||||
{
|
||||
mJoysticksCombo->add(name, value, ADD_BOTTOM, 1);
|
||||
|
|
@ -264,19 +270,21 @@ void LLFloaterJoystick::refreshListOfDevices()
|
|||
|
||||
mHasDeviceList = false;
|
||||
|
||||
void* win_calback = nullptr;
|
||||
// di8_devices_callback callback is immediate and happens in scope of getInputDevices()
|
||||
#if LL_WINDOWS && !LL_MESA_HEADLESS
|
||||
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
|
||||
U32 device_type = DI8DEVCLASS_GAMECTRL;
|
||||
void* callback = &di8_list_devices_callback;
|
||||
win_calback = di8_list_devices_callback;
|
||||
#elif LL_DARWIN
|
||||
U32 device_type = 0;
|
||||
#else
|
||||
// MAC doesn't support device search yet
|
||||
// On MAC there is an ndof_idsearch and it is possible to specify product
|
||||
// and manufacturer in NDOF_Device for ndof_init_first to pick specific one
|
||||
U32 device_type = 0;
|
||||
void* callback = NULL;
|
||||
#endif
|
||||
if (gViewerWindow->getWindow()->getInputDevices(device_type, callback, this))
|
||||
if (gViewerWindow->getWindow()->getInputDevices(device_type, addDeviceCallback, win_calback, this))
|
||||
{
|
||||
mHasDeviceList = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public:
|
|||
virtual void draw();
|
||||
static void setSNDefaults();
|
||||
|
||||
static void addDeviceCallback(std::string &name, LLSD::Binary& value, void* userdata);
|
||||
void addDevice(std::string &name, LLSD& value);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -227,8 +227,17 @@ std::string string_from_guid(const GUID &guid)
|
|||
|
||||
return res;
|
||||
}
|
||||
#elif LL_DARWIN
|
||||
|
||||
bool macos_devices_callback(std::string &product, LLSD::Binary &data, void* userdata)
|
||||
{
|
||||
//LLViewerJoystick::getInstance()->initDevice(&device, product_name, data);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void LLViewerJoystick::updateEnabled(bool autoenable)
|
||||
{
|
||||
|
|
@ -365,19 +374,21 @@ void LLViewerJoystick::init(bool autoenable)
|
|||
{
|
||||
if (mNdofDev)
|
||||
{
|
||||
void* win_callback = nullptr;
|
||||
std::function<void(std::string&, LLSD::Binary&, void*)> osx_callback;
|
||||
// di8_devices_callback callback is immediate and happens in scope of getInputDevices()
|
||||
#if LL_WINDOWS && !LL_MESA_HEADLESS
|
||||
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
|
||||
U32 device_type = DI8DEVCLASS_GAMECTRL;
|
||||
void* callback = &di8_devices_callback;
|
||||
win_callback = &di8_devices_callback;
|
||||
#else
|
||||
// MAC doesn't support device search yet
|
||||
// On MAC there is an ndof_idsearch and it is possible to specify product
|
||||
// and manufacturer in NDOF_Device for ndof_init_first to pick specific one
|
||||
U32 device_type = 0;
|
||||
void* callback = NULL;
|
||||
osx_callback = macos_devices_callback;
|
||||
#endif
|
||||
if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL))
|
||||
if (!gViewerWindow->getWindow()->getInputDevices(device_type, osx_callback, win_callback, NULL))
|
||||
{
|
||||
LL_INFOS("Joystick") << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL;
|
||||
// Failed to gather devices from windows, init first suitable one
|
||||
|
|
@ -438,21 +449,23 @@ void LLViewerJoystick::initDevice(LLSD &guid)
|
|||
{
|
||||
#if LIB_NDOF
|
||||
mLastDeviceUUID = guid;
|
||||
void* win_callback = nullptr;
|
||||
std::function<void(std::string&, LLSD::Binary&, void*)> osx_callback;
|
||||
|
||||
#if LL_WINDOWS && !LL_MESA_HEADLESS
|
||||
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
|
||||
U32 device_type = DI8DEVCLASS_GAMECTRL;
|
||||
void* callback = &di8_devices_callback;
|
||||
win_callback = &di8_devices_callback;
|
||||
#else
|
||||
// MAC doesn't support device search yet
|
||||
// On MAC there is an ndof_idsearch and it is possible to specify product
|
||||
// and manufacturer in NDOF_Device for ndof_init_first to pick specific one
|
||||
U32 device_type = 0;
|
||||
void* callback = NULL;
|
||||
osx_callback = macos_devices_callback;
|
||||
#endif
|
||||
|
||||
mDriverState = JDS_INITIALIZING;
|
||||
if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL))
|
||||
if (!gViewerWindow->getWindow()->getInputDevices(device_type, osx_callback, win_callback, NULL))
|
||||
{
|
||||
LL_INFOS("Joystick") << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL;
|
||||
// Failed to gather devices from windows, init first suitable one
|
||||
|
|
|
|||
|
|
@ -103,7 +103,11 @@ private:
|
|||
bool mCameraUpdated;
|
||||
bool mOverrideCamera;
|
||||
U32 mJoystickRun;
|
||||
LLSD mLastDeviceUUID; // _GUID as U8 binary map, integer 1 for no device/ndof's device
|
||||
|
||||
// Windows: _GUID as U8 binary map
|
||||
// MacOS: long as an U8 binary map
|
||||
// Else: integer 1 for no device/ndof's default device
|
||||
LLSD mLastDeviceUUID;
|
||||
|
||||
static F32 sLastDelta[7];
|
||||
static F32 sDelta[7];
|
||||
|
|
|
|||
|
|
@ -435,6 +435,18 @@
|
|||
left_pad="5"
|
||||
top_pad="7"
|
||||
width="180" />
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="Claimed:"
|
||||
top="247"
|
||||
width="100">
|
||||
Place Page:
|
||||
</text>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
|
|||
Loading…
Reference in New Issue