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