diff -r 000000000000 -r f63038272f30 bluetoothengine/bthid/manager/src/decode.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothengine/bthid/manager/src/decode.cpp Mon Jan 18 20:28:57 2010 +0200 @@ -0,0 +1,265 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This is the implementation of application class +* +*/ + + +#include +#include +#include +#include "modifier.h" +#include "layout.h" +#include "decode.h" +#include "codestore.h" +#include "client.h" +#include "debug.h" +#include "hidvalues.h" + +// ---------------------------------------------------------------------- + +CKeyboardDecoder::CKeyboardDecoder() + : iLayout(0), iAltGrSequence(EFalse), iNumKeysDown(0) + { + TRACE_INFO( ( + _L("[HID]\tCKeyboardDecoder::CKeyboardDecoder at 0x%08x"), this)); + } + +CKeyboardDecoder* CKeyboardDecoder::NewL() + { + CKeyboardDecoder* self = + new (ELeave) CKeyboardDecoder; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +void CKeyboardDecoder::ConstructL() + { + iScanCodes = CScanCodeStore::NewL(); + } + +CKeyboardDecoder::~CKeyboardDecoder() + { + TRACE_INFO( (_L("[HID]\t~CKeyboardDecoder() 0x%08x"), this)); + + iLayout = 0; // (we don't own iLayout) + + delete iScanCodes; + } + +// ---------------------------------------------------------------------- + +void CKeyboardDecoder::Event(const TKeyEventInfo &aEvent, + TDecodedKeyInfo& aDecodedKeys) + { + aDecodedKeys.iCount = 0; + aDecodedKeys.iScanCode = EStdKeyNull; + + iNumKeysDown += (aEvent.iIsKeyDown ? 1 : -1); + // (NB. it is possible to get an up without a down just after a new + // decoder goes into use when the keyboard layout is changed -- but + // only if the Bluetooth keyboard is used to make the layout change.) + if (iNumKeysDown < 0) + iNumKeysDown = 0; + + if (iLayout) + { + if (!HandleRightAlt(aEvent, aDecodedKeys)) + { + if (aEvent.iIsKeyDown) + { + // Key down event: + + TInt rawCode = iLayout->RawScanCode(aEvent.iHidKey, + aEvent.iUsagePage, aEvent.iModifiers); + + // Store the raw scan code, so that the scan code for + // the "key up" event for this key will match the one + // sent for the "key down" event. These could be + // different, for example, if the scan code changes + // depending on the current modifier state. + // + if (iScanCodes->Store(aEvent.iHidKey, aEvent.iUsagePage, + rawCode) == KErrNone) + { + aDecodedKeys.iScanCode = rawCode; + } + else + { + // Store() may fail due to low memory. In that + // case we don't send key down (or key up) events: + // + aDecodedKeys.iScanCode = EStdKeyNull; + } + + // Decode any key press events: + + TUint16 unicodeKey = iLayout->TranslateKey(aEvent.iHidKey, + aEvent.iUsagePage, aEvent.iModifiers, aEvent.iLockKeys); + + if (unicodeKey != 0) + { + ProcessDeadKeys(unicodeKey, aEvent.iHidKey, + aEvent.iUsagePage, aDecodedKeys); + } + } + else + { + // Key up event: + + aDecodedKeys.iScanCode = + iScanCodes->Retrieve(aEvent.iHidKey, aEvent.iUsagePage); + } + } + } + } + +// ---------------------------------------------------------------------- + +TBool CKeyboardDecoder::HandleRightAlt(const TKeyEventInfo &aEvent, + TDecodedKeyInfo& aDecodedKeys) + { + // A press and release of the right-alt (Alt Gr) key should cause + // the S60 symbol selection dialog to appear, if no other keys are + // pressed in between. + + TBool handledEvent = EFalse; + + const TInt KRightAltKey = 0xe6; + + if ((aEvent.iHidKey == KRightAltKey) && + (aEvent.iUsagePage == EUsagePageKeyboard)) + { + if (aEvent.iIsKeyDown && (iNumKeysDown == 1)) + { + iAltGrSequence = ETrue; + } + + if (!aEvent.iIsKeyDown && iAltGrSequence) + { + // We use EKeyApplication2 to indicate to the modified T9 + // FEP that we wish it to produce the symbol selection dialog: + // EKeyApplication2 is not passed to Fep anymore, but + // it is converted to '*' in SendKeyPress() (keyboard.cpp) + aDecodedKeys.iEvent[0] = TTranslatedKey(EKeyApplication2, + EStdKeyApplication2, 0, 0, EFalse); + aDecodedKeys.iCount = 1; + + handledEvent = ETrue; + iAltGrSequence = EFalse; + } + } + else + { + iAltGrSequence = EFalse; + } + + return handledEvent; + } + +// ---------------------------------------------------------------------- + +void CKeyboardDecoder::Reset() + { + iDeadKey.iUnicode = 0; + iAltGrSequence = EFalse; + iNumKeysDown = 0; + } + +// ---------------------------------------------------------------------- + +void CKeyboardDecoder::SetLayout(CKeyboardLayout* aLayout) + { + TRACE_INFO( (_L("[HID]\tCKeyboardDecoder::SetLayout(0x%08x)"), aLayout)); + + iLayout = aLayout; + Reset(); + } + +// ---------------------------------------------------------------------- + +void CKeyboardDecoder::ProcessDeadKeys(TUint16 aUnicodeKey, + TInt aHidKey, TInt aUsagePage, TDecodedKeyInfo &aDecodedKeys) + { + if (iDeadKey.iUnicode == 0) + { + // Check if the current key is a dead key: + // + if (iLayout->IsDeadKey(aUnicodeKey)) + { + // We've received a dead key event, so there's no key press + // to issue -- just record the details for later: + // + TRACE_INFO( (_L("[HID]\tDeadkey 0x%04x (%d:%d)"), + aUnicodeKey, aUsagePage, aHidKey)); + + iDeadKey = TTranslatedKey(aUnicodeKey, + aDecodedKeys.iScanCode, aHidKey, aUsagePage, EFalse); + aDecodedKeys.iCount = 0; + } + else + { + // No dead key processing to do, so just send a + // normal key code: + // + TRACE_INFO( (_L("[HID]\tNo dead key processing, one event"))); + + aDecodedKeys.iEvent[0] = TTranslatedKey(aUnicodeKey, + aDecodedKeys.iScanCode, aHidKey, aUsagePage, + iLayout->IsRepeatingKey(aUnicodeKey)); + aDecodedKeys.iCount = 1; + } + } + else + { + // We've an active dead key, see if the current key produces + // a combination character: + // + TUint16 comboChar = + iLayout->FindCombiningChar(iDeadKey.iUnicode, aUnicodeKey); + + if (comboChar == 0) + { + TRACE_INFO( (_L("[HID]\tNo match for 0x%04x, sending after 0x%04x"), + aUnicodeKey, iDeadKey.iUnicode)); + + // No match, so two key events to send: + + aDecodedKeys.iEvent[0] = iDeadKey; + aDecodedKeys.iEvent[1] = TTranslatedKey(aUnicodeKey, + aDecodedKeys.iScanCode, aHidKey, aUsagePage, + iLayout->IsRepeatingKey(aUnicodeKey)); + aDecodedKeys.iCount = 2; + } + else + { + TRACE_INFO( (_L("[HID]\tFound a match 0x%04x, one combo to send 0x%04x"), + aUnicodeKey, comboChar)); + + // Found a match, so one combo key event to send: + + aDecodedKeys.iEvent[0] = TTranslatedKey(comboChar, + aDecodedKeys.iScanCode, aHidKey, aUsagePage, + iLayout->IsRepeatingKey(comboChar)); + aDecodedKeys.iCount = 1; + } + + // We've finished processing the dead key sequence: + iDeadKey.iUnicode = 0; + } + } + +// ----------------------------------------------------------------------