diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp
index 5da722a72bb8fd1815c5ee3ddcdb4cb58926f765..ecd065a4ef73b27626974b59a42f51af350aa8cf 100644
--- a/indra/llui/lltransutil.cpp
+++ b/indra/llui/lltransutil.cpp
@@ -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;
 	}
 
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index ac4848579fbcf0426893b73f318f35d4683476aa..2d27092e0adb8dd580b16d8b49cc266a441bb55d 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -196,7 +196,13 @@ class LLWindow : public LLInstanceTracker<LLWindow>
 
     // 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:
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 690fe058dbf56e9838d39a2b29840e7429c6b8a0..2e75d309ea6fed55d404129efff0d4a255e2ec5c 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -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"
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 2c841d4703f6b1b6ea80be32567e065511ecc927..bd13138a7d678f3ae69b57fb987bf3828b429229 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -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'))
-    {
-        key = gKeyboard->inverseTranslateKey('Y');
-    }
-    else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
+    //if (mask!=MASK_NONE)
     {
-        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();
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 851c860017fd8153fbc4fa029746119ba7c32d47..cec4f86b252840b6b87ab051c3ea86e3ab747c2a 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -112,6 +112,11 @@ class LLWindowMacOSX : public LLWindow
 	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();
 
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 2e560ddb0a6ae8727deb497cd6d16dae3111c076..b959c034060986abff3ee5f44e2a92adb0fea77e 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -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)
     {
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index b391acc12d390b8484f0d0d62f418571ac3b3d9c..6fbb956539b2e1b063ebb09e53e61c4b356872c8 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -129,7 +129,10 @@ class LLWindowWin32 : public LLWindow
 	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; }
 
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 455df13e48d9d2c002062dd5e3998189380e2257..43d4adbc267192c357e7b1cef92329badd1132fa 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -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;
 	}
 
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index f1f156c2e099cd666e317cf8436d13384d9fae88..e416172eb23e91656972c1179ee9861a2ad6152b 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -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");
diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp
index 558b14bba7c0fecd71e3fd9255c5148788628f99..5265411e5429d9ad859d7f3eac6e7404dd9f45d4 100644
--- a/indra/newview/llfloaterjoystick.cpp
+++ b/indra/newview/llfloaterjoystick.cpp
@@ -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;
     }
diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h
index 1d46efd3f642fb6c97a068c9d8bff52422bc211b..912d9b5310a6b26d7586cf34957fc8be70a5b138 100644
--- a/indra/newview/llfloaterjoystick.h
+++ b/indra/newview/llfloaterjoystick.h
@@ -46,6 +46,7 @@ class LLFloaterJoystick : public LLFloater
 	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:
diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp
index e35cb26ce1d4be6c0d37cc11a2f11d48b608730d..26a626f60fc76e4d3c7cc22dc83d7548fb531cc5 100644
--- a/indra/newview/llviewerjoystick.cpp
+++ b/indra/newview/llviewerjoystick.cpp
@@ -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
diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h
index 3b4f8987100069727df93030225efb671336e3b8..49f8c8eabf4f42e9f40524cc228245a9d7cf05b1 100644
--- a/indra/newview/llviewerjoystick.h
+++ b/indra/newview/llviewerjoystick.h
@@ -103,7 +103,11 @@ class LLViewerJoystick : public LLSingleton<LLViewerJoystick>
 	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];
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index b1ed2453784faa42cbaac989c2d2f9faac30c0c3..d0d4b4ebc07fa904dad273e734f9b7a73082466c 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -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"