--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AknGlobalUI/OldStyleNotif/Src/aknmessagereaderlongpressdetector.cpp Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,637 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include "aknmessagereaderlongpressdetector.h"
+#include <AknUtils.h>
+#include <aknkeylock.h>
+#include <e32base.h>
+#include <eikbtgrp.h>
+#include <apgcli.h>
+#include <e32property.h>
+#include <avkondomainpskeys.h> // keyguard state (KPSUidAvkonDomain, KAknKeyguardStatus)
+#include <layoutmetadata.cdl.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+
+const TInt KMessageReaderUid = 0x10201B00;
+const TInt KDefaultLongPressInterval = 800000; // default value is 0.8 seconds
+const TInt KNegativePointerPosition = -1;
+
+/**
+* CAknPhoneLockObserver class.
+* Detects whether Keyguard is currently enabled or not
+*
+* @lib AknOldStyleNotif.lib
+* @since 3.2
+*/
+NONSHARABLE_CLASS(CAknPhoneLockObserver) : public CActive
+ {
+public:
+ /**
+ * Creates instance of the CAknPhoneLockObserver class.
+ *
+ * @param aObserver (pointer to observer)
+ */
+ static CAknPhoneLockObserver* NewL( CAknMessageReaderLongPressDetector& aParent );
+
+ /**
+ * Destructor.
+ */
+ ~CAknPhoneLockObserver();
+
+ /**
+ * Start observing.
+ */
+ TInt Start();
+
+ /**
+ * Stop observing.
+ */
+ void Stop();
+
+ /**
+ * If either keyguard or devicelock is enabled
+ *
+ * @return ETrue if phone is locked
+ */
+ inline TBool PhoneLocked()
+ {
+ return iPhoneLocked;
+ };
+
+protected:
+
+ /**
+ * C++ default constructor.
+ *
+ * @param aObserver observer
+ */
+ CAknPhoneLockObserver( CAknMessageReaderLongPressDetector& aParent );
+
+ /**
+ * Symbian OS constructor.
+ */
+ void ConstructL();
+
+private: // from CActive
+
+ /** @see CActive::RunL() */
+ void RunL();
+
+ /** @see CActive::DoCancel() */
+ void DoCancel();
+
+ /**
+ * Update phone lock status (phone locked if keyguard or autolock emulation is active)
+ * @return symbian error value
+ */
+ TInt UpdatePhoneLockStatus();
+
+private: // data
+
+ RProperty iProperty;
+ TBool iPhoneLocked;
+
+ // reference to the parent
+ CAknMessageReaderLongPressDetector& iParent;
+ };
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ----------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------
+//
+CAknPhoneLockObserver* CAknPhoneLockObserver::NewL( CAknMessageReaderLongPressDetector& aParent )
+ {
+ CAknPhoneLockObserver* self = new (ELeave) CAknPhoneLockObserver( aParent );
+ CleanupStack::PushL( self );
+ self->ConstructL( );
+ CleanupStack::Pop( self ); //self
+ return self;
+ }
+
+// ----------------------------------------------------------
+// C++ default constructor
+// ----------------------------------------------------------
+//
+CAknPhoneLockObserver::CAknPhoneLockObserver( CAknMessageReaderLongPressDetector& aParent ) :
+ CActive(0), iParent( aParent )
+ {
+ }
+
+// ----------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------
+//
+CAknPhoneLockObserver::~CAknPhoneLockObserver( )
+ {
+ Cancel( );
+ iProperty.Close( );
+ }
+
+// ----------------------------------------------------------
+// Symbian OS default constructor
+// ----------------------------------------------------------
+//
+void CAknPhoneLockObserver::ConstructL( )
+ {
+ // Add this active object to the scheduler.
+ CActiveScheduler::Add( this );
+ TRAPD(err, iProperty.Attach( KPSUidAvkonDomain, KAknKeyguardStatus ) )
+ User::LeaveIfError( err );
+ }
+
+// ----------------------------------------------------------
+// Starts listening
+// ----------------------------------------------------------
+//
+TInt CAknPhoneLockObserver::Start( )
+ {
+ if ( IsActive( ) )
+ return KErrInUse;
+ iStatus = KRequestPending;
+ iProperty.Subscribe( iStatus );
+ SetActive( );
+ UpdatePhoneLockStatus();
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------
+// Stops listening
+// ----------------------------------------------------------
+//
+void CAknPhoneLockObserver::Stop( )
+ {
+ if ( !IsActive() )
+ return;
+ Cancel( );
+ iProperty.Cancel( );
+ }
+
+TInt CAknPhoneLockObserver::UpdatePhoneLockStatus()
+ {
+ TInt value( NULL);
+ TInt err( KErrNone );
+ err = iProperty.Get( value );
+ if ( err == KErrNone )
+ {
+ // either devicelock or keyguard is enabled
+ iPhoneLocked = (value == EKeyguardNotActive) ? EFalse : ETrue;
+ }
+ return err;
+ }
+// ----------------------------------------------------------
+// CAknPhoneLockObserver::RunL()
+// ----------------------------------------------------------
+//
+void CAknPhoneLockObserver::RunL( )
+ {
+ UpdatePhoneLockStatus();
+ // re-subscribe to events
+ iParent.KeysLocked( iPhoneLocked );
+ Start();
+ }
+
+// ----------------------------------------------------------
+// Cancels event listening
+// ----------------------------------------------------------
+//
+void CAknPhoneLockObserver::DoCancel()
+ {
+ iProperty.Cancel();
+ }
+
+// ----------------------------------------------------------------------------
+// Standard two-phased construction
+// ----------------------------------------------------------------------------
+//
+CAknMessageReaderLongPressDetector* CAknMessageReaderLongPressDetector::NewL( CEikButtonGroupContainer* aGlobalNoteBGContainer, RWindow& aGlobalNoteWindow )
+ {
+ CAknMessageReaderLongPressDetector* self = new (ELeave) CAknMessageReaderLongPressDetector( aGlobalNoteBGContainer, aGlobalNoteWindow );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// C++ destructor, only CPeriodic timer is owned
+// ----------------------------------------------------------------------------
+//
+CAknMessageReaderLongPressDetector::~CAknMessageReaderLongPressDetector()
+ {
+ Disable();
+ if ( iLongPressTimer )
+ {
+ delete iLongPressTimer;
+ }
+ if ( iPhoneLockObserver )
+ {
+ delete iPhoneLockObserver;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// C++ constructor
+// ----------------------------------------------------------------------------
+//
+CAknMessageReaderLongPressDetector::CAknMessageReaderLongPressDetector( CEikButtonGroupContainer* aGlobalNoteBGContainer, RWindow& aGlobalNoteWindow ) :
+ iGlobalNoteBGContainer( aGlobalNoteBGContainer ), iGlobalNoteWindow( aGlobalNoteWindow )
+ {
+ // Do nothing
+ }
+
+// ----------------------------------------------------------------------------
+// Symbian constructor
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::ConstructL()
+ {
+ TInt leftSoftKeyPosition( NULL );
+ MEikButtonGroup* buttonGroup = iGlobalNoteBGContainer->ButtonGroup();
+ TInt commandId = buttonGroup->CommandId( leftSoftKeyPosition );
+ iLeftSoftKeyControl = buttonGroup->GroupControlById( commandId );
+
+ iPhoneLockObserver = CAknPhoneLockObserver::NewL( *this );
+ }
+
+// ----------------------------------------------------------------------------
+// Determine if message reader has been installed on the device or not
+// ----------------------------------------------------------------------------
+//
+TBool CAknMessageReaderLongPressDetector::MessageReaderInstalled()
+ {
+ TBool messageReaderDetected( EFalse );
+ RApaLsSession appArcSession;
+ TInt err = appArcSession.Connect();
+ if ( err == KErrNone )
+ {
+ TApaAppInfo applicationInfo;
+ err = appArcSession.GetAppInfo( applicationInfo, TUid::Uid(KMessageReaderUid));
+ // GetAppInfo returns KErrNotFound if application hasn't been installed
+ if ( err == KErrNone )
+ {
+ messageReaderDetected = ETrue;
+ }
+ }
+ appArcSession.Close();
+ return messageReaderDetected;
+ }
+
+// ----------------------------------------------------------------------------
+// Soft notification is on/off the screen
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::SoftNotifierVisible( TBool aVisible )
+ {
+ iSoftNotifierVisible = aVisible;
+ if ( iSoftNotifierVisible )
+ {
+ // start observing keyguard value, only detect if keyguard is enabled
+ iPhoneLockObserver->Start();
+
+ // enable detector if phone is not locked
+ if ( !iPhoneLockObserver->PhoneLocked() )
+ {
+ Enable();
+ }
+ }
+
+ // if the soft notifier is no longer on the screen, disable detector
+ else
+ {
+ Disable();
+ // phone lock observer is only active when any soft notifier is visible
+ iPhoneLockObserver->Stop();
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// Phone keys are locked
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::KeysLocked( TBool aLocked )
+ {
+ // enable detector if soft notifiers are visible and keys aren't locked
+ if ( iSoftNotifierVisible && !aLocked )
+ {
+ Enable();
+ }
+ // if keys were locked, disable detector
+ else if ( aLocked )
+ {
+ Disable();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Give global note subject a access to grouped note information
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::SetMessageNotifierObserver( MAknMessageNotifierObserver* aMessageNotifierObserver )
+ {
+ iMessageNotifierObserver = aMessageNotifierObserver;
+ }
+
+// ----------------------------------------------------------------------------
+// Enable left soft key long press detection (soft notifier is activated)
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::Enable()
+ {
+ // Only enable long press capture when messaging note is being displayed.
+ if (!iDetectorEnabled &&
+ iMessageNotifierObserver && iMessageNotifierObserver->MessageNotifierShown())
+ {
+ iDetectorEnabled = ETrue;
+ if ( iCaptureLongKeyHandle == 0 )
+ {
+ const TInt KCapturePriority = 10;
+ RWindowGroup wg = CCoeEnv::Static()->RootWin();
+
+ iCaptureLongKeyHandle = wg.CaptureLongKey( EKeyCBA1, EKeyCBA1, 0, 0,
+ KCapturePriority,
+ ELongCaptureWaitShort );
+ }
+ iLSKKeyDownDetect = EFalse;
+#ifdef _DEBUG
+ RDebug::Print( _L("CAknMessageReaderLongPressDetector::Enable"));
+#endif
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Disable left soft key long press detection (soft notifier is deactivated)
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::Disable()
+ {
+ if ( iDetectorEnabled )
+ {
+ iDetectorEnabled = EFalse;
+ if ( iCaptureLongKeyHandle > 0 )
+ {
+ RWindowGroup wg = CCoeEnv::Static()->RootWin();
+
+ wg.CancelCaptureLongKey( iCaptureLongKeyHandle );
+
+ iCaptureLongKeyHandle = 0;
+ }
+
+ // reset long press detection
+ StopLongPressTimer();
+#ifdef _DEBUG
+ RDebug::Print( _L("CAknMessageReaderLongPressDetector::Disable"));
+#endif
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Handle key and pointer events for detecting left soft key long presses
+// ----------------------------------------------------------------------------
+//
+TBool CAknMessageReaderLongPressDetector::HandleWsEventL( const TWsEvent& aEvent, CCoeControl* aDestination )
+ {
+ TBool consumeEvent( EFalse );
+
+ // only handle events when soft notifiers are visible and phone is not locked
+ if ( iSoftNotifierVisible && !iPhoneLockObserver->PhoneLocked() )
+ {
+ // only detect long presses if there are unread message notifications
+ if ( iMessageNotifierObserver && iMessageNotifierObserver->MessageNotifierShown() )
+ {
+ TInt eventType( aEvent.Type() );
+ const TKeyEvent keyEvent( *aEvent.Key() );
+
+ if (eventType == EEventKeyDown && (keyEvent.iScanCode == EStdKeyDevice0))
+ {
+ iLSKKeyDownDetect = ETrue;
+ }
+
+ if (eventType == EEventKey && iLSKKeyDownDetect)
+ {
+ if ( keyEvent.iCode == EKeyCBA1 && keyEvent.iRepeats == 1 )
+ {
+ consumeEvent = ETrue;
+ LaunchMessageReaderL();
+ }
+ }
+ else if ( eventType == EEventPointer )
+ {
+ consumeEvent = HandleLongTouchL( *aEvent.Pointer(), aDestination );
+ }
+ }
+ }
+
+ return consumeEvent;
+ }
+
+TBool CAknMessageReaderLongPressDetector::IsPointerInLeftSoftKeyRect(TPoint aPoint, CCoeControl* aDestination)
+ {
+ TBool pointInLSK = EFalse;
+
+ if (aDestination != NULL && iLeftSoftKeyControl != NULL)
+ {
+ if (aDestination == iLeftSoftKeyControl)
+ {
+ pointInLSK = ETrue;
+ }
+ else if (aDestination == iLeftSoftKeyControl->Parent())
+ {
+ // Copy codes from CEikCba class.
+ TRect containerRect(aDestination->Rect());
+ TAknLayoutRect layoutRect;
+ TRect button1Rect(0, 0, 0, 0);
+
+ if (Layout_Meta_Data::IsLandscapeOrientation())
+ {
+ TAknWindowComponentLayout rightAreaLayout(
+ AknLayoutScalable_Avkon::area_side_right_pane(0));
+
+ layoutRect.LayoutRect(
+ containerRect,
+ TAknWindowComponentLayout::Compose(
+ rightAreaLayout,
+ AknLayoutScalable_Avkon::sctrl_sk_bottom_pane()).LayoutLine());
+
+ TRect bottomSKRect(layoutRect.Rect());
+
+ layoutRect.LayoutRect(
+ bottomSKRect,
+ AknLayoutScalable_Avkon::aid_touch_sctrl_bottom().LayoutLine());
+
+ button1Rect = layoutRect.Rect();
+ }
+ else
+ {
+ if (AknLayoutUtils::LayoutMirrored())
+ {
+ layoutRect.LayoutRect(
+ containerRect,
+ AknLayoutScalable_Avkon::aid_touch_ctrl_right().LayoutLine());
+
+ button1Rect = layoutRect.Rect();
+ }
+ else
+ {
+ layoutRect.LayoutRect(
+ containerRect,
+ AknLayoutScalable_Avkon::aid_touch_ctrl_left().LayoutLine());
+
+ button1Rect = layoutRect.Rect();
+ }
+ }
+
+ if (button1Rect.Contains(aPoint))
+ {
+ pointInLSK = ETrue;
+ }
+ }
+ }
+
+ return pointInLSK;
+ }
+
+
+// ----------------------------------------------------------------------------
+// Handle pointer events for detecting left soft key long presses
+// ----------------------------------------------------------------------------
+//
+TBool CAknMessageReaderLongPressDetector::HandleLongTouchL(const TPointerEvent& aPointerEvent, CCoeControl* aDestination )
+ {
+ // Only test the cba's pointer event, iLeftSoftKeyControl->Rect() only is the text rect of cba button.
+ // So, we need to check the parent rect of iLeftSoftKeyControl.
+ TBool leftSoftkeyClicked = IsPointerInLeftSoftKeyRect(aPointerEvent.iPosition, aDestination);
+
+ // start the timer when the pointer event is in the left soft key area and pressed down
+ if ( leftSoftkeyClicked && aPointerEvent.iType == TPointerEvent::EButton1Down )
+ {
+#ifdef _DEBUG
+ RDebug::Print( _L("CAknMessageReaderLongPressDetector::HandleLongTouchL - long LSK touch detection activated"));
+#endif
+ StartLongPressTimerL();
+ iPointerDestination = aDestination;
+ }
+
+ // stop the timer when the pointer event is outside the area or released
+ if ( !leftSoftkeyClicked || aPointerEvent.iType == TPointerEvent::EButton1Up )
+ {
+ StopLongPressTimer();
+#ifdef _DEBUG
+ RDebug::Print( _L("CAknMessageReaderLongPressDetector::HandleLongTouchL - short LSK touch press"));
+#endif
+ }
+
+ return EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// Launch message reader application
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::LaunchMessageReaderL()
+ {
+ // disable detector
+ Disable();
+
+ // launch message reader
+ RApaLsSession ls;
+ User::LeaveIfError(ls.Connect());
+ CleanupClosePushL(ls);
+ CApaCommandLine* cmdLine=CApaCommandLine::NewLC();
+ cmdLine->SetCommandL(EApaCommandRun);
+ TApaAppInfo applicationInfo;
+ ls.GetAppInfo( applicationInfo, TUid::Uid(KMessageReaderUid) );
+ cmdLine->SetExecutableNameL( applicationInfo.iFullName );
+ cmdLine->SetTailEndL( _L8("ui=read_new") );
+ ls.StartApp( *cmdLine );
+ CleanupStack::PopAndDestroy(2); // cmdLine, ls
+
+#ifdef _DEBUG
+ RDebug::Print( _L("CAknMessageReaderLongPressDetector::LaunchMessageReaderL - Messagereader launched"));
+#endif
+ }
+
+
+// ----------------------------------------------------------------------------
+// Long press timer calls this method when timeout is passed
+// ----------------------------------------------------------------------------
+//
+TInt CAknMessageReaderLongPressDetector::ReportLongPressL( TAny* aThis )
+ {
+ static_cast<CAknMessageReaderLongPressDetector*>( aThis )->DoReportLongPressL();
+ return 0;
+ }
+
+// ----------------------------------------------------------------------------
+// Long press timer calls this method when timeout is passed
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::DoReportLongPressL()
+ {
+ // release the soft button
+ TPointerEvent releaseButton;
+ releaseButton.iPosition = TPoint( NULL, KNegativePointerPosition );
+ releaseButton.iType = TPointerEvent::EDrag;
+ releaseButton.iModifiers = NULL;
+ iPointerDestination->HandlePointerEventL( releaseButton );
+
+ // launch message reader
+ LaunchMessageReaderL();
+
+#ifdef _DEBUG
+ RDebug::Print( _L("CAknMessageReaderLongPressDetector::DoReportLongPressL - long LSK key press"));
+#endif
+ }
+
+// ----------------------------------------------------------------------------
+// Start long press timer
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::StartLongPressTimerL()
+ {
+ // create timer if needed
+ if ( !iLongPressTimer )
+ {
+ iLongPressTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+ }
+ // reset timer if already active
+ else if ( iLongPressTimer->IsActive() )
+ {
+ iLongPressTimer->Cancel();
+ }
+ // start timer
+ iLongPressTimer->Start( KDefaultLongPressInterval, KDefaultLongPressInterval,
+ TCallBack( ReportLongPressL, this ) );
+
+ }
+
+// ----------------------------------------------------------------------------
+// Stop long press timer
+// ----------------------------------------------------------------------------
+//
+void CAknMessageReaderLongPressDetector::StopLongPressTimer()
+ {
+ if ( iLongPressTimer && iLongPressTimer->IsActive() )
+ {
+ iLongPressTimer->Cancel();
+ }
+ }
+
+// End of File.