epoc-keypress.cpp

Go to the documentation of this file.
00001 /**
00002  * ====================================================================
00003  * capturer.cpp
00004  * Copyright (c) 2006 Nokia Corporation
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *     http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  * ====================================================================
00018  */
00019 
00020 // A small amount of the code is derived from CCapturer in PyS60,
00021 // hence the above license applies. Any changes made are Copyright
00022 // 2009 Helsinki Institute for Information Technology (HIIT) and Tero
00023 // Hasu <tero.hasu@hut.fi>, and are made available under the original
00024 // license.
00025 
00026 /*
00027  References:
00028 
00029  * http://mikie.iki.fi/symbian/keycapture.html
00030 
00031  * http://stackoverflow.com/questions/243504/capture-keystrokes-on-symbian-os
00032 
00033  */
00034  
00035 #include "epoc-keypress.hpp"
00036 
00037 #if __KEYPRESS_ENABLED__
00038 
00039 #include "epoc-key-codes.hpp"
00040 
00041 #include "common/assertions.h"
00042 #include "application_config.h"
00043 #include "er_errors.h"
00044 #include "common/error_list.h"
00045 #include "common/logging.h"
00046 #include "common/platform_error.h"
00047 #include "sa_sensor_list_log_db.h"
00048 #include "common/utilities.h"
00049 
00050 CSensor_keypress* CSensor_keypress::NewL(LogDb* aLogDb)
00051 {
00052   CSensor_keypress* self = new (ELeave) CSensor_keypress(aLogDb);
00053   CleanupStack::PushL(self);
00054   self->ConstructL();
00055   CleanupStack::Pop(self);
00056   return self;
00057 };
00058 
00059 CSensor_keypress::CSensor_keypress(LogDb* aLogDb) :
00060   CActiveRunG(CActive::EPriorityLow)
00061 {
00062   iLogDb = aLogDb;
00063   CActiveScheduler::Add(this);
00064 };
00065 
00066 static const int allKeyCodes[] = SELECT_KEY_CODES;
00067 
00068 void CSensor_keypress::ConstructL()
00069 {
00070   // The size chosen so that we are not wasteful with space, but
00071   // neither should require too many reallocations.
00072   SET_TRAP_OOM(User::LeaveNoMemory());
00073   iKeysText = g_string_sized_new(20 + MAX_NUM_CAPTURED_KEYS * 2);
00074   UNSET_TRAP_OOM();
00075   assert(iKeysText != NULL);
00076 
00077   iSession = new (ELeave) RWsSession();
00078   
00079   User::LeaveIfError(iSession->Connect());
00080   iWinGroup = new (ELeave) RWindowGroup(*iSession);
00081   iWinGroup->Construct((TUint32)iWinGroup, EFalse);
00082   
00083   iWinGroup->SetOrdinalPosition(-1, ECoeWinPriorityNeverAtFront); 
00084   iWinGroup->EnableReceiptOfFocus(EFalse);
00085   
00086   iWinGroupName = CApaWindowGroupName::NewL(*iSession);
00087   iWinGroupName->SetHidden(ETrue); // Hide from tasklist.
00088   iWinGroupName->SetWindowGroupName(*iWinGroup);
00089 };
00090 
00091 void CSensor_keypress::RequestAllKeys()
00092 {
00093   const int* code = &allKeyCodes[0];
00094   iNumCaptureHandles = 0;
00095   while (*code) {
00096     //logg("asking for key code %d", (*code));
00097     iCaptureHandles[iNumCaptureHandles] = SetKeyToBeCaptured(*code);
00098     code++;
00099     iNumCaptureHandles++;
00100   }
00101   //logt("done asking");
00102 }
00103 
00104 // This sensor is particularly delicate, since we are eating
00105 // keypresses. Failing to forward them is a problem.
00106 void CSensor_keypress::CancelAllKeys()
00107 {
00108   while (iNumCaptureHandles > 0) {
00109     TInt32 handle = iCaptureHandles[iNumCaptureHandles];
00110     if (handle >= 0)
00111       RemoveKey(handle);
00112     iNumCaptureHandles--;
00113   }
00114 }
00115 
00116 // Negative return value indicates an error.
00117 //
00118 // e32keys.h defines some of the possible values in TKeyCode, but that's only the special ones, so potentially there are lots.
00119 TInt32 CSensor_keypress::SetKeyToBeCaptured(TInt32 keyCode)
00120 {
00121   TInt32 captureHandle;
00122   // Negative values indicate error, other values are capture handles,
00123   // of use when cancelling key capture for the same key.
00124   captureHandle = iWinGroup->CaptureKey(keyCode,0,0);
00125   return captureHandle;
00126 };
00127 
00128 void CSensor_keypress::RemoveKey(TInt32 captureHandle)
00129 {
00130   iWinGroup->CancelCaptureKey(captureHandle);
00131 };
00132 
00133 gboolean CSensor_keypress::StartL(GError** error)
00134 {
00135   if (!IsActive()) {
00136     RequestAllKeys();
00137     MakeRequest();
00138     //log_db_log_status(iLogDb, NULL, "keypress sensor started");
00139   }
00140   return TRUE;
00141 }
00142 
00143 void CSensor_keypress::Stop()
00144 {
00145   if (IsActive()) {
00146     Cancel();
00147     //log_db_log_status(iLogDb, NULL, "keypress sensor stopped");
00148   }
00149   LogAndClear(NULL); // best effort, already being stopped
00150 }
00151 
00152 void CSensor_keypress::MakeRequest()
00153 {
00154   iSession->EventReady(&iStatus);
00155   SetActive();
00156 };
00157 
00158 void CSensor_keypress::DoCancel()
00159 {
00160   iSession->EventReadyCancel();
00161   CancelAllKeys();
00162 };
00163 
00164 CSensor_keypress::~CSensor_keypress()
00165 {
00166   Cancel();
00167   LogAndClear(NULL);
00168   if(iWinGroup){
00169     iWinGroup->Close();
00170     delete iWinGroup;
00171   }
00172   delete iWinGroupName;
00173   if(iSession){
00174     iSession->Close();
00175     delete iSession;
00176   }
00177   g_string_free(iKeysText, TRUE);
00178 };
00179 
00180 gboolean CSensor_keypress::RunGL(GError** error)
00181 {  
00182   assert_error_unset(error);
00183 
00184   TInt errCode = iStatus.Int();
00185 
00186   //logg("keypress event %d", errCode);
00187 
00188   if (errCode) {
00189     // This error really should not occur, but since it has, we will
00190     // simply stop this one scanner. For a retry, someone just call
00191     // StartL.
00192     log_db_log_status(iLogDb, NULL, "INACTIVATE: keypress: failure reading sensor: %s (%d)", plat_error_strerror(errCode), errCode);
00193     Stop();
00194   } else {
00195     TWsEvent event;
00196     iSession->GetEvent(event);
00197     
00198     //TInt32 lastCapturedKey = event.Key()->iCode;
00199     //logg("last captured key was %d", lastCapturedKey);
00200 
00201     time_t now = time(NULL); 
00202     if (now != -1) { // if no error getting time
00203       iCapturedKeys[iNumCapturedKeys] = now;
00204       iNumCapturedKeys++;
00205       if (iNumCapturedKeys == MAX_NUM_CAPTURED_KEYS) {
00206   if (!LogAndClear(error)) {
00207     return FALSE;
00208   }
00209       }
00210     }
00211 
00212     // Forward keypress to original recipient.
00213     iSession->SendEventToWindowGroup(iSession->GetFocusWindowGroup(), event);
00214 
00215     MakeRequest();
00216   }
00217 
00218   return TRUE;
00219 };
00220 
00221 gboolean CSensor_keypress::LogAndClear(GError** error)
00222 {
00223   if (iNumCapturedKeys > 0) {
00224     time_t base = iCapturedKeys[0];
00225     SET_TRAP_OOM(goto nomemory);
00226     g_string_set_size(iKeysText, 0);
00227     g_string_append_printf(iKeysText, "{base: %d, times: [", base);
00228     int i = 0;
00229     while (i < iNumCapturedKeys) {
00230       if (i != 0)
00231   g_string_append(iKeysText, ", ");
00232       g_string_append_printf(iKeysText, "%d", iCapturedKeys[i] - base);
00233       i++;
00234     }
00235     g_string_append(iKeysText, "]}");
00236     UNSET_TRAP_OOM();
00237     iNumCapturedKeys = 0;
00238 
00239     if (!log_db_log_keypress(iLogDb, iKeysText->str, error)) {
00240       return FALSE;
00241     }
00242   }
00243   return TRUE;
00244 
00245  nomemory:
00246   if (error) *error = gx_error_no_memory;
00247   return FALSE;
00248 }
00249 
00250 const char* CSensor_keypress::Description()
00251 {
00252   return "keypress";
00253 }
00254 
00255 #endif // __KEYPRESS_ENABLED__
00256 

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:52 2011 by Doxygen 1.6.1