2 * Copyright (C) 2007-2013 Team XBMC
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)
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"
36 using namespace PERIPHERALS
;
38 CKeyboardStat g_Keyboard
;
40 CKeyboardStat::CKeyboardStat()
42 memset(&m_lastKeysym
, 0, sizeof(m_lastKeysym
));
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
))
69 const CKey
CKeyboardStat::ProcessKeyDown(XBMC_keysym
& keysym
)
75 XBMCKEYTABLE keytable
;
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
;
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
129 if (keytable
.unicode
== 0 && unicode
!= 0)
131 else if (keysym
.unicode
> 32 && keysym
.unicode
< 128)
132 ascii
= unicode
& 0x7f;
135 // The keysym.sym is unknown ...
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
;
159 m_lastKeysym
= keysym
;
160 m_lastKeyTime
= CTimeUtils::GetFrameTime();
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
))
174 // Create and return a CKey
176 CKey
key(vkey
, unicode
, ascii
, modifiers
, held
);
181 void CKeyboardStat::ProcessKeyUp(void)
183 memset(&m_lastKeysym
, 0, sizeof(m_lastKeysym
));
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
)
194 XBMCKEYTABLE keytable
;
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
);
217 keyname
+= StringUtils::Format("%i", keyid
);
218 keyname
+= StringUtils::Format(" (0x%02x)", KeyID
);