diff -r da10798406fc -r 8dc858aede52 libraries/iosrv/client/command_base.cpp --- a/libraries/iosrv/client/command_base.cpp Wed Aug 25 22:23:26 2010 +0100 +++ b/libraries/iosrv/client/command_base.cpp Sat Aug 28 00:14:27 2010 +0100 @@ -14,7 +14,7 @@ #include "ioutils.h" #include "command_base.h" #include - +#include // for definition of CTRL() using namespace IoUtils; #define RETURN_IF_ERROR(x) {TInt _err = (x); if (_err<0) return _err;} @@ -1523,10 +1523,15 @@ TUint privateFlags = (iFlags & KPrivateFlagsMask); iFlags = (aFlags & KPublicFlagsMask); iFlags |= privateFlags; + // Make sure implied flags are set if (iFlags & ECompleteOnRunL) { iFlags |= EManualComplete; } + if (iFlags & ECaptureCtrlC) + { + iFlags |= ENotifyKeypresses; + } } EXPORT_C void CCommandBase::SetCif(const CCommandInfoFile& aCif) @@ -1588,6 +1593,17 @@ UpdateHandlesL(); } + if (iFlags & ENotifyKeypresses) + { + __ASSERT_ALWAYS(iExtension && iExtension->ExtensionVersion() >= ECommandExtensionV2, IoUtils::Panic(EENotifyKeypressesSpecifiedWithoutExtensionBeingSet)); + iKeypressWatcher = new(ELeave) CKeypressWatcher(*static_cast(iExtension), Stdin()); + if (iFlags & ECaptureCtrlC) + { + User::LeaveIfError(Stdin().CaptureKey(CTRL('c'), 0, 0)); + } + iKeypressWatcher->Notify(); + } + TBool deleted(EFalse); iDeleted = &deleted; // Note, commands that manually complete may call CCommandBase::Complete from their DoRunL, which in the case @@ -1626,7 +1642,7 @@ } EXPORT_C CCommandBase::CCommandBase(TUint aFlags) - : CActive(CActive::EPriorityStandard), iFlags(aFlags) + : CActive(CActive::EPriorityStandard) { CActiveScheduler::Add(this); if (Dll::Tls() == NULL) @@ -1635,14 +1651,15 @@ iFlags |= ETlsSet; } - // Ensure EManualComplete is set if ECompleteOnRunL is. - SetFlags(Flags()); + // Don't initialise iFlags directly - SetFlags checks that private flags aren't being set + SetFlags(aFlags); } EXPORT_C CCommandBase::~CCommandBase() { delete iReadChangeNotifier; delete iCompleter; + delete iKeypressWatcher; iFs.Close(); if (iFlags & EOwnsHandles) { @@ -1781,6 +1798,15 @@ iStdout.Write(aData); // Ignore error. } +EXPORT_C TUint CCommandBase::ReadKey() + { + // Make sure keypresswatcher doesn't get in the way (some commands do some synchronous ReadKeys followed by use of async ENotifyKeypresses callbacks) + if (iKeypressWatcher) iKeypressWatcher->Cancel(); + TUint result = iStdin.ReadKey(); + if (iKeypressWatcher) iKeypressWatcher->Notify(); + return result; + } + EXPORT_C void CCommandBase::Printf(TRefByValue aFmt, ...) { VA_LIST list; @@ -3538,7 +3564,7 @@ // This makes them attached to the same I/O end-points (consoles, files, etc) // as the passed in handles. User::LeaveIfError(iStdin.Duplicate(aStdin)); - User::LeaveIfError(iStdin.SetToForeground()); + // iStdin.SetToForeground() moved to Run() so the child doesn't steal foreground until it actually runs User::LeaveIfError(iStdout.Duplicate(aStdout)); User::LeaveIfError(iStderr.Duplicate(aStderr)); @@ -3579,6 +3605,7 @@ EXPORT_C void RChildProcess::Run(TRequestStatus& aStatus) { + iStdin.SetToForeground(); iProcess.Logon(aStatus); if (aStatus != KRequestPending) { @@ -3808,8 +3835,46 @@ iReadHandle.CancelNotifyChange(); } +// +// CKeypressWatcher // +CKeypressWatcher::CKeypressWatcher(IoUtils::MCommandExtensionsV2& aCmd, RIoConsoleReadHandle& aReadHandle) + : CActive(CActive::EPriorityStandard), iCmd(aCmd), iReadHandle(aReadHandle) + { + CActiveScheduler::Add(this); + } + +CKeypressWatcher::~CKeypressWatcher() + { + Cancel(); + } + +void CKeypressWatcher::Notify() + { + iReadHandle.WaitForKey(iStatus); + SetActive(); + } + +void CKeypressWatcher::RunL() + { + TUint code = iReadHandle.KeyCode(); + TUint modifiers = iReadHandle.KeyModifiers(); + Notify(); + iCmd.KeyPressed(code, modifiers); + if (code == CTRL('c')) + { + iCmd.CtrlCPressed(); + } + } + +void CKeypressWatcher::DoCancel() + { + iReadHandle.WaitForKeyCancel(); + } + +// + EXPORT_C TCommandExtensionVersion MCommandExtensionsV1::ExtensionVersion() const { return ECommandExtensionV1; @@ -3824,3 +3889,18 @@ { iExtension = aExtension; } + +EXPORT_C TCommandExtensionVersion MCommandExtensionsV2::ExtensionVersion() const + { + return ECommandExtensionV2; + } + +EXPORT_C void MCommandExtensionsV2::KeyPressed(TUint /*aKeyCode*/, TUint /*aModifiers*/) + { + // Default is to do nothing + } + +EXPORT_C void MCommandExtensionsV2::CtrlCPressed() + { + // Default is to do nothing + }