×

Discussion Board

Results 1 to 13 of 13
  1. #1
    Regular Contributor
    Join Date
    May 2008
    Posts
    90

    Question RWsSession in a console/headless application

    Hi,

    I'm working on a background application and have to use RWsSession to send key events to another application, but it doesn't seem to work. I tried several methods suggested in the wiki (http://wiki.forum.nokia.com/index.ph...ate_a_keypress) with no luck. I tried the TKeyEvent and both TRawEvent approaches (using UserSvr and RWsSession), but neither produced any results.

    The TKeyEvent approach, that I tried last, behaves in an interesting way: I connect to the WS using the following code:
    RWsSession ws;
    UserLeaveIfError( ws.Connect() );
    The code does not leave. Then I send the event using ws.SimulateEvent and in the end I call ws.Flush() which never returns. Also int the other experiments I found that RWsSession.Close() would do the same: when I pushed it to the cleanup stack using CleanupClosePushL, the PopAndDestroy() call would block infinitely.

    Is there any special magic that has to be done so that I can connect to the window server from a non-gui application? The WS is running, because I'm starting the application from the phone menu (it has a launcher icon both in the emulator and on the real phone), so I'm not running the whole emulator in console mode, just this app.

    It's quite strange that the RWsSession seems to connect without any problem and then it freezes. Maybe it needs some active object magic?

    Thanks,
    Laszlo

  2. #2
    Registered User
    Join Date
    Oct 2007
    Posts
    20

    Re: RWsSession in a console/headless application

    Maybe you need SwEvent capabilities.

  3. #3
    Regular Contributor
    Join Date
    May 2008
    Posts
    90

    Re: RWsSession in a console/headless application

    Sure and I have it. The SIS is self signed and does have SwEvent capability. I guess if there was a problem with it then the SimulateEvent methods would panic or something, but they don't. The problem is explicitly with the Flush and Close calls.

  4. #4
    Registered User
    Join Date
    Mar 2005
    Posts
    29

    Re: RWsSession in a console/headless application

    Although I don't have the solution of your problem, I do experience the same problem once.

    It seems it is quite safe only listening to any window events in a console application using RWsSession. But, that is all. ;-)

  5. #5
    Regular Contributor
    Join Date
    May 2008
    Posts
    90

    Re: RWsSession in a console/headless application

    Thanks. It doesn't sound too good. II wonder if it's a bug or just a shortcoming of the documentation.

  6. #6
    Regular Contributor
    Join Date
    Apr 2008
    Posts
    217

    Re: RWsSession in a console/headless application

    Hi Atleta,

    In my console exe i had a scenario to simulate right soft key and I am using code below which works perfect on my N95. Not sure if this will help you but here it is for your reference.

    Code:
    void MyClass::RightSoftKeyPressL()
    {
    
        TWsEvent        event;
        RWsSession      wsSession;
    
        User::LeaveIfError(wsSession.Connect());
    
        TInt id = wsSession.GetFocusWindowGroup();
        event.SetType(EEventKey);
        event.SetTimeNow();
        event.Key()->iCode = EKeyDevice1;
        event.Key()->iModifiers = 0;
        event.Key()->iRepeats = 0;
        event.Key()->iScanCode = EStdKeyDevice1;
        wsSession.SendEventToWindowGroup(id, event);
        wsSession.Close();
    
    }

  7. #7
    Regular Contributor
    Join Date
    May 2008
    Posts
    90

    Re: RWsSession in a console/headless application

    Hi,

    did you manage to do this from a non-GUI application?

  8. #8
    Super Contributor
    Join Date
    Nov 2004
    Location
    Wiltshire, UK
    Posts
    3,644

    Re: RWsSession in a console/headless application

    The problem is here
    The SIS is self signed and does have SwEvent capability.
    You have to use Symbian signed online or a devcert, SWEvent is not a self granted capability.
    Both the devcert and the MMP file and any DLL's you are loading into your process all require SWEvent.
    Download Symbian OS now! [url]http://developer.symbian.org[/url]

  9. #9
    Regular Contributor
    Join Date
    Apr 2008
    Posts
    217

    Re: RWsSession in a console/headless application

    did you manage to do this from a non-GUI application?
    Yes, but ofcourse I am using dev cert. As correctly pointed by Paul SwEvent capability requires dev cert. Self signed won't work. BTW my headless app captures keys in background so I added SwEvent capability for that purpose initially and might be working for this also. I haven't specifically tested if this require SwEvent capability for sure.
    Last edited by gailu; 2009-01-05 at 16:17.

  10. #10
    Regular Contributor
    Join Date
    May 2008
    Posts
    90

    Re: RWsSession in a console/headless application

    You're right, but unfortunately that wasn't the problem. Actually the self signing howto in the wiki (http://wiki.forum.nokia.com/index.ph...gn_Certificate) says that if my app requests a capability that needs stronger-than-self signature than it wouldn't install, but actually it does. I have SwEvent in my MMP file and the phones happily install it even self signed. (I thought it would panic, but it doesn't make a difference.) Anyway, I tried open signed and the result is the same. I guess it has something to do with threading/active objects. As my app is a console one it does not have an event loop or anything.

    Actually thinking it further, I might just be sending the events to myself... I thought that it would go to the foreground application, but looking at the code sent by gailu it seems that tehe the foreground app needs to be addressed explicitly. I'll give that a try as well. Anyway it's strange that despite what the documentation says I was able to install an application with a wrong capability/certificate combo. (It might be that the wiki is wrong.)

  11. #11
    Registered User
    Join Date
    Mar 2005
    Posts
    29

    Smile Re: RWsSession in a console/headless application

    A recent update.

    The capturing and the sending back of key event is working now on a headless console exe application. Sending back the event is just described in the previous post(in my case, I capture the right soft key while in the menu list; but not all keys and applications can promise to work this way, the red "No" key with the phone app, for example). Although this event is not generated from my application, just captured.

    You would better use DEV certification with required capabilities specified in MMP to make it work. According to my experience, the installation will go fine, but the actual invoke of capability required API will fail and give a return value of -46(KErrPermissionDenied), not 0(KErrNone).

    The capture code is as follows, the code style is a little weird(I don't use NewL and NewLC here, and the ConstuctL is actually invoked directly in constructor), hope the logging message will help too:

    header:
    Code:
    #ifndef CWSEVENTCAPTURER_H_
    #define CWSEVENTCAPTURER_H_
    
    #include <W32STD.H>
    #include <e32keys.h>
    #include <flogger.h>
    
    class MWsEventCallBack 
    {
    public:
    	virtual TBool KeyDownCapturedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
    	virtual TBool KeyUpCapturedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
    	virtual TBool KeyCapturedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
    	virtual TBool WindowGroupListChangedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
    };
    
    
    enum KeyCapturerId {
    	KeyCapturerA,
    	KeyCapturerB,
    };
    
    class CWsEventCapturer : public CActive 
    {
    public:
    	CWsEventCapturer(MWsEventCallBack& aObserver);
    	virtual ~CWsEventCapturer();
    	
    private:
    	void ConstructL();
    	
    public:
    	void SetCaptureKey(KeyCapturerId aId, TStdScanCode aScanCode, TKeyCode aKeyCode);
    	
    	
    private:
    	void RunL();
    	void DoCancel();
    	void Listen();
    	
    public:
    	void StopKeyEventCapture(KeyCapturerId aId);
    	void StartKeyEventCapture(KeyCapturerId aId);
    	
    private:
    	
    	MWsEventCallBack& 	iObserver;
    
    #ifdef __FLOGGER__
    	RFileLogger iFileLogger;
    #endif
    	
    	TKeyCode iCaptureKeyCodeA;
    	TStdScanCode iCaptureKeyScanCodeA;
    	
    	TInt 			iKeyEventHandleA;
    	TInt			iKeyUpAndDownEventHandleA;
    	
    	TKeyCode iCaptureKeyCodeB;
    	TStdScanCode iCaptureKeyScanCodeB;
    	
    	TInt 			iKeyEventHandleB;
    	TInt			iKeyUpAndDownEventHandleB;
    	
    	RWsSession     	iWsSession;
    	RWindowGroup    iWg; 
    };
    
    #endif /*CWSEVENTCAPTURER_H_*/
    source:
    Code:
    #include "CWsEventCapturer.h"
    #include <APGWGNAM.H>
    
    
    CWsEventCapturer::CWsEventCapturer(MWsEventCallBack& aObserver) 
    	: CActive(EPriorityStandard),
    	iObserver(aObserver),
    	iCaptureKeyCodeA(EKeyNull),
    	iCaptureKeyScanCodeA(EStdKeyNull),
    	iCaptureKeyCodeB(EKeyNull),
    	iCaptureKeyScanCodeB(EStdKeyNull),
    	iKeyEventHandleA(-1),
    	iKeyUpAndDownEventHandleA(-1),
    	iKeyEventHandleB(-1),
    	iKeyUpAndDownEventHandleB(-1) {
    	
    	ConstructL();
    }
     
    CWsEventCapturer::~CWsEventCapturer()
    {	
    	StopKeyEventCapture(KeyCapturerA);
    	StopKeyEventCapture(KeyCapturerB);
    	
    	if (IsActive()) {
    		Cancel();
    	}
    	
    	iWg.Close();
    	iWsSession.Close();
    #ifdef __FLOGGER__
    	iFileLogger.Close();
    #endif
    }
    
    void CWsEventCapturer::SetCaptureKey(KeyCapturerId aId, TStdScanCode aScanCode, TKeyCode aKeyCode) {
    	switch (aId) {
    	case KeyCapturerA:
    		iCaptureKeyScanCodeA = aScanCode;
    		iCaptureKeyCodeA = aKeyCode;
    		break;
    	case KeyCapturerB:
    		iCaptureKeyScanCodeB = aScanCode;
    		iCaptureKeyCodeB = aKeyCode;
    		break;
    	}
    }
    
    
    void CWsEventCapturer::StartKeyEventCapture(KeyCapturerId aId) {
    #define __INT32_MAX__ 0x7fffffffL
    #define __INT32_MIN__ (-__INT32_MAX__ - 1L)
    
    	switch (aId) {
    	case KeyCapturerA:
    		if (iKeyUpAndDownEventHandleA < 0 && iCaptureKeyScanCodeA != EStdKeyNull) {
    			iKeyUpAndDownEventHandleA = iWg.CaptureKeyUpAndDowns(iCaptureKeyScanCodeA, 0, 0/*, __INT32_MIN__*/);
    		}
    		
    		if (iKeyEventHandleA < 0 && iCaptureKeyCodeA != EKeyNull) {
    			iKeyEventHandleA = iWg.CaptureKey(iCaptureKeyCodeA, 0, 0/*, __INT32_MIN__*/);
    		}
    		break;
    	case KeyCapturerB:
    		if (iKeyUpAndDownEventHandleB < 0 && iCaptureKeyScanCodeB != EStdKeyNull) {
    			iKeyUpAndDownEventHandleB = iWg.CaptureKeyUpAndDowns(iCaptureKeyScanCodeB, 0, 0/*, __INT32_MIN__*/);
    		}
    		
    		if (iKeyEventHandleB < 0 && iCaptureKeyCodeB != EKeyNull) {
    			iKeyEventHandleB = iWg.CaptureKey(iCaptureKeyCodeB, 0, 0/*, __INT32_MIN__*/);
    		}
    		break;
    	}
    	
    #ifdef __FLOGGER__	
    	iFileLogger.WriteFormat(_L("capture started, keyA up/down handle: %d, keyA event handle: %d"), iKeyUpAndDownEventHandleA, iKeyEventHandleA);
    	iFileLogger.WriteFormat(_L("capture started, keyB up/down handle: %d, keyB event handle: %d"), iKeyUpAndDownEventHandleB, iKeyEventHandleB);
    #endif
    	
    //	Listen();
    }
    
    void CWsEventCapturer::StopKeyEventCapture(KeyCapturerId aId) {
    //	if (IsActive()) {
    //		Cancel();
    //	}
    	
    	switch (aId) {
    	case KeyCapturerA:
    		if(iKeyEventHandleA >= 0) {
    			iWg.CancelCaptureKey(iKeyEventHandleA);
    			iKeyEventHandleA = -1;
    		}
    		if (iKeyUpAndDownEventHandleA >= 0) {
    			iWg.CancelCaptureKeyUpAndDowns(iKeyUpAndDownEventHandleA);
    			iKeyUpAndDownEventHandleA = -1;
    		}
    		break;
    	case KeyCapturerB:
    		if(iKeyEventHandleB >= 0) {
    			iWg.CancelCaptureKey(iKeyEventHandleB);
    			iKeyEventHandleB = -1;
    		}
    		if (iKeyUpAndDownEventHandleB >= 0) {
    			iWg.CancelCaptureKeyUpAndDowns(iKeyUpAndDownEventHandleB);
    			iKeyUpAndDownEventHandleB = -1;
    		}
    		break;
    	}
    	
    #ifdef __FLOGGER__
    	iFileLogger.WriteFormat(_L("capture stopped, keyA up/down handle: %d, keyA event handle: %d"), iKeyUpAndDownEventHandleA, iKeyEventHandleA);
    	iFileLogger.WriteFormat(_L("capture started, keyB up/down handle: %d, keyB event handle: %d"), iKeyUpAndDownEventHandleB, iKeyEventHandleB);
    #endif
    }
    
    void CWsEventCapturer::ConstructL()
    {
    #ifdef __FLOGGER__
    	iFileLogger.Connect();
    	iFileLogger.CreateLog(TPtrC((const TUint16 *) L"extkman"), TPtrC((const TUint16 *) L"swcap.txt"), EFileLoggingModeOverwrite);
    	iFileLogger.SetDateAndTime( EFalse, ETrue );
    	
    	iFileLogger.WriteFormat(_L("window event capturer inited"));
    #endif
    	
    	CActiveScheduler::Add(this);
    	
    	User::LeaveIfError(iWsSession.Connect());
     
    	iWg = RWindowGroup(iWsSession);
    	User::LeaveIfError(iWg.Construct((TUint32)&iWg, EFalse));
    	iWg.SetOrdinalPosition(-1);
    	iWg.EnableReceiptOfFocus(EFalse);
    	
    	int err = 0;
    	err = iWg.EnableOnEvents(EEventControlAlways);
    	err = iWg.EnableGroupListChangeEvents();
     
    	CApaWindowGroupName* wn=CApaWindowGroupName::NewLC(iWsSession);
    	wn->SetHidden(ETrue);
    	wn->SetWindowGroupName(iWg);
    	CleanupStack::PopAndDestroy();//wn
    	
    	Listen();
    }
     
    void CWsEventCapturer::RunL()
    {
    	if (iStatus == KErrNone) 
    	{
    		TWsEvent e;
    		iWsSession.GetEvent(e);
    #ifdef __FLOGGER__
    		iFileLogger.WriteFormat(_L("event type: %d"), e.Type());
    		if (e.Key()) {
    			iFileLogger.WriteFormat(_L("key code: %d, key scan code: %d"), e.Key()->iCode, e.Key()->iScanCode);
    		}
    #endif
    		
    		switch (e.Type()) {
    		case EEventKeyUp:
    			if (iObserver.KeyUpCapturedL(e, iWsSession)) {	
    				TInt wgId = iWsSession.GetFocusWindowGroup();
    				iWsSession.SendEventToWindowGroup(wgId, e);
    			}
    			break;
    		case EEventKeyDown:
    			if (iObserver.KeyDownCapturedL(e, iWsSession)) {	
    				TInt wgId = iWsSession.GetFocusWindowGroup();
    				iWsSession.SendEventToWindowGroup(wgId, e);
    			}
    			break;
    		case EEventKey:
    			if (iObserver.KeyCapturedL(e, iWsSession)) {	
    				TInt wgId = iWsSession.GetFocusWindowGroup();
    				iWsSession.SendEventToWindowGroup(wgId, e);
    			}
    			break;
    		case EEventWindowGroupListChanged:
    			iObserver.WindowGroupListChangedL(e, iWsSession);
    			break;
    		default:
    			break;
    
    		}
    	}
    	
    	if (iStatus != KErrCancel) 
    	{
    		Listen();
    	}
    }
     
    void CWsEventCapturer::DoCancel()
    {
    	iWsSession.EventReadyCancel();
    }
     
    void CWsEventCapturer::Listen()
    {
    	if (!IsActive()) {
    		iWsSession.EventReady(&iStatus);
    		SetActive();
    	}
    }

  12. #12
    Regular Contributor
    Join Date
    May 2008
    Posts
    90

    Re: RWsSession in a console/headless application

    I was also able to make it work, indeed the problem was with using a self signed certificate. Even the version that went into an infinite blocking (that used RWsSession.SimulateKeyEvent and Flush) runs know, though it still does not do anything. However the other undocumented SimulateRawKeyEvent does work just as UserSvr::AddEvent.

    After reading your post I discovered that (this is not java and) the error would probably be reported in the return value in the case of UserSvr::AddEvent. I say probably, because it's not documented, but returns a TInt. However the SimulateXEvent versions do not report errors at all.

    I also tried the code posted by gailu, but it didn't work for some reason. The app just doesn't seem to receive the keypress. But then it might be that I messed something up, so I'll give it another try tomorrow. However, what I can say for sure (and for the record) is that using the undocumented (and thus risky) RWsSession.SimulateRawEvent and UserSvr::AddEvent both worked for me if the app was signed with the correct cert. I used Open Signed online and the opensignsis.py script to save me some typing and clicking.

    What I could see as a difference between the RWsSession and the UserSvr version is that the latter one caused some extra screen/app changes, while the former just worked.

    Thanks everybody!

  13. #13
    Regular Contributor
    Join Date
    May 2008
    Posts
    90

    Re: RWsSession in a console/headless application

    The code for the two methods that I was able to make work is the following:

    Code:
    void SomeClass::SendKey( TStdScanCode key )
            {
            TRawEvent ev;
            ev.Set( TRawEvent::EKeyDown, key );
            UserSvr::AddEvent( ev );
    
            User::After( 1000000 ); // 1s, could be less
            TRawEvent ev1;
            ev1.Set( TRawEvent::EKeyUp, key );
            UserSvr::AddEvent( ev1 );
            }
    and

    Code:
    void SomeClass::SendKey( TStdScanCode key )
            {
            RWsSession ws;
            User::LeaveIfError( ws.Connect() );
            CleanupClosePushL(ws);
            TRawEvent ev1;
            ev1.Set( TRawEvent::EKeyDown, key );
            ws.SimulateRawEvent( ev1 );
            User::After( 1000000 ); // 1s
            TRawEvent ev2;
            ev2.Set( TRawEvent::EKeyUp, key );
            ws.SimulateRawEvent( ev2 );
            CleanupStack::PopAndDestroy(&ws);
            }

Similar Threads

  1. AutoStart My application at bootup
    By prakashs in forum Symbian
    Replies: 7
    Last Post: 2009-03-24, 10:06
  2. Replies: 37
    Last Post: 2008-07-16, 05:17
  3. Replies: 1
    Last Post: 2008-05-08, 12:32
  4. 3250: Too many SMSs received crash the application
    By kewldeep in forum Mobile Java General
    Replies: 4
    Last Post: 2007-01-27, 00:00
  5. Replies: 0
    Last Post: 2005-05-28, 10:20

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×