diff options
Diffstat (limited to 'src/input/KeyboardStat.cpp')
-rw-r--r-- | src/input/KeyboardStat.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/input/KeyboardStat.cpp b/src/input/KeyboardStat.cpp new file mode 100644 index 0000000000..75f726521c --- /dev/null +++ b/src/input/KeyboardStat.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2007-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +// C++ Implementation: CKeyboard + +// Comment OUT, if not really debugging!!!: +//#define DEBUG_KEYBOARD_GETCHAR + +#include "KeyboardStat.h" +#include "KeyboardLayoutConfiguration.h" +#include "windowing/XBMC_events.h" +#include "utils/TimeUtils.h" +#include "input/XBMC_keytable.h" +#include "input/XBMC_vkeys.h" +#include "peripherals/Peripherals.h" +#include "peripherals/devices/PeripheralHID.h" + +using namespace std; +using namespace PERIPHERALS; + +CKeyboardStat g_Keyboard; + +CKeyboardStat::CKeyboardStat() +{ + memset(&m_lastKeysym, 0, sizeof(m_lastKeysym)); + m_lastKeyTime = 0; +} + +CKeyboardStat::~CKeyboardStat() +{ +} + +void CKeyboardStat::Initialize() +{ +} + +bool CKeyboardStat::LookupSymAndUnicodePeripherals(XBMC_keysym &keysym, uint8_t *key, char *unicode) +{ + vector<CPeripheral *> hidDevices; + if (g_peripherals.GetPeripheralsWithFeature(hidDevices, FEATURE_HID)) + { + for (unsigned int iDevicePtr = 0; iDevicePtr < hidDevices.size(); iDevicePtr++) + { + CPeripheralHID *hidDevice = (CPeripheralHID *) hidDevices.at(iDevicePtr); + if (hidDevice && hidDevice->LookupSymAndUnicode(keysym, key, unicode)) + return true; + } + } + return false; +} + +const CKey CKeyboardStat::ProcessKeyDown(XBMC_keysym& keysym) +{ uint8_t vkey; + wchar_t unicode; + char ascii; + uint32_t modifiers; + unsigned int held; + XBMCKEYTABLE keytable; + + modifiers = 0; + if (keysym.mod & XBMCKMOD_CTRL) + modifiers |= CKey::MODIFIER_CTRL; + if (keysym.mod & XBMCKMOD_SHIFT) + modifiers |= CKey::MODIFIER_SHIFT; + if (keysym.mod & XBMCKMOD_ALT) + modifiers |= CKey::MODIFIER_ALT; + if (keysym.mod & XBMCKMOD_SUPER) + modifiers |= CKey::MODIFIER_SUPER; + if (keysym.mod & XBMCKMOD_META) + modifiers |= CKey::MODIFIER_META; + + CLog::Log(LOGDEBUG, "Keyboard: scancode: 0x%02x, sym: 0x%04x, unicode: 0x%04x, modifier: 0x%x", keysym.scancode, keysym.sym, keysym.unicode, keysym.mod); + + // The keysym.unicode is usually valid, even if it is zero. A zero + // unicode just means this is a non-printing keypress. The ascii and + // vkey will be set below. + unicode = keysym.unicode; + ascii = 0; + vkey = 0; + held = 0; + + // Start by check whether any of the HID peripherals wants to translate this keypress + if (LookupSymAndUnicodePeripherals(keysym, &vkey, &ascii)) + { + CLog::Log(LOGDEBUG, "%s - keypress translated by a HID peripheral", __FUNCTION__); + } + + // Continue by trying to match both the sym and unicode. This will identify + // the majority of keypresses + else if (KeyTableLookupSymAndUnicode(keysym.sym, keysym.unicode, &keytable)) + { + vkey = keytable.vkey; + ascii = keytable.ascii; + } + + // If we failed to match the sym and unicode try just the unicode. This + // will match keys like \ that are on different keys on regional keyboards. + else if (KeyTableLookupUnicode(keysym.unicode, &keytable)) + { + vkey = keytable.vkey; + ascii = keytable.ascii; + } + + // If there is still no match try the sym + else if (KeyTableLookupSym(keysym.sym, &keytable)) + { + vkey = keytable.vkey; + + // Occasionally we get non-printing keys that have a non-zero value in + // the keysym.unicode. Check for this here and replace any rogue unicode + // values. + if (keytable.unicode == 0 && unicode != 0) + unicode = 0; + else if (keysym.unicode > 32 && keysym.unicode < 128) + ascii = unicode & 0x7f; + } + + // The keysym.sym is unknown ... + else + { + if (!vkey && !ascii) + { + if (keysym.mod & XBMCKMOD_LSHIFT) vkey = 0xa0; + else if (keysym.mod & XBMCKMOD_RSHIFT) vkey = 0xa1; + else if (keysym.mod & XBMCKMOD_LALT) vkey = 0xa4; + else if (keysym.mod & XBMCKMOD_RALT) vkey = 0xa5; + else if (keysym.mod & XBMCKMOD_LCTRL) vkey = 0xa2; + else if (keysym.mod & XBMCKMOD_RCTRL) vkey = 0xa3; + else if (keysym.unicode > 32 && keysym.unicode < 128) + // only TRUE ASCII! (Otherwise XBMC crashes! No unicode not even latin 1!) + ascii = (char)(keysym.unicode & 0xff); + } + } + + // At this point update the key hold time + if (keysym.mod == m_lastKeysym.mod && keysym.scancode == m_lastKeysym.scancode && keysym.sym == m_lastKeysym.sym && keysym.unicode == m_lastKeysym.unicode) + { + held = CTimeUtils::GetFrameTime() - m_lastKeyTime; + } + else + { + m_lastKeysym = keysym; + m_lastKeyTime = CTimeUtils::GetFrameTime(); + held = 0; + } + + // For all shift-X keys except shift-A to shift-Z and shift-F1 to shift-F24 the + // shift modifier is ignored. This so that, for example, the * keypress (shift-8) + // is seen as <asterisk> not <asterisk mod="shift">. + // The A-Z keys are exempted because shift-A-Z is used for navigation in lists. + // The function keys are exempted because function keys have no shifted value and + // the Nyxboard remote uses keys like Shift-F3 for some buttons. + if (modifiers == CKey::MODIFIER_SHIFT) + if ((unicode < 'A' || unicode > 'Z') && (unicode < 'a' || unicode > 'z') && (vkey < XBMCVK_F1 || vkey > XBMCVK_F24)) + modifiers = 0; + + // Create and return a CKey + + CKey key(vkey, unicode, ascii, modifiers, held); + + return key; +} + +void CKeyboardStat::ProcessKeyUp(void) +{ + memset(&m_lastKeysym, 0, sizeof(m_lastKeysym)); + m_lastKeyTime = 0; +} + +// Return the key name given a key ID +// Used to make the debug log more intelligable +// The KeyID includes the flags for ctrl, alt etc + +std::string CKeyboardStat::GetKeyName(int KeyID) +{ int keyid; + std::string keyname; + XBMCKEYTABLE keytable; + + keyname.clear(); + +// Get modifiers + + if (KeyID & CKey::MODIFIER_CTRL) + keyname.append("ctrl-"); + if (KeyID & CKey::MODIFIER_SHIFT) + keyname.append("shift-"); + if (KeyID & CKey::MODIFIER_ALT) + keyname.append("alt-"); + if (KeyID & CKey::MODIFIER_SUPER) + keyname.append("win-"); + if (KeyID & CKey::MODIFIER_META) + keyname.append("meta-"); + +// Now get the key name + + keyid = KeyID & 0xFF; + if (KeyTableLookupVKeyName(keyid, &keytable)) + keyname.append(keytable.keyname); + else + keyname += StringUtils::Format("%i", keyid); + keyname += StringUtils::Format(" (0x%02x)", KeyID); + + return keyname; +} + + |