libraries/iosrv/server/console.cpp
changeset 83 706c7a69e448
parent 69 849a0b46c767
--- a/libraries/iosrv/server/console.cpp	Thu Nov 04 20:51:05 2010 +0000
+++ b/libraries/iosrv/server/console.cpp	Thu Nov 04 23:22:39 2010 +0000
@@ -52,8 +52,9 @@
 	iRequestQueue.Close();
 	delete iImplementation;
 	delete iReader;
+	delete iConsoleSizeChangedNotifier;
 	iConsole.Close();
-	delete iCreationTitle ;
+	delete iCreationTitle;
 	iServerThread.Close();
 	}
 
@@ -99,10 +100,7 @@
 
 void CIoConsole::IorepReadL(MIoReader&)
 	{
-	if (!iReader->IsActive())
-		{
-		iReader->QueueRead();
-		}
+	QueueReaderIfRequired();
 	}
 
 void CIoConsole::IorepReadKeyL(MIoReader& aReader)
@@ -197,10 +195,6 @@
 		{
 		User::LeaveIfError(iConsole.SetLazyConstruct());
 		}
-	if (iConfig.ConsoleSizeDetect())
-		{
-		User::LeaveIfError(iConsole.SetConsoleSizeDetect());
-		}
 	if (aUnderlying)
 		{
 		User::LeaveIfError(aUnderlying->Open());
@@ -211,6 +205,7 @@
 	NewRequest(new(ELeave)TConsoleCreateRequest(*this));
 		
 	iReader = CConsoleReader::NewL(*this);
+	iConsoleSizeChangedNotifier = new(ELeave) CConsoleSizeChangedNotifier(*this);
 	}
 	
 void CIoConsole::CreateComplete(TInt aError)
@@ -276,16 +271,7 @@
 		{
 		if (reader->IorIsKeyCaptured(aKeyCode, aModifiers))
 			{
-			if (reader->IorReadPending())
-				{
-				TPtrC keyCodePtr((TUint16*)&aKeyCode, 1);
-				reader->IorReadBuf().Append(keyCodePtr);
-				reader->IorDataBuffered(1);
-				}
-			else
-				{
-				reader->IorReadKeyComplete(KErrNone, aKeyCode, aModifiers);
-				}
+			reader->IorReadKeyComplete(KErrNone, aKeyCode, aModifiers);
 			keyHandled = ETrue;
 			break;
 			}
@@ -306,6 +292,7 @@
 	TBool pendingReader(EFalse);
 	TInt index = 0;
 	MIoReader* reader = AttachedReader(index++);
+	TBool foregroundReader(ETrue);
 	while (reader)
 		{
 		if (reader->IorReadPending() || reader->IorReadKeyPending())
@@ -313,7 +300,13 @@
 			pendingReader = ETrue;
 			break;
 			}
+		if (foregroundReader && reader->IorAllKeysCaptured())
+			{
+			// If the foreground reader has captured all keys, we don't care about the background readers.
+			break;
+			}
 		reader = AttachedReader(index++);
+		foregroundReader = EFalse;
 		}
 
 	if (pendingReader && !iReader->IsActive())
@@ -841,11 +834,6 @@
 
 //______________________________________________________________________________
 //						RIoConsoleProxy
-TInt RIoConsoleProxy::SetConsoleSizeDetect()
-	{
-	return SendReceive(ESetConsoleSizeDetect);
-	}
-	
 TInt RIoConsoleProxy::SetLazyConstruct()
 	{
 	return SendReceive(ESetLazyConstruct);
@@ -871,6 +859,16 @@
 	SendReceive(EWriteStdErr, TIpcArgs(&aDescriptor), aStatus);
 	}
 
+void RIoConsoleProxy::NotifySizeChanged(TRequestStatus& aStatus)
+	{
+	SendReceive(ENotifySizeChange, TIpcArgs(), aStatus);
+	}
+
+void RIoConsoleProxy::CancelNotifySizeChanged()
+	{
+	SendReceive(ECancelNotifySizeChange, TIpcArgs());
+	}
+
 //______________________________________________________________________________
 //						CIoConsoleProxyServer
 CConsoleProxyServer* CIoConsoleProxyServerNewL(TAny* aParams)
@@ -983,6 +981,7 @@
 
 CIoConsoleProxySession::~CIoConsoleProxySession()
 	{
+	delete iSizeChangedMessageCompleter;
 	delete iUnderlyingConsole;
 	}
 
@@ -990,11 +989,6 @@
 	{
 	switch (aMessage.Function())
 		{
-	case RIoConsoleProxy::ESetConsoleSizeDetect:
-		if (iConsole) User::Leave(KErrNotReady); // too late!
-		SetFlag(EAutoDetectSize, ETrue);
-		aMessage.Complete(KErrNone);
-		return;
 	case RIoConsoleProxy::ESetLazyConstruct:
 		if (iConsole) User::Leave(KErrNotReady); // too late!
 		SetFlag(ELazy, ETrue);
@@ -1010,11 +1004,12 @@
 		OpenExistingL(aMessage);
 		return;	
 	case RConsoleProxy::EGetScreenSize:
-		if (GetFlag(EAutoDetectSize) && !GetFlag(ELazy))
+		if (GetFlag(EHaveDetectedSize))
 			{
 			DetectSizeL(aMessage);
 			return;
 			}
+		// Otherwise drop through to CConsoleProxySession's implementation
 		break;
 	case RIoConsoleProxy::EWriteStdErr:
 		{
@@ -1040,6 +1035,26 @@
 		aMessage.Complete(KErrNone);
 		return;
 		}
+	case RIoConsoleProxy::ENotifySizeChange:
+		{
+		if (iSizeChangedMessageCompleter == NULL)
+			{
+			iSizeChangedMessageCompleter = new(ELeave) CSizeChangeMessageCompleter;
+			if (iConsole) iSizeChangedMessageCompleter->SetConsole(iConsole->Console());
+			}
+		iSizeChangedMessageCompleter->NotifySizeChange(const_cast<RMessage2&>(aMessage));
+		return;
+		}
+	case RIoConsoleProxy::ECancelNotifySizeChange:
+		{
+		//RDebug::Printf("case RIoConsoleProxy::ECancelNotifySizeChange ");
+		if (iSizeChangedMessageCompleter)
+			{
+			iSizeChangedMessageCompleter->CancelNotify();
+			}
+		aMessage.Complete(KErrNone);
+		return;
+		}
 	default:
 		break;
 		}
@@ -1057,7 +1072,7 @@
 	MProxiedConsole* cons;
 	if (GetFlag(ELazy))
 		{
-		CLazyConsole* lazy = new(ELeave)CLazyConsole(iConsoleCreate, GetFlag(EAutoDetectSize));
+		CLazyConsole* lazy = new(ELeave) CLazyConsole(iConsoleCreate);
 		CleanupStack::PushL(lazy);
 		cons = MProxiedConsole::DefaultL(lazy);
 		CleanupStack::Pop();
@@ -1086,10 +1101,18 @@
 	
 void CIoConsoleProxySession::ConsoleCreatedL(MProxiedConsole* aConsole)
 	{
-	if (GetFlag(EAutoDetectSize) && !(GetFlag(ELazy)))
+	if (!GetFlag(ELazy))
 		{
-		iDetectedSize = DetectConsoleSize(aConsole->Console());
+		// If it's lazy, we can't check ReportedCorrectly until it's been instantiated
+		CConsoleBase* console = aConsole->Console();
+		if (!ConsoleSize::ReportedCorrectly(console))
+			{
+			iDetectedSize = DetectConsoleSize(console);
+			SetFlag(EHaveDetectedSize, ETrue);
+			}
 		}
+
+	if (iSizeChangedMessageCompleter) iSizeChangedMessageCompleter->SetConsole(aConsole->Console());
 	}
 
 void CIoConsoleProxySession::DetectSizeL(const RMessage2& aMessage)
@@ -1207,8 +1230,8 @@
 
 //______________________________________________________________________________
 //						CLazyConsole
-CLazyConsole::CLazyConsole(TConsoleCreateFunction aConsoleCreate, TBool aAutoDetectSize)
-	: iConsoleCreate(aConsoleCreate), iSizeAutoDetect(aAutoDetectSize)
+CLazyConsole::CLazyConsole(TConsoleCreateFunction aConsoleCreate)
+	: iConsoleCreate(aConsoleCreate)
 	{
 	}
 
@@ -1240,10 +1263,17 @@
 		iCreateError = iConsole->Create(iTitle, iSize);
 		User::RenameProcess(procName.Left(procName.Locate('['))); // ...so restore it just in case
 		}
-	if ((iCreateError == KErrNone) && iSizeAutoDetect)
+	if ((iCreateError == KErrNone) && !ConsoleSize::ReportedCorrectly(iConsole))
 		{
 		iDetectedSize = DetectConsoleSize(iConsole);
+		iHaveDetectedSize = ETrue;
 		}
+	if (iCreateError == KErrNone && iStatusForNotifySizeRequest != NULL)
+		{
+		ConsoleSize::NotifySizeChanged(iConsole, *iStatusForNotifySizeRequest);
+		iStatusForNotifySizeRequest = NULL;
+		}
+
 	if (iCreateError != KErrNone)
 		{
 		delete iConsole;
@@ -1341,7 +1371,7 @@
 	{
 	if (CheckCreated() == KErrNone)
 		{
-		if (iSizeAutoDetect)
+		if (iHaveDetectedSize)
 			{
 			return iDetectedSize;
 			}
@@ -1382,6 +1412,23 @@
 		*constructed = (iConsole != NULL);
 		return KErrNone;
 		}
+	else if (iConsole == NULL && aExtensionId == ConsoleMode::KSetConsoleModeExtension && (ConsoleMode::TMode)(TUint)a1 == ConsoleMode::EText)
+		{
+		// A console that isn't created yet will default to text mode anyway so we don't need to force instantiation. This works around an issue with iosrv calling ConsoleMode::Set even on the underlying console
+		return KErrNone;
+		}
+	else if (iConsole == NULL && aExtensionId == ConsoleSize::KConsoleSizeNotifyChangedExtension)
+		{
+		// Remember this notify for later
+		TRequestStatus* stat = (TRequestStatus*)a1;
+		//RDebug::Printf("Lazycons KConsoleSizeNotifyChangedExtension a1=%x iStatusForNotifySizeRequest=%x", a1, iStatusForNotifySizeRequest);
+		if (stat == NULL && iStatusForNotifySizeRequest != NULL)
+			{
+			User::RequestComplete(iStatusForNotifySizeRequest, KErrCancel);
+			}
+		iStatusForNotifySizeRequest = stat;
+		return KErrNone; // It's ok to say KErrNone now but complete the TRequestStatus with KErrExtensionNotSupported later
+		}
 	else 
 		{
 		TInt err = CheckCreated();
@@ -1392,3 +1439,100 @@
 		return err;
 		}
 	}
+
+//
+
+CIoConsole::CConsoleSizeChangedNotifier::CConsoleSizeChangedNotifier(CIoConsole& aConsole)
+	: CActive(CActive::EPriorityStandard), iConsole(aConsole)
+	{
+	CActiveScheduler::Add(this);
+	iConsole.iConsole.NotifySizeChanged(iStatus);
+	SetActive();
+	}
+
+CIoConsole::CConsoleSizeChangedNotifier::~CConsoleSizeChangedNotifier()
+	{
+	Cancel();
+	}
+
+void CIoConsole::CConsoleSizeChangedNotifier::RunL()
+	{
+	if (iStatus.Int() != KErrNone) // eg KErrExtensionNotSupported
+		{
+		return;
+		}
+
+	iConsole.iConsole.NotifySizeChanged(iStatus);
+	SetActive();
+
+	MIoReader* fg = iConsole.AttachedReader();
+	if (fg)
+		{
+		fg->IorReaderChange(RIoReadHandle::EConsoleSizeChanged);
+		}
+	}
+
+void CIoConsole::CConsoleSizeChangedNotifier::DoCancel()
+	{
+	//RDebug::Printf("Calling RIoConsoleProxt::CancelNotifySizeChanged");
+	iConsole.iConsole.CancelNotifySizeChanged();
+	}
+
+//
+
+CSizeChangeMessageCompleter::CSizeChangeMessageCompleter()
+	: CActive(CActive::EPriorityStandard)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CSizeChangeMessageCompleter::~CSizeChangeMessageCompleter()
+	{
+	Cancel();
+	}
+
+void CSizeChangeMessageCompleter::NotifySizeChange(RMessagePtr2& aMessage)
+	{
+	iMessage = aMessage;
+	if (iActualConsole)
+		{
+		ConsoleSize::NotifySizeChanged(iActualConsole, iStatus);
+		SetActive();
+		}
+	}
+
+void CSizeChangeMessageCompleter::RunL()
+	{
+	iMessage.Complete(iStatus.Int());
+	}
+
+void CSizeChangeMessageCompleter::DoCancel()
+	{
+	ASSERT(iActualConsole);
+	ConsoleSize::CancelNotifySizeChanged(iActualConsole);
+	}
+
+void CSizeChangeMessageCompleter::SetConsole(CConsoleBase* aConsole)
+	{
+	ASSERT(iActualConsole == NULL);
+	iActualConsole = aConsole;
+	if (!iMessage.IsNull())
+		{
+		ConsoleSize::NotifySizeChanged(iActualConsole, iStatus);
+		SetActive();
+		}
+	}
+
+void CSizeChangeMessageCompleter::CancelNotify()
+	{
+	//RDebug::Printf("CSizeChangeMessageCompleter::CancelNotify");
+	if (IsActive())
+		{
+		Cancel();
+		}
+	
+	if (!iMessage.IsNull())
+		{
+		iMessage.Complete(KErrCancel);
+		}
+	}