Merge pull request #4594 from FernetMenta/paplayer
[xbmc.git] / xbmc / input / KeyboardStat.cpp
blob222863b6fe55f7066784487428e86d60c38ba2dc
1 /*
2 * Copyright (C) 2007-2013 Team XBMC
3 * http://xbmc.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 // C++ Implementation: CKeyboard
23 // Comment OUT, if not really debugging!!!:
24 //#define DEBUG_KEYBOARD_GETCHAR
26 #include "KeyboardStat.h"
27 #include "KeyboardLayoutConfiguration.h"
28 #include "windowing/XBMC_events.h"
29 #include "utils/TimeUtils.h"
30 #include "input/XBMC_keytable.h"
31 #include "input/XBMC_vkeys.h"
32 #include "peripherals/Peripherals.h"
33 #include "peripherals/devices/PeripheralHID.h"
35 using namespace std;
36 using namespace PERIPHERALS;
38 CKeyboardStat g_Keyboard;
40 CKeyboardStat::CKeyboardStat()
42 memset(&m_lastKeysym, 0, sizeof(m_lastKeysym));
43 m_lastKeyTime = 0;
46 CKeyboardStat::~CKeyboardStat()
50 void CKeyboardStat::Initialize()
54 bool CKeyboardStat::LookupSymAndUnicodePeripherals(XBMC_keysym &keysym, uint8_t *key, char *unicode)
56 vector<CPeripheral *> hidDevices;
57 if (g_peripherals.GetPeripheralsWithFeature(hidDevices, FEATURE_HID))
59 for (unsigned int iDevicePtr = 0; iDevicePtr < hidDevices.size(); iDevicePtr++)
61 CPeripheralHID *hidDevice = (CPeripheralHID *) hidDevices.at(iDevicePtr);
62 if (hidDevice && hidDevice->LookupSymAndUnicode(keysym, key, unicode))
63 return true;
66 return false;
69 const CKey CKeyboardStat::ProcessKeyDown(XBMC_keysym& keysym)
70 { uint8_t vkey;
71 wchar_t unicode;
72 char ascii;
73 uint32_t modifiers;
74 unsigned int held;
75 XBMCKEYTABLE keytable;
77 modifiers = 0;
78 if (keysym.mod & XBMCKMOD_CTRL)
79 modifiers |= CKey::MODIFIER_CTRL;
80 if (keysym.mod & XBMCKMOD_SHIFT)
81 modifiers |= CKey::MODIFIER_SHIFT;
82 if (keysym.mod & XBMCKMOD_ALT)
83 modifiers |= CKey::MODIFIER_ALT;
84 if (keysym.mod & XBMCKMOD_SUPER)
85 modifiers |= CKey::MODIFIER_SUPER;
86 if (keysym.mod & XBMCKMOD_META)
87 modifiers |= CKey::MODIFIER_META;
89 CLog::Log(LOGDEBUG, "Keyboard: scancode: 0x%02x, sym: 0x%04x, unicode: 0x%04x, modifier: 0x%x", keysym.scancode, keysym.sym, keysym.unicode, keysym.mod);
91 // The keysym.unicode is usually valid, even if it is zero. A zero
92 // unicode just means this is a non-printing keypress. The ascii and
93 // vkey will be set below.
94 unicode = keysym.unicode;
95 ascii = 0;
96 vkey = 0;
97 held = 0;
99 // Start by check whether any of the HID peripherals wants to translate this keypress
100 if (LookupSymAndUnicodePeripherals(keysym, &vkey, &ascii))
102 CLog::Log(LOGDEBUG, "%s - keypress translated by a HID peripheral", __FUNCTION__);
105 // Continue by trying to match both the sym and unicode. This will identify
106 // the majority of keypresses
107 else if (KeyTableLookupSymAndUnicode(keysym.sym, keysym.unicode, &keytable))
109 vkey = keytable.vkey;
110 ascii = keytable.ascii;
113 // If we failed to match the sym and unicode try just the unicode. This
114 // will match keys like \ that are on different keys on regional keyboards.
115 else if (KeyTableLookupUnicode(keysym.unicode, &keytable))
117 vkey = keytable.vkey;
118 ascii = keytable.ascii;
121 // If there is still no match try the sym
122 else if (KeyTableLookupSym(keysym.sym, &keytable))
124 vkey = keytable.vkey;
126 // Occasionally we get non-printing keys that have a non-zero value in
127 // the keysym.unicode. Check for this here and replace any rogue unicode
128 // values.
129 if (keytable.unicode == 0 && unicode != 0)
130 unicode = 0;
131 else if (keysym.unicode > 32 && keysym.unicode < 128)
132 ascii = unicode & 0x7f;
135 // The keysym.sym is unknown ...
136 else
138 if (!vkey && !ascii)
140 if (keysym.mod & XBMCKMOD_LSHIFT) vkey = 0xa0;
141 else if (keysym.mod & XBMCKMOD_RSHIFT) vkey = 0xa1;
142 else if (keysym.mod & XBMCKMOD_LALT) vkey = 0xa4;
143 else if (keysym.mod & XBMCKMOD_RALT) vkey = 0xa5;
144 else if (keysym.mod & XBMCKMOD_LCTRL) vkey = 0xa2;
145 else if (keysym.mod & XBMCKMOD_RCTRL) vkey = 0xa3;
146 else if (keysym.unicode > 32 && keysym.unicode < 128)
147 // only TRUE ASCII! (Otherwise XBMC crashes! No unicode not even latin 1!)
148 ascii = (char)(keysym.unicode & 0xff);
152 // At this point update the key hold time
153 if (keysym.mod == m_lastKeysym.mod && keysym.scancode == m_lastKeysym.scancode && keysym.sym == m_lastKeysym.sym && keysym.unicode == m_lastKeysym.unicode)
155 held = CTimeUtils::GetFrameTime() - m_lastKeyTime;
157 else
159 m_lastKeysym = keysym;
160 m_lastKeyTime = CTimeUtils::GetFrameTime();
161 held = 0;
164 // For all shift-X keys except shift-A to shift-Z and shift-F1 to shift-F24 the
165 // shift modifier is ignored. This so that, for example, the * keypress (shift-8)
166 // is seen as <asterisk> not <asterisk mod="shift">.
167 // The A-Z keys are exempted because shift-A-Z is used for navigation in lists.
168 // The function keys are exempted because function keys have no shifted value and
169 // the Nyxboard remote uses keys like Shift-F3 for some buttons.
170 if (modifiers == CKey::MODIFIER_SHIFT)
171 if ((unicode < 'A' || unicode > 'Z') && (unicode < 'a' || unicode > 'z') && (vkey < XBMCVK_F1 || vkey > XBMCVK_F24))
172 modifiers = 0;
174 // Create and return a CKey
176 CKey key(vkey, unicode, ascii, modifiers, held);
178 return key;
181 void CKeyboardStat::ProcessKeyUp(void)
183 memset(&m_lastKeysym, 0, sizeof(m_lastKeysym));
184 m_lastKeyTime = 0;
187 // Return the key name given a key ID
188 // Used to make the debug log more intelligable
189 // The KeyID includes the flags for ctrl, alt etc
191 CStdString CKeyboardStat::GetKeyName(int KeyID)
192 { int keyid;
193 CStdString keyname;
194 XBMCKEYTABLE keytable;
196 keyname.clear();
198 // Get modifiers
200 if (KeyID & CKey::MODIFIER_CTRL)
201 keyname.append("ctrl-");
202 if (KeyID & CKey::MODIFIER_SHIFT)
203 keyname.append("shift-");
204 if (KeyID & CKey::MODIFIER_ALT)
205 keyname.append("alt-");
206 if (KeyID & CKey::MODIFIER_SUPER)
207 keyname.append("win-");
208 if (KeyID & CKey::MODIFIER_META)
209 keyname.append("meta-");
211 // Now get the key name
213 keyid = KeyID & 0xFF;
214 if (KeyTableLookupVKeyName(keyid, &keytable))
215 keyname.append(keytable.keyname);
216 else
217 keyname += StringUtils::Format("%i", keyid);
218 keyname += StringUtils::Format(" (0x%02x)", KeyID);
220 return keyname;