dolphin/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.mm

273 lines
8.3 KiB
Plaintext

// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <sstream>
#include <Cocoa/Cocoa.h>
#include <Foundation/Foundation.h>
#include <IOKit/hid/IOHIDLib.h>
#include "InputCommon/ControllerInterface/OSX/OSXKeyboard.h"
namespace ciface
{
namespace OSX
{
Keyboard::Keyboard(IOHIDDeviceRef device, std::string name, void* window)
: m_device(device), m_device_name(name)
{
// This class should only receive Keyboard or Keypad devices
// Now, filter on just the buttons we can handle sanely
NSDictionary* matchingElements = @{
@kIOHIDElementTypeKey : @(kIOHIDElementTypeInput_Button),
@kIOHIDElementMinKey : @0,
@kIOHIDElementMaxKey : @1
};
CFArrayRef elements = IOHIDDeviceCopyMatchingElements(m_device, (CFDictionaryRef)matchingElements,
kIOHIDOptionsTypeNone);
if (elements)
{
for (int i = 0; i < CFArrayGetCount(elements); i++)
{
IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
// DeviceElementDebugPrint(e, nullptr);
AddInput(new Key(e, m_device));
}
CFRelease(elements);
}
m_windowid = [[reinterpret_cast<NSView*>(window) window] windowNumber];
// cursor, with a hax for-loop
for (unsigned int i = 0; i < 4; ++i)
AddInput(new Cursor(!!(i & 2), (&m_cursor.x)[i / 2], !!(i & 1)));
for (u8 i = 0; i < sizeof(m_mousebuttons) / sizeof(m_mousebuttons[0]); ++i)
AddInput(new Button(i, m_mousebuttons[i]));
}
void Keyboard::UpdateInput()
{
CGRect bounds = CGRectZero;
uint32_t windowid[1] = {m_windowid};
CFArrayRef windowArray = CFArrayCreate(nullptr, (const void**)windowid, 1, nullptr);
CFArrayRef windowDescriptions = CGWindowListCreateDescriptionFromArray(windowArray);
CFDictionaryRef windowDescription =
(CFDictionaryRef)CFArrayGetValueAtIndex((CFArrayRef)windowDescriptions, 0);
if (CFDictionaryContainsKey(windowDescription, kCGWindowBounds))
{
CFDictionaryRef boundsDictionary =
(CFDictionaryRef)CFDictionaryGetValue(windowDescription, kCGWindowBounds);
if (boundsDictionary != nullptr)
CGRectMakeWithDictionaryRepresentation(boundsDictionary, &bounds);
}
CFRelease(windowDescriptions);
CFRelease(windowArray);
CGEventRef event = CGEventCreate(nil);
CGPoint loc = CGEventGetLocation(event);
CFRelease(event);
loc.x -= bounds.origin.x;
loc.y -= bounds.origin.y;
m_cursor.x = loc.x / bounds.size.width * 2 - 1.0;
m_cursor.y = loc.y / bounds.size.height * 2 - 1.0;
m_mousebuttons[0] =
CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonLeft);
m_mousebuttons[1] =
CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonRight);
m_mousebuttons[2] =
CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonCenter);
}
std::string Keyboard::GetName() const
{
return m_device_name;
}
std::string Keyboard::GetSource() const
{
return "Keyboard";
}
Keyboard::Key::Key(IOHIDElementRef element, IOHIDDeviceRef device)
: m_element(element), m_device(device)
{
static const struct PrettyKeys
{
const uint32_t code;
const char* const name;
} named_keys[] = {
{kHIDUsage_KeyboardA, "A"},
{kHIDUsage_KeyboardB, "B"},
{kHIDUsage_KeyboardC, "C"},
{kHIDUsage_KeyboardD, "D"},
{kHIDUsage_KeyboardE, "E"},
{kHIDUsage_KeyboardF, "F"},
{kHIDUsage_KeyboardG, "G"},
{kHIDUsage_KeyboardH, "H"},
{kHIDUsage_KeyboardI, "I"},
{kHIDUsage_KeyboardJ, "J"},
{kHIDUsage_KeyboardK, "K"},
{kHIDUsage_KeyboardL, "L"},
{kHIDUsage_KeyboardM, "M"},
{kHIDUsage_KeyboardN, "N"},
{kHIDUsage_KeyboardO, "O"},
{kHIDUsage_KeyboardP, "P"},
{kHIDUsage_KeyboardQ, "Q"},
{kHIDUsage_KeyboardR, "R"},
{kHIDUsage_KeyboardS, "S"},
{kHIDUsage_KeyboardT, "T"},
{kHIDUsage_KeyboardU, "U"},
{kHIDUsage_KeyboardV, "V"},
{kHIDUsage_KeyboardW, "W"},
{kHIDUsage_KeyboardX, "X"},
{kHIDUsage_KeyboardY, "Y"},
{kHIDUsage_KeyboardZ, "Z"},
{kHIDUsage_Keyboard1, "1"},
{kHIDUsage_Keyboard2, "2"},
{kHIDUsage_Keyboard3, "3"},
{kHIDUsage_Keyboard4, "4"},
{kHIDUsage_Keyboard5, "5"},
{kHIDUsage_Keyboard6, "6"},
{kHIDUsage_Keyboard7, "7"},
{kHIDUsage_Keyboard8, "8"},
{kHIDUsage_Keyboard9, "9"},
{kHIDUsage_Keyboard0, "0"},
{kHIDUsage_KeyboardReturnOrEnter, "Return"},
{kHIDUsage_KeyboardEscape, "Escape"},
{kHIDUsage_KeyboardDeleteOrBackspace, "Backspace"},
{kHIDUsage_KeyboardTab, "Tab"},
{kHIDUsage_KeyboardSpacebar, "Space"},
{kHIDUsage_KeyboardHyphen, "-"},
{kHIDUsage_KeyboardEqualSign, "="},
{kHIDUsage_KeyboardOpenBracket, "["},
{kHIDUsage_KeyboardCloseBracket, "]"},
{kHIDUsage_KeyboardBackslash, "\\"},
{kHIDUsage_KeyboardSemicolon, ";"},
{kHIDUsage_KeyboardQuote, "'"},
{kHIDUsage_KeyboardGraveAccentAndTilde, "Tilde"},
{kHIDUsage_KeyboardComma, ","},
{kHIDUsage_KeyboardPeriod, "."},
{kHIDUsage_KeyboardSlash, "/"},
{kHIDUsage_KeyboardCapsLock, "Caps Lock"},
{kHIDUsage_KeyboardF1, "F1"},
{kHIDUsage_KeyboardF2, "F2"},
{kHIDUsage_KeyboardF3, "F3"},
{kHIDUsage_KeyboardF4, "F4"},
{kHIDUsage_KeyboardF5, "F5"},
{kHIDUsage_KeyboardF6, "F6"},
{kHIDUsage_KeyboardF7, "F7"},
{kHIDUsage_KeyboardF8, "F8"},
{kHIDUsage_KeyboardF9, "F9"},
{kHIDUsage_KeyboardF10, "F10"},
{kHIDUsage_KeyboardF11, "F11"},
{kHIDUsage_KeyboardF12, "F12"},
{kHIDUsage_KeyboardInsert, "Insert"},
{kHIDUsage_KeyboardHome, "Home"},
{kHIDUsage_KeyboardPageUp, "Page Up"},
{kHIDUsage_KeyboardDeleteForward, "Delete"},
{kHIDUsage_KeyboardEnd, "End"},
{kHIDUsage_KeyboardPageDown, "Page Down"},
{kHIDUsage_KeyboardRightArrow, "Right Arrow"},
{kHIDUsage_KeyboardLeftArrow, "Left Arrow"},
{kHIDUsage_KeyboardDownArrow, "Down Arrow"},
{kHIDUsage_KeyboardUpArrow, "Up Arrow"},
{kHIDUsage_KeypadSlash, "Keypad /"},
{kHIDUsage_KeypadAsterisk, "Keypad *"},
{kHIDUsage_KeypadHyphen, "Keypad -"},
{kHIDUsage_KeypadPlus, "Keypad +"},
{kHIDUsage_KeypadEnter, "Keypad Enter"},
{kHIDUsage_Keypad1, "Keypad 1"},
{kHIDUsage_Keypad2, "Keypad 2"},
{kHIDUsage_Keypad3, "Keypad 3"},
{kHIDUsage_Keypad4, "Keypad 4"},
{kHIDUsage_Keypad5, "Keypad 5"},
{kHIDUsage_Keypad6, "Keypad 6"},
{kHIDUsage_Keypad7, "Keypad 7"},
{kHIDUsage_Keypad8, "Keypad 8"},
{kHIDUsage_Keypad9, "Keypad 9"},
{kHIDUsage_Keypad0, "Keypad 0"},
{kHIDUsage_KeypadPeriod, "Keypad ."},
{kHIDUsage_KeyboardNonUSBackslash, "Paragraph"},
{kHIDUsage_KeypadEqualSign, "Keypad ="},
{kHIDUsage_KeypadComma, "Keypad ,"},
{kHIDUsage_KeyboardLeftControl, "Left Control"},
{kHIDUsage_KeyboardLeftShift, "Left Shift"},
{kHIDUsage_KeyboardLeftAlt, "Left Alt"},
{kHIDUsage_KeyboardLeftGUI, "Left Command"},
{kHIDUsage_KeyboardRightControl, "Right Control"},
{kHIDUsage_KeyboardRightShift, "Right Shift"},
{kHIDUsage_KeyboardRightAlt, "Right Alt"},
{kHIDUsage_KeyboardRightGUI, "Right Command"},
{184, "Eject"},
};
const uint32_t keycode = IOHIDElementGetUsage(m_element);
for (auto& named_key : named_keys)
{
if (named_key.code == keycode)
{
m_name = named_key.name;
return;
}
}
std::stringstream ss;
ss << "Key " << keycode;
m_name = ss.str();
}
ControlState Keyboard::Key::GetState() const
{
IOHIDValueRef value;
if (IOHIDDeviceGetValue(m_device, m_element, &value) == kIOReturnSuccess)
return IOHIDValueGetIntegerValue(value);
else
return 0;
}
ControlState Keyboard::Cursor::GetState() const
{
return std::max(0.0, ControlState(m_axis) / (m_positive ? 1.0 : -1.0));
}
ControlState Keyboard::Button::GetState() const
{
return (m_button != 0);
}
std::string Keyboard::Cursor::GetName() const
{
static char tmpstr[] = "Cursor ..";
tmpstr[7] = (char)('X' + m_index);
tmpstr[8] = (m_positive ? '+' : '-');
return tmpstr;
}
std::string Keyboard::Button::GetName() const
{
return std::string("Click ") + char('0' + m_index);
}
std::string Keyboard::Key::GetName() const
{
return m_name;
}
bool Keyboard::IsSameDevice(const IOHIDDeviceRef other_device) const
{
return m_device == other_device;
}
}
}