summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorHonglei Zhang <honglei.zhang@nokia.com>2011-07-03 17:22:41 (GMT)
committerHonglei Zhang <honglei.zhang@nokia.com>2011-07-03 17:22:41 (GMT)
commit3b6a61953bcd319a6df55d66116ce92f7525ec00 (patch)
tree4642541a9ab510546b1bc77bd4c0790a8eaedfec /src/gui
parent2d930fdabccad6bfbbd0075610a302027c8d499b (diff)
downloadQt-3b6a61953bcd319a6df55d66116ce92f7525ec00.zip
Qt-3b6a61953bcd319a6df55d66116ce92f7525ec00.tar.gz
Qt-3b6a61953bcd319a6df55d66116ce92f7525ec00.tar.bz2
Enable key capture and RemCon interfaces for Qt apps on Symbian
The volume and other multimedia keys in Symbian are not delivered through the normal key events, but through a seperate API called CRemConCoreApiTarget. The commit implements the feature that multimedia key events are delivered via normal key events to Qt Application, if the Qt::AA_CaptureMultimediaKeys is defined. Task-number: QTBUG-4415 Reviewed-by: Sami Merila Reviewed-by: Miikka Heikkinen
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qkeymapper_p.h2
-rw-r--r--src/gui/kernel/qkeymapper_s60.cpp195
-rw-r--r--src/gui/s60framework/qs60keycapture.cpp308
-rw-r--r--src/gui/s60framework/qs60keycapture_p.h116
-rw-r--r--src/gui/s60framework/qs60mainappui.cpp17
-rw-r--r--src/gui/s60framework/s60framework.pri21
6 files changed, 568 insertions, 91 deletions
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index 2607c2a..1d624f9 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -213,6 +213,8 @@ public:
int mapS60ScanCodesToQt(TUint s60key);
int mapQtToS60Key(int qtKey);
int mapQtToS60ScanCodes(int qtKey);
+ int mapS60RemConIdToS60Key(int s60RemConId);
+ int mapS60RemConIdToS60ScanCodes(int s60RemConId);
void updateInputLanguage();
#endif
};
diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp
index 1113b77..2a7083e 100644
--- a/src/gui/kernel/qkeymapper_s60.cpp
+++ b/src/gui/kernel/qkeymapper_s60.cpp
@@ -87,97 +87,104 @@ QString QKeyMapperPrivate::translateKeyEvent(int keySym, Qt::KeyboardModifiers /
}
#include <e32keys.h>
+#include <remconcoreapi.h>
struct KeyMapping{
TKeyCode s60KeyCode;
TStdScanCode s60ScanCode;
+ TRemConCoreApiOperationId s60RemConId;
Qt::Key qtKey;
};
using namespace Qt;
+// key mapping table in the format of
+// {S60 key code, S60 scan code, S60 RemCon operation Id, Qt key code}
static const KeyMapping keyMapping[] = {
- {EKeyBackspace, EStdKeyBackspace, Key_Backspace},
- {EKeyTab, EStdKeyTab, Key_Tab},
- {EKeyEnter, EStdKeyEnter, Key_Enter},
- {EKeyEscape, EStdKeyEscape, Key_Escape},
- {EKeySpace, EStdKeySpace, Key_Space},
- {EKeyDelete, EStdKeyDelete, Key_Delete},
- {EKeyPrintScreen, EStdKeyPrintScreen, Key_SysReq},
- {EKeyPause, EStdKeyPause, Key_Pause},
- {EKeyHome, EStdKeyHome, Key_Home},
- {EKeyEnd, EStdKeyEnd, Key_End},
- {EKeyPageUp, EStdKeyPageUp, Key_PageUp},
- {EKeyPageDown, EStdKeyPageDown, Key_PageDown},
- {EKeyInsert, EStdKeyInsert, Key_Insert},
- {EKeyLeftArrow, EStdKeyLeftArrow, Key_Left},
- {EKeyRightArrow, EStdKeyRightArrow, Key_Right},
- {EKeyUpArrow, EStdKeyUpArrow, Key_Up},
- {EKeyDownArrow, EStdKeyDownArrow, Key_Down},
- {EKeyLeftShift, EStdKeyLeftShift, Key_Shift},
- {EKeyRightShift, EStdKeyRightShift, Key_Shift},
- {EKeyLeftAlt, EStdKeyLeftAlt, Key_Alt},
- {EKeyRightAlt, EStdKeyRightAlt, Key_AltGr},
- {EKeyLeftCtrl, EStdKeyLeftCtrl, Key_Control},
- {EKeyRightCtrl, EStdKeyRightCtrl, Key_Control},
- {EKeyLeftFunc, EStdKeyLeftFunc, Key_Super_L},
- {EKeyRightFunc, EStdKeyRightFunc, Key_Super_R},
- {EKeyCapsLock, EStdKeyCapsLock, Key_CapsLock},
- {EKeyNumLock, EStdKeyNumLock, Key_NumLock},
- {EKeyScrollLock, EStdKeyScrollLock, Key_ScrollLock},
- {EKeyF1, EStdKeyF1, Key_F1},
- {EKeyF2, EStdKeyF2, Key_F2},
- {EKeyF3, EStdKeyF3, Key_F3},
- {EKeyF4, EStdKeyF4, Key_F4},
- {EKeyF5, EStdKeyF5, Key_F5},
- {EKeyF6, EStdKeyF6, Key_F6},
- {EKeyF7, EStdKeyF7, Key_F7},
- {EKeyF8, EStdKeyF8, Key_F8},
- {EKeyF9, EStdKeyF9, Key_F9},
- {EKeyF10, EStdKeyF10, Key_F10},
- {EKeyF11, EStdKeyF11, Key_F11},
- {EKeyF12, EStdKeyF12, Key_F12},
- {EKeyF13, EStdKeyF13, Key_F13},
- {EKeyF14, EStdKeyF14, Key_F14},
- {EKeyF15, EStdKeyF15, Key_F15},
- {EKeyF16, EStdKeyF16, Key_F16},
- {EKeyF17, EStdKeyF17, Key_F17},
- {EKeyF18, EStdKeyF18, Key_F18},
- {EKeyF19, EStdKeyF19, Key_F19},
- {EKeyF20, EStdKeyF20, Key_F20},
- {EKeyF21, EStdKeyF21, Key_F21},
- {EKeyF22, EStdKeyF22, Key_F22},
- {EKeyF23, EStdKeyF23, Key_F23},
- {EKeyF24, EStdKeyF24, Key_F24},
- {EKeyOff, EStdKeyOff, Key_PowerOff},
-// {EKeyMenu, EStdKeyMenu, Key_Menu}, // Menu is EKeyApplication0
- {EKeyHelp, EStdKeyHelp, Key_Help},
- {EKeyDial, EStdKeyDial, Key_Call},
- {EKeyIncVolume, EStdKeyIncVolume, Key_VolumeUp},
- {EKeyDecVolume, EStdKeyDecVolume, Key_VolumeDown},
- {EKeyDevice0, EStdKeyDevice0, Key_Context1}, // Found by manual testing.
- {EKeyDevice1, EStdKeyDevice1, Key_Context2}, // Found by manual testing.
- {EKeyDevice3, EStdKeyDevice3, Key_Select},
- {EKeyDevice7, EStdKeyDevice7, Key_Camera},
- {EKeyApplication0, EStdKeyApplication0, Key_Menu}, // Found by manual testing.
- {EKeyApplication1, EStdKeyApplication1, Key_Launch1}, // Found by manual testing.
- {EKeyApplication2, EStdKeyApplication2, Key_MediaPlay}, // Found by manual testing.
- {EKeyApplication3, EStdKeyApplication3, Key_MediaStop}, // Found by manual testing.
- {EKeyApplication4, EStdKeyApplication4, Key_MediaNext}, // Found by manual testing.
- {EKeyApplication5, EStdKeyApplication5, Key_MediaPrevious}, // Found by manual testing.
- {EKeyApplication6, EStdKeyApplication6, Key_Launch6},
- {EKeyApplication7, EStdKeyApplication7, Key_Launch7},
- {EKeyApplication8, EStdKeyApplication8, Key_Launch8},
- {EKeyApplication9, EStdKeyApplication9, Key_Launch9},
- {EKeyApplicationA, EStdKeyApplicationA, Key_LaunchA},
- {EKeyApplicationB, EStdKeyApplicationB, Key_LaunchB},
- {EKeyApplicationC, EStdKeyApplicationC, Key_LaunchC},
- {EKeyApplicationD, EStdKeyApplicationD, Key_LaunchD},
- {EKeyApplicationE, EStdKeyApplicationE, Key_LaunchE},
- {EKeyApplicationF, EStdKeyApplicationF, Key_LaunchF},
- {EKeyApplication19, EStdKeyApplication19, Key_CameraFocus},
- {EKeyYes, EStdKeyYes, Key_Yes},
- {EKeyNo, EStdKeyNo, Key_No},
- {TKeyCode(0), TStdScanCode(0), Qt::Key(0)}
+ {EKeyBackspace, EStdKeyBackspace, ENop, Key_Backspace},
+ {EKeyTab, EStdKeyTab, ENop, Key_Tab},
+ {EKeyEnter, EStdKeyEnter, ERemConCoreApiEnter, Key_Enter},
+ {EKeyEscape, EStdKeyEscape, ENop, Key_Escape},
+ {EKeySpace, EStdKeySpace, ENop, Key_Space},
+ {EKeyDelete, EStdKeyDelete, ENop, Key_Delete},
+ {EKeyPrintScreen, EStdKeyPrintScreen, ENop, Key_SysReq},
+ {EKeyPause, EStdKeyPause, ENop, Key_Pause},
+ {EKeyHome, EStdKeyHome, ENop, Key_Home},
+ {EKeyEnd, EStdKeyEnd, ENop, Key_End},
+ {EKeyPageUp, EStdKeyPageUp, ERemConCoreApiPageUp, Key_PageUp},
+ {EKeyPageDown, EStdKeyPageDown, ERemConCoreApiPageDown, Key_PageDown},
+ {EKeyInsert, EStdKeyInsert, ENop, Key_Insert},
+ {EKeyLeftArrow, EStdKeyLeftArrow, ERemConCoreApiLeft, Key_Left},
+ {EKeyRightArrow, EStdKeyRightArrow, ERemConCoreApiRight, Key_Right},
+ {EKeyUpArrow, EStdKeyUpArrow, ERemConCoreApiUp, Key_Up},
+ {EKeyDownArrow, EStdKeyDownArrow, ERemConCoreApiDown, Key_Down},
+ {EKeyLeftShift, EStdKeyLeftShift, ENop, Key_Shift},
+ {EKeyRightShift, EStdKeyRightShift, ENop, Key_Shift},
+ {EKeyLeftAlt, EStdKeyLeftAlt, ENop, Key_Alt},
+ {EKeyRightAlt, EStdKeyRightAlt, ENop, Key_AltGr},
+ {EKeyLeftCtrl, EStdKeyLeftCtrl, ENop, Key_Control},
+ {EKeyRightCtrl, EStdKeyRightCtrl, ENop, Key_Control},
+ {EKeyLeftFunc, EStdKeyLeftFunc, ENop, Key_Super_L},
+ {EKeyRightFunc, EStdKeyRightFunc, ENop, Key_Super_R},
+ {EKeyCapsLock, EStdKeyCapsLock, ENop, Key_CapsLock},
+ {EKeyNumLock, EStdKeyNumLock, ENop, Key_NumLock},
+ {EKeyScrollLock, EStdKeyScrollLock, ENop, Key_ScrollLock},
+ {EKeyF1, EStdKeyF1, ERemConCoreApiF1, Key_F1},
+ {EKeyF2, EStdKeyF2, ERemConCoreApiF2, Key_F2},
+ {EKeyF3, EStdKeyF3, ERemConCoreApiF3, Key_F3},
+ {EKeyF4, EStdKeyF4, ERemConCoreApiF4, Key_F4},
+ {EKeyF5, EStdKeyF5, ERemConCoreApiF5, Key_F5},
+ {EKeyF6, EStdKeyF6, ENop, Key_F6},
+ {EKeyF7, EStdKeyF7, ENop, Key_F7},
+ {EKeyF8, EStdKeyF8, ENop, Key_F8},
+ {EKeyF9, EStdKeyF9, ENop, Key_F9},
+ {EKeyF10, EStdKeyF10, ENop, Key_F10},
+ {EKeyF11, EStdKeyF11, ENop, Key_F11},
+ {EKeyF12, EStdKeyF12, ENop, Key_F12},
+ {EKeyF13, EStdKeyF13, ENop, Key_F13},
+ {EKeyF14, EStdKeyF14, ENop, Key_F14},
+ {EKeyF15, EStdKeyF15, ENop, Key_F15},
+ {EKeyF16, EStdKeyF16, ENop, Key_F16},
+ {EKeyF17, EStdKeyF17, ENop, Key_F17},
+ {EKeyF18, EStdKeyF18, ENop, Key_F18},
+ {EKeyF19, EStdKeyF19, ENop, Key_F19},
+ {EKeyF20, EStdKeyF20, ENop, Key_F20},
+ {EKeyF21, EStdKeyF21, ENop, Key_F21},
+ {EKeyF22, EStdKeyF22, ENop, Key_F22},
+ {EKeyF23, EStdKeyF23, ENop, Key_F23},
+ {EKeyF24, EStdKeyF24, ENop, Key_F24},
+ {EKeyOff, EStdKeyOff, ENop, Key_PowerOff},
+// {EKeyMenu, EStdKeyMenu, ENop, Key_Menu}, // Menu is EKeyApplication0
+ {EKeyHelp, EStdKeyHelp, ERemConCoreApiHelp, Key_Help},
+ {EKeyDial, EStdKeyDial, ENop, Key_Call},
+ {EKeyIncVolume, EStdKeyIncVolume, ERemConCoreApiVolumeUp, Key_VolumeUp},
+ {EKeyDecVolume, EStdKeyDecVolume, ERemConCoreApiVolumeDown, Key_VolumeDown},
+ {EKeyDevice0, EStdKeyDevice0, ENop, Key_Context1}, // Found by manual testing.
+ {EKeyDevice1, EStdKeyDevice1, ENop, Key_Context2}, // Found by manual testing.
+ {EKeyDevice3, EStdKeyDevice3, ERemConCoreApiSelect, Key_Select},
+ {EKeyDevice7, EStdKeyDevice7, ENop, Key_Camera},
+ {EKeyApplication0, EStdKeyApplication0, ENop, Key_Menu}, // Found by manual testing.
+ {EKeyApplication1, EStdKeyApplication1, ENop, Key_Launch1}, // Found by manual testing.
+ {EKeyApplication2, EStdKeyApplication2, ERemConCoreApiPlay, Key_MediaPlay}, // Found by manual testing.
+ {EKeyApplication3, EStdKeyApplication3, ERemConCoreApiStop, Key_MediaStop}, // Found by manual testing.
+ {EKeyApplication4, EStdKeyApplication4, ERemConCoreApiForward, Key_MediaNext}, // Found by manual testing.
+ {EKeyApplication5, EStdKeyApplication5, ERemConCoreApiBackward, Key_MediaPrevious}, // Found by manual testing.
+ {EKeyApplication6, EStdKeyApplication6, ENop, Key_Launch6},
+ {EKeyApplication7, EStdKeyApplication7, ENop, Key_Launch7},
+ {EKeyApplication8, EStdKeyApplication8, ENop, Key_Launch8},
+ {EKeyApplication9, EStdKeyApplication9, ENop, Key_Launch9},
+ {EKeyApplicationA, EStdKeyApplicationA, ENop, Key_LaunchA},
+ {EKeyApplicationB, EStdKeyApplicationB, ENop, Key_LaunchB},
+ {EKeyApplicationC, EStdKeyApplicationC, ENop, Key_LaunchC},
+ {EKeyApplicationD, EStdKeyApplicationD, ENop, Key_LaunchD},
+ {EKeyApplicationE, EStdKeyApplicationE, ENop, Key_LaunchE},
+ {EKeyApplicationF, EStdKeyApplicationF, ENop, Key_LaunchF},
+ {EKeyApplication19, EStdKeyApplication19, ENop, Key_CameraFocus},
+ {EKeyYes, EStdKeyYes, ENop, Key_Yes},
+ {EKeyNo, EStdKeyNo, ENop, Key_No},
+ {EKeyDevice20, EStdKeyDevice20, ERemConCoreApiPausePlayFunction, Key_MediaTogglePlayPause},
+ {EKeyDevice21, EStdKeyDevice21, ERemConCoreApiRewind, Key_AudioRewind},
+ {EKeyDevice22, EStdKeyDevice22, ERemConCoreApiFastForward, Key_AudioForward},
+ {TKeyCode(0), TStdScanCode(0), ENop, Qt::Key(0)}
};
int QKeyMapperPrivate::mapS60KeyToQt(TUint s60key)
@@ -228,6 +235,30 @@ int QKeyMapperPrivate::mapQtToS60ScanCodes(int qtKey)
return res;
}
+int QKeyMapperPrivate::mapS60RemConIdToS60Key(int s60RemConId)
+{
+ int res = KErrUnknown;
+ for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) {
+ if (keyMapping[i].s60RemConId == s60RemConId) {
+ res = keyMapping[i].s60KeyCode;
+ break;
+ }
+ }
+ return res;
+}
+
+int QKeyMapperPrivate::mapS60RemConIdToS60ScanCodes(int s60RemConId)
+{
+ int res = KErrUnknown;
+ for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) {
+ if (keyMapping[i].s60RemConId == s60RemConId) {
+ res = keyMapping[i].s60ScanCode;
+ break;
+ }
+ }
+ return res;
+}
+
void QKeyMapperPrivate::updateInputLanguage()
{
#ifdef Q_WS_S60
diff --git a/src/gui/s60framework/qs60keycapture.cpp b/src/gui/s60framework/qs60keycapture.cpp
new file mode 100644
index 0000000..db4cc0e
--- /dev/null
+++ b/src/gui/s60framework/qs60keycapture.cpp
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <remconinterfaceselector.h>
+#include <remconcoreapitarget.h>
+#include <coemain.h>
+#include "qkeymapper_p.h"
+#include "qs60keycapture_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Helper class for sending key handling responses to RemCon.
+*/
+class CResponseHandler : public CActive
+{
+public:
+ static CResponseHandler *NewL(CRemConCoreApiTarget &remConCoreApiTarget);
+ virtual ~CResponseHandler();
+ void CompleteAnyKey(TRemConCoreApiOperationId operationId);
+
+private:
+ CResponseHandler(CRemConCoreApiTarget &remConCoreApiTarget);
+
+ void RunL();
+ void DoCancel();
+
+private:
+ RArray<TRemConCoreApiOperationId> iResponseArray;
+ CRemConCoreApiTarget &iRemConCoreApiTarget;
+};
+
+CResponseHandler::CResponseHandler(CRemConCoreApiTarget &remConCoreApiTarget)
+ : CActive(CActive::EPriorityStandard),
+ iRemConCoreApiTarget(remConCoreApiTarget)
+{
+ CActiveScheduler::Add(this);
+}
+
+CResponseHandler *CResponseHandler::NewL(CRemConCoreApiTarget &remConCoreApiTarget)
+{
+ CResponseHandler *self =
+ new (ELeave) CResponseHandler(remConCoreApiTarget);
+ return self;
+}
+
+CResponseHandler::~CResponseHandler()
+{
+ Cancel();
+ iResponseArray.Close();
+}
+
+void CResponseHandler::CompleteAnyKey(TRemConCoreApiOperationId operationId)
+{
+ if (!IsActive()) {
+ TInt error = KErrNone;
+ iRemConCoreApiTarget.SendResponse(iStatus, operationId, error);
+ SetActive();
+ } else {
+ // already active. Append to array and complete later.
+ iResponseArray.Append(operationId);
+ }
+}
+
+void CResponseHandler::DoCancel()
+{
+ iRemConCoreApiTarget.Cancel();
+}
+
+void CResponseHandler::RunL()
+{
+ // if any existing -> Send response
+ if (iResponseArray.Count()) {
+ CompleteAnyKey(iResponseArray[0]);
+ // Remove already completed key
+ iResponseArray.Remove(0);
+ iResponseArray.Compress();
+ }
+}
+
+
+/*
+ * QS60KeyCapture provides media key handling using services from RemCon.
+ */
+QS60KeyCapture::QS60KeyCapture(CCoeEnv *env, QObject *parent):
+ QObject(parent), coeEnv(env), selector(0), target(0), handler(0)
+{
+ initRemCon();
+
+ TTimeIntervalMicroSeconds32 initialTime;
+ TTimeIntervalMicroSeconds32 time;
+ coeEnv->WsSession().GetKeyboardRepeatRate(initialTime, time);
+ initialRepeatTime = (initialTime.Int() / 1000); // msecs
+ repeatTime = (time.Int() / 1000); // msecs
+
+ int clickTimeout = initialRepeatTime + repeatTime;
+
+ volumeUpClickTimer.setSingleShot(true);
+ volumeDownClickTimer.setSingleShot(true);
+ repeatTimer.setSingleShot(true);
+
+ volumeUpClickTimer.setInterval(clickTimeout);
+ volumeDownClickTimer.setInterval(clickTimeout);
+ repeatTimer.setInterval(initialRepeatTime);
+
+ connect(&volumeUpClickTimer, SIGNAL(timeout()), this, SLOT(volumeUpClickTimerExpired()));
+ connect(&volumeDownClickTimer, SIGNAL(timeout()), this, SLOT(volumeDownClickTimerExpired()));
+ connect(&repeatTimer, SIGNAL(timeout()), this, SLOT(repeatTimerExpired()));
+}
+
+/*
+ * Initializes RemCon connection for receiving key events
+ */
+void QS60KeyCapture::initRemCon()
+{
+ try {
+ QT_TRAP_THROWING(
+ selector = CRemConInterfaceSelector::NewL();
+ target = CRemConCoreApiTarget::NewL(*selector, *this);
+ handler = CResponseHandler::NewL(*target);
+ selector->OpenTargetL());
+ } catch (const std::exception &e) {
+ delete handler;
+ delete selector;
+ selector = 0;
+ target = 0;
+ handler = 0;
+ }
+}
+
+QS60KeyCapture::~QS60KeyCapture()
+{
+ delete handler;
+ delete selector;
+}
+
+void QS60KeyCapture::MrccatoCommand(TRemConCoreApiOperationId operationId,
+ TRemConCoreApiButtonAction buttonAction)
+{
+ if (!target)
+ return;
+
+ switch (operationId) {
+ // Volume up/down keys auto repeat if user hold the key long enough
+ case ERemConCoreApiVolumeUp:
+ case ERemConCoreApiVolumeDown:
+ {
+ // Side key events are sent using following scheme:
+ // - ButtonClick is sent first
+ // - if nothing happens before repeat timer expires, no further events are generated
+ // - if user holds the button longer, ButtonPress is sent and
+ // when button is finally released ButtonRelease is sent.
+
+ QTimer &timer = (operationId == ERemConCoreApiVolumeUp) ? volumeUpClickTimer : volumeDownClickTimer;
+
+ switch (buttonAction) {
+ case ERemConCoreApiButtonPress:
+ if (timer.isActive()) {
+ timer.stop();
+ // force repeat event
+ repeatKeyEvent = mapToKeyEvent(operationId);
+ repeatTimerExpired();
+ } else {
+ sendKey(operationId, QEvent::KeyPress);
+ repeatTimer.start(initialRepeatTime);
+ }
+ break;
+ case ERemConCoreApiButtonRelease:
+ timer.stop();
+ sendKey(operationId, QEvent::KeyRelease);
+ repeatTimer.stop();
+ break;
+ case ERemConCoreApiButtonClick:
+ if (timer.isActive()) {
+ timer.stop();
+ sendKey(operationId, QEvent::KeyRelease);
+ }
+ sendKey(operationId, QEvent::KeyPress);
+ timer.start();
+ repeatTimer.stop();
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ switch (buttonAction) {
+ case ERemConCoreApiButtonPress:
+ sendKey(operationId, QEvent::KeyPress);
+ repeatTimer.start(initialRepeatTime);
+ break;
+ case ERemConCoreApiButtonRelease:
+ sendKey(operationId, QEvent::KeyRelease);
+ repeatTimer.stop();
+ break;
+ case ERemConCoreApiButtonClick:
+ sendKey(operationId, QEvent::KeyPress);
+ sendKey(operationId, QEvent::KeyRelease);
+ repeatTimer.stop();
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (handler)
+ handler->CompleteAnyKey(operationId);
+}
+
+/*
+ * Sends volume up KeyRelease event
+ */
+void QS60KeyCapture::volumeUpClickTimerExpired()
+{
+ sendKey(ERemConCoreApiVolumeUp, QEvent::KeyRelease);
+}
+
+/*
+ * Sends volume down KeyRelease event
+ */
+void QS60KeyCapture::volumeDownClickTimerExpired()
+{
+ sendKey(ERemConCoreApiVolumeDown, QEvent::KeyRelease);
+}
+
+/*
+ * Repeats last key event
+ */
+void QS60KeyCapture::repeatTimerExpired()
+{
+ // set auto repeat flag on
+ repeatKeyEvent.iRepeats = 1;
+ coeEnv->SimulateKeyEventL(repeatKeyEvent, EEventKey);
+ repeatTimer.start(repeatTime);
+}
+
+/*
+ * Maps RemCon operation id to key event (includes key code and scan codes)
+ */
+TKeyEvent QS60KeyCapture::mapToKeyEvent(TRemConCoreApiOperationId operationId)
+{
+ TKeyEvent keyEvent;
+ keyEvent.iModifiers = 0;
+ keyEvent.iRepeats = 0;
+ keyEvent.iCode = qt_keymapper_private()->mapS60RemConIdToS60Key(operationId);
+ keyEvent.iScanCode = qt_keymapper_private()->mapS60RemConIdToS60ScanCodes(operationId);
+ return keyEvent;
+}
+
+/*
+ * Delivers key events to the application.
+ * RemCon operations are converted to simulated key events
+ */
+void QS60KeyCapture::sendKey(TRemConCoreApiOperationId operationId, QEvent::Type type)
+{
+ TKeyEvent keyEvent = mapToKeyEvent(operationId);
+
+ if (type == QEvent::KeyPress) {
+ coeEnv->SimulateKeyEventL(keyEvent, EEventKeyDown);
+ coeEnv->SimulateKeyEventL(keyEvent, EEventKey);
+ // save the key press event for repeats
+ repeatKeyEvent = keyEvent;
+ } else {
+ coeEnv->SimulateKeyEventL(keyEvent, EEventKeyUp);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/s60framework/qs60keycapture_p.h b/src/gui/s60framework/qs60keycapture_p.h
new file mode 100644
index 0000000..41cb765
--- /dev/null
+++ b/src/gui/s60framework/qs60keycapture_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QS60KEYCAPTURE_P_H
+#define QS60KEYCAPTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_SYMBIAN
+
+#include <QObject>
+#include <QEvent>
+#include <QTimer>
+#include <remconcoreapitargetobserver.h>
+#include <w32std.h>
+
+class CRemConInterfaceSelector;
+class CRemConCoreApiTarget;
+class CResponseHandler;
+class CCoeEnv;
+
+QT_BEGIN_NAMESPACE
+
+class QS60KeyCapture: public QObject,
+ public MRemConCoreApiTargetObserver
+{
+ Q_OBJECT
+public:
+ QS60KeyCapture(CCoeEnv *env, QObject *parent = 0);
+ ~QS60KeyCapture();
+
+ void MrccatoCommand(TRemConCoreApiOperationId operationId,
+ TRemConCoreApiButtonAction buttonAct);
+
+private slots:
+ void volumeUpClickTimerExpired();
+ void volumeDownClickTimerExpired();
+ void repeatTimerExpired();
+
+private:
+ void sendKey(TRemConCoreApiOperationId operationId, QEvent::Type type);
+ TKeyEvent mapToKeyEvent(TRemConCoreApiOperationId operationId);
+ void initRemCon();
+
+private:
+ QS60KeyCapture();
+ Q_DISABLE_COPY(QS60KeyCapture)
+
+ CCoeEnv *coeEnv;
+
+ CRemConInterfaceSelector *selector;
+ CRemConCoreApiTarget *target;
+ CResponseHandler *handler;
+
+ QTimer volumeUpClickTimer;
+ QTimer volumeDownClickTimer;
+
+ TKeyEvent repeatKeyEvent;
+ int initialRepeatTime; // time before first repeat key event
+ int repeatTime; // time between subsequent repeat key events
+ QTimer repeatTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_SYMBIAN
+#endif // QS60KEYCAPTURE_P_H
diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp
index bfd1825..f120287 100644
--- a/src/gui/s60framework/qs60mainappui.cpp
+++ b/src/gui/s60framework/qs60mainappui.cpp
@@ -59,6 +59,7 @@
#include <private/qmenu_p.h>
#include <private/qt_s60_p.h>
#include <qdebug.h>
+#include "qs60keycapture_p.h"
//Animated wallpapers in Qt applications are not supported.
const TInt KAknDisableAnimationBackground = 0x02000000;
@@ -66,6 +67,20 @@ const TInt KAknSingleClickCompatible = 0x01000000;
QT_BEGIN_NAMESPACE
+static QS60KeyCapture *qt_S60KeyCapture = 0;
+
+static void installS60KeyCapture(CCoeEnv *env)
+{
+ if (QApplication::testAttribute(Qt::AA_CaptureMultimediaKeys))
+ qt_S60KeyCapture = new QS60KeyCapture(env);
+}
+
+static void removeS60KeyCapture()
+{
+ delete qt_S60KeyCapture;
+ qt_S60KeyCapture = 0;
+}
+
/*!
\class QS60MainAppUi
\since 4.6
@@ -127,6 +142,7 @@ void QS60MainAppUi::ConstructL()
}
#endif
BaseConstructL(flags);
+ installS60KeyCapture(iCoeEnv);
}
/*!
@@ -142,6 +158,7 @@ QS60MainAppUi::QS60MainAppUi()
*/
QS60MainAppUi::~QS60MainAppUi()
{
+ removeS60KeyCapture();
}
/*!
diff --git a/src/gui/s60framework/s60framework.pri b/src/gui/s60framework/s60framework.pri
index 19525b7..e30d2c0 100644
--- a/src/gui/s60framework/s60framework.pri
+++ b/src/gui/s60framework/s60framework.pri
@@ -1,10 +1,13 @@
SOURCES += s60framework/qs60mainapplication.cpp \
- s60framework/qs60mainappui.cpp \
- s60framework/qs60maindocument.cpp
-
-HEADERS += s60framework/qs60mainapplication_p.h \
- s60framework/qs60mainapplication.h \
- s60framework/qs60mainappui.h \
- s60framework/qs60maindocument.h
-
-!isEmpty(QT_LIBINFIX): DEFINES += QT_LIBINFIX_UNQUOTED=$$QT_LIBINFIX \ No newline at end of file
+ s60framework/qs60mainappui.cpp \
+ s60framework/qs60maindocument.cpp \
+ s60framework/qs60keycapture.cpp
+HEADERS += qs60keycapture_p.h \
+ s60framework/qs60mainapplication_p.h \
+ s60framework/qs60mainapplication.h \
+ s60framework/qs60mainappui.h \
+ s60framework/qs60maindocument.h \
+ s60framework/qs60keycapture_p.h
+LIBS += -lremconcoreapi \
+ -lremconinterfacebase
+!isEmpty(QT_LIBINFIX):DEFINES += QT_LIBINFIX_UNQUOTED=$$QT_LIBINFIX