libraries/qr3/src/keycapture.cpp
changeset 0 7f656887cf89
child 86 56b6ee983610
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // keycapture.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 #include <fshell/qr3dll.h>
       
    13 
       
    14 class RWsSession;
       
    15 class RWindowGroup;
       
    16 
       
    17 #include <fshell/common.mmh>
       
    18 #ifdef FSHELL_WSERV_SUPPORT
       
    19 #include <w32std.h>
       
    20 #endif
       
    21 
       
    22 //#define KEYCAPTURE_DEBUG(args...) RDebug::Printf(args)
       
    23 #define KEYCAPTURE_DEBUG(args...) 
       
    24 
       
    25 enum
       
    26 	{
       
    27 	ELongCapture = 1,
       
    28 	ECaptureIsDummy = 2,
       
    29 	ECaptureIsKeyUpDown = 4,
       
    30 	};
       
    31 
       
    32 struct SCapture
       
    33 	{
       
    34 	MCaptureInterface* iClient;
       
    35 	TInt iIdentifier;
       
    36 	TInt iOriginalCode; // This is the code we were actually passed in.
       
    37 	TInt iCaptureCode; // This is the key code we call capture on. This will be the same as iOriginalCode for a normal capture. For a long capture, it will be a virtual key. For an up-and-down, it will be the scan code equivalent of iOriginalCode
       
    38 	TInt32 iCaptureHandle;
       
    39 	TUint32 iFlags;
       
    40 	TInt iPriority;
       
    41 	};
       
    42 
       
    43 #define iWs (*reinterpret_cast<RWsSession*>(iOpaque1))
       
    44 #define iWg (*reinterpret_cast<RWindowGroup*>(iOpaque2))
       
    45 #define iCaptures (*reinterpret_cast<CArrayFixFlat<SCapture>**>(&iOpaque3))
       
    46 #define iPushList (*reinterpret_cast<CArrayPtrFlat<CArrayFixFlat<SCapture> >**>(&iOpaque4))
       
    47 #define KSpareKeysMask 0xF
       
    48 
       
    49 #define KSpareKeyRange EKeyF9 // We use the range F9-F12 inclusive as that seems to be about the only range that I can find not being used by UIQ or licensees
       
    50 
       
    51 CKeyCapturer::CKeyCapturer()
       
    52 	: CActive(CActive::EPriorityUserInput)
       
    53 	, iUsedSpareKeys(0)
       
    54 	{
       
    55 	}
       
    56 
       
    57 void CKeyCapturer::ConstructL()
       
    58 	{
       
    59 #ifdef FSHELL_WSERV_SUPPORT
       
    60 	__ASSERT_COMPILE(sizeof(RWsSession) == EOpaquePadding1);
       
    61 	__ASSERT_COMPILE(sizeof(RWindowGroup) == EOpaquePadding2);
       
    62 	User::LeaveIfError(iWs.Connect());
       
    63 	iWg = RWindowGroup(iWs);
       
    64 	User::LeaveIfError(iWg.Construct((TUint32)this, EFalse));
       
    65 	iWg.SetOrdinalPosition(-1,-1); // This appears to be needed to solve a race condition whereby someone creates a new window (or window group, or something) at roughly the same time as we do, which prevents the other window from coming to the foreground
       
    66 	User::LeaveIfError(iWg.SetName(_L("CKeyCapturerWindowGroup"))); // To ease debugging in wserv
       
    67 
       
    68 	iCaptures = new(ELeave) CArrayFixFlat<SCapture>(8);
       
    69 	iPushList = new(ELeave) CArrayPtrFlat<CArrayFixFlat<SCapture> >(8);
       
    70 
       
    71 	CActiveScheduler::Add(this);
       
    72 	iWs.EventReady(&iStatus);
       
    73 	SetActive();
       
    74 #else
       
    75 	User::Leave(KErrNotSupported);
       
    76 #endif
       
    77 	}
       
    78 
       
    79 EXPORT_C void CKeyCapturer::AddCaptureL(MCaptureInterface* aClient, TInt aIdentifier, TInt aKeyCode)
       
    80 	{
       
    81 	AddCaptureL(aClient, aIdentifier, aKeyCode, 0, KMaxTInt);
       
    82 	}
       
    83 
       
    84 EXPORT_C void CKeyCapturer::AddCaptureL(MCaptureInterface* aClient, TInt aIdentifier, TInt aKeyCode, TInt aScanCode, TInt aCapturePriority)
       
    85 	{
       
    86 	if (aKeyCode == 0 || !aClient) User::Leave(KErrArgument);
       
    87 	RemoveCapture(aClient, aIdentifier); // Just in case it's already been set
       
    88 
       
    89 	SCapture cap;
       
    90 	cap.iClient = aClient;
       
    91 	cap.iIdentifier = aIdentifier;
       
    92 	cap.iCaptureCode = aKeyCode;
       
    93 	cap.iOriginalCode = aKeyCode;
       
    94 	cap.iFlags = 0;
       
    95 	cap.iPriority = aCapturePriority;
       
    96 
       
    97 	AddCaptureL(cap);
       
    98 
       
    99 	if (aScanCode)
       
   100 		{
       
   101 		// If we've been passed a scan code, use it to capture the keyup and keydown events too
       
   102 		SCapture upanddownCap;
       
   103 		upanddownCap.iClient = NULL;
       
   104 		upanddownCap.iIdentifier = -1;
       
   105 		upanddownCap.iCaptureCode = aScanCode;
       
   106 		upanddownCap.iOriginalCode = aScanCode;
       
   107 		upanddownCap.iFlags = ECaptureIsDummy | ECaptureIsKeyUpDown;
       
   108 		upanddownCap.iPriority = aCapturePriority;
       
   109 
       
   110 		TRAPD(err, AddCaptureL(upanddownCap));
       
   111 		if (err)
       
   112 			{
       
   113 			CancelCapture(cap);
       
   114 			iCaptures->Delete(iCaptures->Count()-1);
       
   115 			User::Leave(err);
       
   116 			}
       
   117 		}
       
   118 	}
       
   119 
       
   120 EXPORT_C void CKeyCapturer::AddLongCaptureL(MCaptureInterface* aClient, TInt aIdentifier, TInt aKeyCode, TInt aScanCode)
       
   121 	{
       
   122 	AddLongCaptureL(aClient, aIdentifier, aKeyCode, aScanCode, KMaxTInt);
       
   123 	}
       
   124 
       
   125 EXPORT_C void CKeyCapturer::AddLongCaptureL(MCaptureInterface* aClient, TInt aIdentifier, TInt aKeyCode, TInt aScanCode, TInt aCapturePriority)
       
   126 	{
       
   127 	if (aKeyCode == 0 || aScanCode == 0 || !aClient) User::Leave(KErrArgument);
       
   128 	RemoveCapture(aClient, aIdentifier); // Just in case it's already been set
       
   129 
       
   130 	SCapture cap;
       
   131 	cap.iClient = aClient;
       
   132 	cap.iIdentifier = aIdentifier;
       
   133 	cap.iCaptureCode = 0; // Is filled in later
       
   134 	cap.iOriginalCode = aKeyCode;
       
   135 	cap.iFlags = ELongCapture;
       
   136 	cap.iPriority = aCapturePriority;
       
   137 
       
   138 	AddCaptureL(cap);
       
   139 	
       
   140 	// In order to get repeat events (and, by extension, long key presses) the key events
       
   141 	// must be going to the window group that's capturing the long press. Therefore,
       
   142 	// we also need to capture the key events even if we don't have any client for that
       
   143 	// key.
       
   144 	//
       
   145 	// Of course, this isn't documented anywhere.
       
   146 	SCapture keyCap;
       
   147 	keyCap.iClient = NULL; // So that no action is taken when a short press occurs
       
   148 	keyCap.iIdentifier = -1;
       
   149 	keyCap.iCaptureCode = aKeyCode;
       
   150 	keyCap.iOriginalCode = aKeyCode;
       
   151 	keyCap.iFlags = ECaptureIsDummy;
       
   152 	keyCap.iPriority = aCapturePriority;
       
   153 	
       
   154 	TRAPD(err, AddCaptureL(keyCap));
       
   155 	if (err)
       
   156 		{
       
   157 		CancelCapture(cap);
       
   158 		iCaptures->Delete(iCaptures->Count()-1);
       
   159 		User::Leave(err);
       
   160 		}
       
   161 
       
   162 	// And finally, do a upanddown capture as well, for good measure (TODO do this for normal captures as well, but need the scancode... grr.
       
   163 	SCapture upanddownCap;
       
   164 	upanddownCap.iClient = NULL;
       
   165 	upanddownCap.iIdentifier = -1;
       
   166 	upanddownCap.iCaptureCode = aScanCode;
       
   167 	upanddownCap.iOriginalCode = aScanCode;
       
   168 	upanddownCap.iFlags = ECaptureIsDummy | ECaptureIsKeyUpDown;
       
   169 	upanddownCap.iPriority = aCapturePriority;
       
   170 
       
   171 	TRAP(err, AddCaptureL(upanddownCap));
       
   172 	if (err)
       
   173 		{
       
   174 		CancelCapture(keyCap);
       
   175 		iCaptures->Delete(iCaptures->Count()-1);
       
   176 		CancelCapture(cap);
       
   177 		iCaptures->Delete(iCaptures->Count()-1);
       
   178 		User::Leave(err);
       
   179 		}
       
   180 	}
       
   181 
       
   182 void CKeyCapturer::AddCaptureL(SCapture& cap)
       
   183 	{
       
   184 #ifdef FSHELL_WSERV_SUPPORT
       
   185 	TBool isLong = (cap.iFlags & ELongCapture);
       
   186 	TBool isUpDown = (cap.iFlags & ECaptureIsKeyUpDown);
       
   187 	//ASSERT(iFlags & (ELongCapture | ECaptureIsKeyUpDown) == 0); // Can't be both a long capture and an up-down
       
   188 
       
   189 	if (isLong && iUsedSpareKeys == KSpareKeysMask)
       
   190 		{
       
   191 		// No more keys available to remap as long key presses
       
   192 		User::Leave(KErrOverflow);
       
   193 		}
       
   194 
       
   195 	if (cap.iPriority == KMaxTInt) cap.iPriority = KMaxTInt-1; // Internally somewhere wserv adds one to the priority, and KMaxTInt+1 is KMinTInt...
       
   196 
       
   197 	KEYCAPTURE_DEBUG("KC: AddCapture ident=%d on key=%d, long=%d, updown=%d, dummy=%d)", cap.iIdentifier, cap.iOriginalCode, isLong, isUpDown, cap.iFlags&ECaptureIsDummy);
       
   198 
       
   199 	iCaptures->SetReserveL(iCaptures->Count() + 1); // So that the AppendL later cannot fail
       
   200 	if (isLong)
       
   201 		{
       
   202 		TInt spareKey = -1; // There's a cleaner way to work this out, but since there's only 4, what's the point?
       
   203 		if ((iUsedSpareKeys & 1) == 0) spareKey = 0;
       
   204 		else if ((iUsedSpareKeys & 2) == 0) spareKey = 1;
       
   205 		else if ((iUsedSpareKeys & 4) == 0) spareKey = 2;
       
   206 		else if ((iUsedSpareKeys & 8) == 0) spareKey = 3;
       
   207 		ASSERT(spareKey != -1); // Otherwise the check at the top should have caught this case
       
   208 		cap.iCaptureCode = KSpareKeyRange + spareKey;
       
   209 		
       
   210 		cap.iCaptureHandle = iWg.CaptureLongKey(cap.iOriginalCode, cap.iCaptureCode, 0, 0, cap.iPriority, ELongCaptureWaitShort);
       
   211 		User::LeaveIfError(cap.iCaptureHandle);
       
   212 		iUsedSpareKeys |= 1 << spareKey;
       
   213 		}
       
   214 	else if (isUpDown)
       
   215 		{
       
   216 		cap.iCaptureHandle = iWg.CaptureKeyUpAndDowns(cap.iCaptureCode, 0, 0, cap.iPriority);
       
   217 		User::LeaveIfError(cap.iCaptureHandle);
       
   218 		}
       
   219 	else
       
   220 		{
       
   221 		cap.iCaptureHandle = iWg.CaptureKey(cap.iCaptureCode, 0, 0, cap.iPriority);
       
   222 		User::LeaveIfError(cap.iCaptureHandle);
       
   223 		}
       
   224 	iCaptures->AppendL(cap);
       
   225 #else
       
   226 	User::Leave(KErrNotSupported);
       
   227 #endif
       
   228 	}
       
   229 
       
   230 EXPORT_C void CKeyCapturer::RemoveCapture(MCaptureInterface* aClient, TInt aIdentifier)
       
   231 	{
       
   232 	// Linear search thru iCaptures
       
   233 	for (TInt i = 0; i < iCaptures->Count(); i++)
       
   234 		{
       
   235 		SCapture cap = iCaptures->operator[](i); // Copy cap so we can use it after it's been deleted below
       
   236 		if (cap.iIdentifier == aIdentifier)
       
   237 			{
       
   238 			ASSERT(cap.iClient == aClient);
       
   239 			(void)aClient; // For urel aClient is unused
       
   240 			
       
   241 			CancelCapture(cap);
       
   242 			iCaptures->Delete(i);
       
   243 			RemoveDummyForCapture(cap);
       
   244 			break;
       
   245 			}
       
   246 		}
       
   247 	}
       
   248 
       
   249 void CKeyCapturer::CancelCapture(SCapture& cap)
       
   250 	{
       
   251 #ifdef FSHELL_WSERV_SUPPORT
       
   252 	KEYCAPTURE_DEBUG("KC: CancelCapture ident=%d, captureCode=%d, flags=%d", cap.iIdentifier, cap.iCaptureCode, cap.iFlags);
       
   253 	if (cap.iFlags & ELongCapture)
       
   254 		{
       
   255 		iWg.CancelCaptureLongKey(cap.iCaptureHandle);
       
   256 		TInt bit = cap.iCaptureCode - KSpareKeyRange;
       
   257 		iUsedSpareKeys &= ~(1<<bit);
       
   258 		}
       
   259 	else if (cap.iFlags & ECaptureIsKeyUpDown)
       
   260 		{
       
   261 		iWg.CancelCaptureKeyUpAndDowns(cap.iCaptureHandle);
       
   262 		}
       
   263 	else
       
   264 		{
       
   265 		iWg.CancelCaptureKey(cap.iCaptureHandle);
       
   266 		}
       
   267 #endif
       
   268 	}
       
   269 
       
   270 CKeyCapturer::~CKeyCapturer()
       
   271 	{
       
   272 	Cancel();
       
   273 
       
   274 	for (TInt i = 0; i < iCaptures->Count(); i++)
       
   275 		{
       
   276 		SCapture& cap = iCaptures->operator[](i);
       
   277 		CancelCapture(cap);
       
   278 		}
       
   279 	delete iCaptures;
       
   280 	iPushList->ResetAndDestroy();
       
   281 	delete iPushList;
       
   282 #ifdef FSHELL_WSERV_SUPPORT
       
   283 	iWg.Close();
       
   284 	iWs.Close();
       
   285 #endif
       
   286 	}
       
   287 
       
   288 void CKeyCapturer::RunL()
       
   289 	{
       
   290 #ifdef FSHELL_WSERV_SUPPORT
       
   291 	TWsEvent e;
       
   292 	iWs.GetEvent(e);
       
   293 
       
   294 	iWs.EventReady(&iStatus);
       
   295 	SetActive();
       
   296 
       
   297 	if (e.Type() == EEventKey || e.Type() == EEventKeyDown || e.Type() == EEventKeyUp)
       
   298 		{
       
   299 		TInt code = e.Key()->iCode;
       
   300 		TInt scanCode = e.Key()->iScanCode;
       
   301 		KEYCAPTURE_DEBUG("KC: Received key event (type=%d, key=%d, scan=%d, rep=%d)", e.Type(), code, scanCode, e.Key()->iRepeats);
       
   302 
       
   303 		SCapture* foundDummyCapture = NULL;
       
   304 		
       
   305 		// Linear search thru iCaptures
       
   306 		for (TInt i = 0; i < iCaptures->Count(); i++)
       
   307 			{
       
   308 			SCapture& cap = iCaptures->operator[](i);
       
   309 			
       
   310 			TBool match;
       
   311 			if (e.Type() == EEventKeyDown || e.Type() == EEventKeyUp)
       
   312 				{
       
   313 				match = (scanCode == cap.iCaptureCode) && (cap.iFlags & ECaptureIsKeyUpDown);
       
   314 				}
       
   315 			else
       
   316 				{
       
   317 				match = (code == cap.iCaptureCode) && !(cap.iFlags & ECaptureIsKeyUpDown);
       
   318 				}
       
   319 				
       
   320 			if (match)
       
   321 				{
       
   322 				TBool dummy = cap.iFlags & ECaptureIsDummy;
       
   323 				if (cap.iClient && !dummy)
       
   324 					{
       
   325 					iLastEventScanCode = e.Key()->iScanCode;
       
   326 					KEYCAPTURE_DEBUG("KC: Sending event ident=%d to client", cap.iIdentifier);
       
   327 					cap.iClient->CapturedKeyPressedL(cap.iIdentifier);
       
   328 					iLastEventScanCode = 0;
       
   329 					}
       
   330 				if (dummy)
       
   331 					{
       
   332 					// If it's a dummy capture tied to a particular long key press, then we want to keep looking just in case there's something else that has genuinely captured the key
       
   333 					// Also we remember the dummy in case we don't find any other capture, because we need to forward on uncaptured dummies
       
   334 					foundDummyCapture = &cap;
       
   335 					}
       
   336 				else
       
   337 					{
       
   338 					foundDummyCapture = NULL;
       
   339 					break;
       
   340 					}
       
   341 				}
       
   342 			}
       
   343 		if (foundDummyCapture)
       
   344 			{
       
   345 			KEYCAPTURE_DEBUG("KC: Capture is dummy, passing on to frontmost windowgroup");
       
   346 			TInt foc = iWs.GetFocusWindowGroup();
       
   347 			if (foc != iWg.Identifier())
       
   348 				{
       
   349 				// Send the event on being sure not to pass it back to ourselves!
       
   350 				iWs.SendEventToWindowGroup(foc, e);
       
   351 				}
       
   352 			}
       
   353 		}
       
   354 #endif
       
   355 	}
       
   356 
       
   357 TInt CKeyCapturer::RunError(TInt /*aError*/)
       
   358 	{
       
   359 	return KErrNone; // Don't care if our client left from its call to CapturedKeyPressedL
       
   360 	}
       
   361 
       
   362 void CKeyCapturer::DoCancel()
       
   363 	{
       
   364 #ifdef FSHELL_WSERV_SUPPORT
       
   365 	iWs.EventReadyCancel();
       
   366 #endif
       
   367 	}
       
   368 
       
   369 #ifdef __EXE__
       
   370 	CKeyCapturer* gCapturer = NULL;
       
   371 #endif
       
   372 
       
   373 EXPORT_C CKeyCapturer* CKeyCapturer::GetCapturerL()
       
   374 	{
       
   375 	CKeyCapturer* ref = NULL;
       
   376 
       
   377 #ifdef __EXE__
       
   378 	if (!gCapturer)
       
   379 		{
       
   380 		gCapturer = CKeyCapturer::NewLC();
       
   381 		CleanupStack::Pop();
       
   382 		}
       
   383 	ref = gCapturer;
       
   384 #else
       
   385 	ref = (CKeyCapturer*)Dll::Tls();
       
   386 	if (!ref)
       
   387 		{
       
   388 		ref = CKeyCapturer::NewLC();
       
   389 		User::LeaveIfError(Dll::SetTls(ref));
       
   390 		CleanupStack::Pop(ref);
       
   391 		}
       
   392 #endif
       
   393 	return ref;
       
   394 	}
       
   395 
       
   396 EXPORT_C void CKeyCapturer::DeleteCapturer()
       
   397 	{
       
   398 #ifdef __EXE__
       
   399 	delete gCapturer;
       
   400 	gCapturer = NULL;
       
   401 #else
       
   402 	CKeyCapturer* ref = (CKeyCapturer*)Dll::Tls();
       
   403 	delete ref;
       
   404 	Dll::SetTls(NULL);
       
   405 	//Dll::FreeTls();
       
   406 #endif
       
   407 	}
       
   408 
       
   409 CKeyCapturer* CKeyCapturer::NewLC()
       
   410 	{
       
   411 	CKeyCapturer* res = new(ELeave) CKeyCapturer;
       
   412 	CleanupStack::PushL(res);
       
   413 	res->ConstructL();
       
   414 	return res;
       
   415 	}
       
   416 
       
   417 EXPORT_C void CKeyCapturer::PushCurrentCapturesL()
       
   418 	{
       
   419 	CArrayFixFlat<SCapture>* newList = new(ELeave) CArrayFixFlat<SCapture>(8);
       
   420 	iPushList->AppendL(iCaptures);
       
   421 	// Now cancel everything in currentList to leave a clean slate
       
   422 	for (TInt i = 0; i < iCaptures->Count(); i++)
       
   423 		{
       
   424 		SCapture& cap = iCaptures->operator[](i);
       
   425 		CancelCapture(cap);
       
   426 		}
       
   427 	iCaptures = newList;
       
   428 	}
       
   429 
       
   430 EXPORT_C void CKeyCapturer::PopCapturesL()
       
   431 	{
       
   432 	//__ASSERT_ALWAYS(iPushList->Count() >= 1, User::Invariant());
       
   433 	KEYCAPTURE_DEBUG("KC: Popping captures");
       
   434 
       
   435 	// Cancel everything in the current list
       
   436 	for (TInt i = 0; i < iCaptures->Count(); i++)
       
   437 		{
       
   438 		SCapture& cap = iCaptures->operator[](i);
       
   439 		CancelCapture(cap);
       
   440 		}
       
   441 	iCaptures->Reset(); // Transfer everything to iCaptures one by one, to allow for the (admittedly unlikely) possibility that any individual capture could fail
       
   442 
       
   443 	CArrayFixFlat<SCapture>* newList = (*iPushList)[iPushList->Count()-1];
       
   444 	for (TInt i = newList->Count() - 1; i >= 0 ; i--)
       
   445 		{
       
   446 		SCapture& cap = newList->operator[](i);
       
   447 		AddCaptureL(cap);
       
   448 		newList->Delete(i); // When it's been sucessfully captured into iCaptures, remove if from newList
       
   449 		}
       
   450 	iPushList->Delete(iPushList->Count() - 1);
       
   451 	delete newList;
       
   452 	KEYCAPTURE_DEBUG("KC: Finished restoring previous captures");
       
   453 	}
       
   454 
       
   455 EXPORT_C TInt CKeyCapturer::IsCaptured(TInt aIdentifier)
       
   456 	{
       
   457 	TBool dontCare;
       
   458 	return IsCaptured(aIdentifier, dontCare);
       
   459 	}
       
   460 
       
   461 EXPORT_C TInt CKeyCapturer::IsCaptured(TInt aIdentifier, TBool& aIsLong)
       
   462 	{
       
   463 	for (TInt i = 0; i < iCaptures->Count(); i++)
       
   464 		{
       
   465 		SCapture& cap = iCaptures->operator[](i);
       
   466 		if (cap.iIdentifier == aIdentifier && !(cap.iFlags & ECaptureIsDummy))
       
   467 			{
       
   468 			aIsLong = cap.iFlags & ELongCapture;
       
   469 			return cap.iOriginalCode;
       
   470 			}
       
   471 		}
       
   472 	return 0;
       
   473 	}
       
   474 
       
   475 EXPORT_C TInt CKeyCapturer::GetScanCodeOfLastEvent()
       
   476 	{
       
   477 	return iLastEventScanCode;
       
   478 	}
       
   479 
       
   480 void CKeyCapturer::RemoveDummyForCapture(const SCapture& aCapture)
       
   481 	{
       
   482 	for (TInt i = 0; i < iCaptures->Count(); i++)
       
   483 		{
       
   484 		SCapture cap = iCaptures->operator[](i);
       
   485 		TUint32 matchFlags = ECaptureIsDummy;
       
   486 		if (aCapture.iFlags & ELongCapture)
       
   487 			{
       
   488 			// Nothing to do - the match flags for a long press are ECaptureIsDummy and that's it
       
   489 			}
       
   490 		else
       
   491 			{
       
   492 			// A dummy for a short press is an upAndDown one
       
   493 			matchFlags |= ECaptureIsKeyUpDown;
       
   494 			}
       
   495 		if ((cap.iFlags & matchFlags) && (cap.iOriginalCode == aCapture.iOriginalCode))
       
   496 			{
       
   497 			CancelCapture(cap);
       
   498 			iCaptures->Delete(i);
       
   499 			RemoveDummyForCapture(cap); // Just in case the long press had a dummy (being the short press) which would then ALSO have a dummy (the upanddown)
       
   500 			break;
       
   501 			}
       
   502 		}
       
   503 	}