00001 /* 00002 !concept {:name => "Tracking application focus on Symbian"} 00003 */ 00004 00005 #include "epoc-appfocus.hpp" 00006 00007 #if __APPFOCUS_ENABLED__ 00008 00009 #include "application_config.h" 00010 #include "er_errors.h" 00011 #include "sa_sensor_list_log_db.h" 00012 00013 #include "common/assertions.h" 00014 #include "common/error_list.h" 00015 #include "common/logging.h" 00016 #include "common/platform_error.h" 00017 #include "common/utilities.h" 00018 00019 #include <apgwgnam.h> // library apgrfx.lib 00020 #include <coedef.h> // for ECoeWinPriorityNeverAtFront 00021 00022 // A useful reference is http://developer.sonyericsson.com/message/99028. 00023 00024 // ---------------------------------------------------------------------------- 00025 00026 NONSHARABLE_CLASS(CMyWindowGroup) : 00027 public CBase 00028 { 00029 public: 00030 00031 static CMyWindowGroup* NewL(RWsSession& aWsSession); 00032 00033 virtual ~CMyWindowGroup(); 00034 00035 RWindowGroup& Ref() { return iWindowGroup; } 00036 00037 private: 00038 00039 CMyWindowGroup(RWsSession& aWsSession) : iWsSession(aWsSession), iWindowGroup(aWsSession) {} 00040 00041 void ConstructL(); 00042 00043 private: 00044 00045 RWsSession& iWsSession; 00046 00047 DEF_SESSION(RWindowGroup, iWindowGroup); 00048 }; 00049 00050 CMyWindowGroup* CMyWindowGroup::NewL(RWsSession& aWsSession) 00051 { 00052 CMyWindowGroup* obj = new (ELeave) CMyWindowGroup(aWsSession); 00053 CleanupStack::PushL(obj); 00054 obj->ConstructL(); 00055 CleanupStack::Pop(); 00056 return obj; 00057 } 00058 00059 void CMyWindowGroup::ConstructL() 00060 { 00061 TUint32 clientHandle = reinterpret_cast<TUint32>(&iWindowGroup); 00062 LEAVE_IF_ERROR_OR_SET_SESSION_OPEN(iWindowGroup, iWindowGroup.Construct(clientHandle, EFalse)); 00063 00064 // Hide the icon for this window group. Not sure exactly what it 00065 // takes to do this, but all of this (in this order) at least 00066 // appears to work. People have been having trouble making this 00067 // happen, it seems. Probably they get this right with the PyS60 00068 // keycapture module, but have not checked. 00069 CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(iWsSession, clientHandle); 00070 wgName->SetHidden(ETrue); 00071 CleanupStack::PopAndDestroy(); // wgName 00072 00073 iWindowGroup.EnableReceiptOfFocus(EFalse); 00074 iWindowGroup.SetOrdinalPosition(-1, ECoeWinPriorityNeverAtFront); // hide the window group 00075 iWindowGroup.DefaultOwningWindow(); 00076 } 00077 00078 CMyWindowGroup::~CMyWindowGroup() 00079 { 00080 SESSION_CLOSE_IF_OPEN(iWindowGroup); 00081 } 00082 00083 // ---------------------------------------------------------------------------- 00084 00085 CSensor_appfocus* CSensor_appfocus::NewL(LogDb* aLogDb) 00086 { 00087 CSensor_appfocus* obj = new (ELeave) CSensor_appfocus(aLogDb); 00088 CleanupStack::PushL(obj); 00089 obj->ConstructL(); 00090 CleanupStack::Pop(); 00091 return obj; 00092 } 00093 00094 CSensor_appfocus::CSensor_appfocus(LogDb* aLogDb) : 00095 CActiveRunG(EPriorityStandard) 00096 { 00097 iLogDb = aLogDb; 00098 CActiveScheduler::Add(this); 00099 } 00100 00101 void CSensor_appfocus::ConstructL() 00102 { 00103 LEAVE_IF_ERROR_OR_SET_SESSION_OPEN(iWsSession, iWsSession.Connect()); 00104 00105 // It seems the RWsSession passed to RWindowGroup must be open, so 00106 // we require some contortions here. 00107 iMyWindowGroup = CMyWindowGroup::NewL(iWsSession); 00108 } 00109 00110 CSensor_appfocus::~CSensor_appfocus() 00111 { 00112 Cancel(); // safe when AO inactive as DoCancel not called 00113 delete iMyWindowGroup; 00114 SESSION_CLOSE_IF_OPEN(iWsSession); 00115 } 00116 00117 gboolean CSensor_appfocus::StartL(GError** error) 00118 { 00119 if (!iFocusChangeEventsEnabled) { 00120 // I do not believe it's dangerous to leave this enabled, if say 00121 // there is a scanning error and we cannot continue processing 00122 // events. We do not invoke EventReady, and so the event delivery 00123 // should skip us. I hope. 00124 User::LeaveIfError(iMyWindowGroup->Ref().EnableFocusChangeEvents()); 00125 iFocusChangeEventsEnabled = ETrue; 00126 } 00127 if (!IsActive()) { 00128 MakeRequest(); 00129 //log_db_log_status(iLogDb, NULL, "appfocus sensor started"); 00130 } 00131 return TRUE; 00132 } 00133 00134 void CSensor_appfocus::Stop() 00135 { 00136 if (IsActive()) { 00137 Cancel(); 00138 //log_db_log_status(iLogDb, NULL, "appfocus sensor stopped"); 00139 } 00140 00141 if (iFocusChangeEventsEnabled) { 00142 // Okay to call even if not enabled. 00143 iMyWindowGroup->Ref().DisableFocusChangeEvents(); 00144 iFocusChangeEventsEnabled = EFalse; 00145 } 00146 } 00147 00148 void CSensor_appfocus::MakeRequest() 00149 { 00150 // I guess we do actually require our very own window server session 00151 // here. 00152 iWsSession.EventReady(&iStatus); 00153 00154 SetActive(); 00155 } 00156 00157 gboolean CSensor_appfocus::RunGL(GError** error) 00158 { 00159 assert_error_unset(error); 00160 00161 TInt errCode = iStatus.Int(); 00162 00163 //logg("appfocus event %d", errCode); 00164 00165 //Leave(gx_error_no_memory); // test 00166 00167 if (errCode) { 00168 // This error really should not occur, but since it has, we will 00169 // simply stop this one scanner. For a retry, someone just call 00170 // StartL. 00171 goto fail; 00172 } else { 00173 // Must do a GetEvent before doing another EventReady. 00174 TWsEvent event; 00175 iWsSession.GetEvent(event); 00176 00177 TInt wgid = iWsSession.GetFocusWindowGroup(); 00178 CApaWindowGroupName* gn = NULL; 00179 TRAP(errCode, gn = CApaWindowGroupName::NewL(iWsSession, wgid)); 00180 if (errCode) { 00181 goto fail; 00182 } 00183 TUid uid = gn->AppUid(); // the uid of the focused app 00184 TInt32 appUid = uid.iUid; 00185 sqlite3_int64 appUid64 = (sqlite3_int64)((TUint32)appUid); 00186 TPtrC nameDes = gn->Caption(); 00187 gchar appName[32+1]; // should be big enough for informative logging 00188 ConvToUtf8CString(appName, 32, nameDes); 00189 delete gn; 00190 00191 guilogf("appfocus: '%s' 0x%08x", appName, appUid); 00192 00193 if (!log_db_log_appfocus(iLogDb, appUid64, appName, error)) { 00194 return FALSE; 00195 } 00196 00197 MakeRequest(); 00198 } 00199 00200 return TRUE; 00201 00202 fail: 00203 if (!log_db_log_status(iLogDb, error, "INACTIVATE: appfocus: failure reading sensor: %s (%d)", plat_error_strerror(errCode), errCode)) { 00204 // Logging failing is quite severe. We shall report the error 00205 // upwards, where the framework will hopefully take corrective 00206 // action, and probably then call either our StartL or dtor, 00207 // depending on whether recovery was possible. 00208 return FALSE; 00209 } 00210 00211 return TRUE; 00212 } 00213 00214 const char* CSensor_appfocus::Description() 00215 { 00216 return "appfocus"; 00217 } 00218 00219 void CSensor_appfocus::DoCancel() 00220 { 00221 iWsSession.EventReadyCancel(); 00222 } 00223 00224 #endif // __APPFOCUS_ENABLED__ 00225 00226 /** 00227 00228 epoc-appfocus.cpp 00229 00230 Copyright 2009 Helsinki Institute for Information Technology (HIIT) 00231 and the authors. All rights reserved. 00232 00233 Authors: Tero Hasu <tero.hasu@hut.fi> 00234 00235 Permission is hereby granted, free of charge, to any person 00236 obtaining a copy of this software and associated documentation files 00237 (the "Software"), to deal in the Software without restriction, 00238 including without limitation the rights to use, copy, modify, merge, 00239 publish, distribute, sublicense, and/or sell copies of the Software, 00240 and to permit persons to whom the Software is furnished to do so, 00241 subject to the following conditions: 00242 00243 The above copyright notice and this permission notice shall be 00244 included in all copies or substantial portions of the Software. 00245 00246 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00247 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00248 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00249 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 00250 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 00251 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00252 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00253 SOFTWARE. 00254 00255 **/
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:52 2011 by Doxygen 1.6.1