sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // The text cursor sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include "server.h" sl@0: #include "tcursor.h" sl@0: #include "windowgroup.h" sl@0: #include "wstop.h" sl@0: #include "panics.h" sl@0: #include "offscreenbitmap.h" sl@0: #include "EVENT.H" sl@0: #include "graphics/windowserverconstants.h" sl@0: sl@0: void RWsTextCursor::ConstructL(CWsWindowGroup *aGroupWin) sl@0: { sl@0: iInternalFlags = 0; sl@0: iGroupWin=aGroupWin; sl@0: iCustomTextCursor = NULL; sl@0: } sl@0: sl@0: void RWsTextCursor::Close() sl@0: { sl@0: iDrawRegion.Close(); sl@0: Cancel(); sl@0: } sl@0: sl@0: void RWsTextCursor::SetL(const TWsWinCmdSetTextCursor &aSet, TBool aClipped) sl@0: { sl@0: if (aSet.cursor.iType < TTextCursor::ETypeFirst || sl@0: (aSet.cursor.iType > TTextCursor::ETypeLast && sl@0: aSet.cursor.iType <= TTextCursor::ETypeLastBasic) || sl@0: (aSet.cursor.iFlags&static_cast(ETextCursorPrivateFlags))) sl@0: { sl@0: Cancel(); sl@0: iGroupWin->OwnerPanic(EWservPanicInvalidTextCursor); sl@0: } sl@0: else sl@0: { sl@0: CWsClientWindow* win = NULL; sl@0: iGroupWin->WsOwner()->HandleToClientWindow(aSet.window, &win); sl@0: sl@0: // Check window is a child of the group window sl@0: CWsWindowBase* searchWin = NULL; sl@0: for(searchWin=win; searchWin->WinType()!=EWinTypeGroup; searchWin=searchWin->BaseParent()) sl@0: {} sl@0: if (iGroupWin != searchWin) sl@0: { sl@0: Cancel(); sl@0: iGroupWin->OwnerPanic(EWservPanicWindow); sl@0: } sl@0: sl@0: TPoint pos(aSet.pos.iX, aSet.pos.iY-aSet.cursor.iAscent); sl@0: TSize size(aSet.cursor.iWidth, aSet.cursor.iHeight); sl@0: TUint flags = aSet.cursor.iFlags; sl@0: TInt type = aSet.cursor.iType; sl@0: TRect clipRect = iClipRect; sl@0: TRgb color = aSet.cursor.iColor; sl@0: CWsCustomTextCursor* customTextCursor = iCustomTextCursor; sl@0: TBool changed = EFalse; sl@0: sl@0: TPoint clipOrigo; sl@0: TSize clipSize; sl@0: sl@0: if (type > TTextCursor::ETypeLastBasic) sl@0: { sl@0: changed = ETrue; sl@0: sl@0: customTextCursor = CWsClient::FindCustomTextCursor(type); sl@0: if (!customTextCursor) sl@0: { sl@0: Cancel(); sl@0: iGroupWin->OwnerPanic(EWservPanicNoCustomTextCursor); sl@0: return; sl@0: } sl@0: sl@0: if( !customTextCursor->HasSpriteMember() ) sl@0: { sl@0: iGroupWin->OwnerPanic(EWservPanicNoSpriteMember); sl@0: return; sl@0: } sl@0: sl@0: TInt yAdjust=0; sl@0: switch (customTextCursor->Alignment()) sl@0: { sl@0: case RWsSession::ECustomTextCursorAlignTop: sl@0: break; sl@0: case RWsSession::ECustomTextCursorAlignBaseline: sl@0: yAdjust = aSet.cursor.iAscent-1; sl@0: break; sl@0: case RWsSession::ECustomTextCursorAlignBottom: sl@0: yAdjust = aSet.cursor.iHeight-1; sl@0: break; sl@0: default: sl@0: Cancel(); sl@0: iGroupWin->OwnerPanic(EWservPanicCustomTextCursorAlign); sl@0: return; sl@0: } sl@0: pos.iY += yAdjust; sl@0: // Start with a clipping rect to be the whole window sl@0: // relative cursor pos and shrink down to what we want sl@0: clipOrigo = -pos; sl@0: clipSize = win->Size(); sl@0: if (flags & TTextCursor::EFlagClipHorizontal) sl@0: { sl@0: clipOrigo.iX = 0; sl@0: clipSize.iWidth = size.iWidth; sl@0: } sl@0: if (flags & TTextCursor::EFlagClipVertical) sl@0: { sl@0: clipOrigo.iY = -yAdjust; sl@0: clipSize.iHeight = aSet.cursor.iHeight; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: customTextCursor = NULL; sl@0: } sl@0: sl@0: if (aClipped) sl@0: { sl@0: flags|=ETextCursorFlagClipped; sl@0: clipRect=aSet.rect; sl@0: } sl@0: sl@0: if (pos != iPos || size != iSize || iType != type || sl@0: flags != iFlags || clipRect != iClipRect || color != iColor || sl@0: customTextCursor != iCustomTextCursor || win != iWin) sl@0: { sl@0: // There is a change in the cursor. sl@0: changed = ETrue; sl@0: } sl@0: sl@0: if (iInternalFlags&EHasFocus && changed) sl@0: { sl@0: TCursorSprite::Hide(); sl@0: } sl@0: sl@0: iPos = pos; sl@0: iSize = size; sl@0: iType = type; sl@0: iFlags= flags; sl@0: iClipRect = clipRect; sl@0: iColor = color; sl@0: iCustomTextCursor = customTextCursor; sl@0: iWin = win; sl@0: if (customTextCursor && iInternalFlags&EHasFocus) sl@0: { sl@0: customTextCursor->CompleteL(win, !(flags&TTextCursor::EFlagNoFlash), flags & (TTextCursor::EFlagClipHorizontal | TTextCursor::EFlagClipVertical), clipOrigo, clipSize); sl@0: customTextCursor->SetPositionNoRedraw(pos); sl@0: } sl@0: sl@0: if (iInternalFlags&EHasFocus && changed) sl@0: { sl@0: TCursorSprite::SetCurrentCursor(this, win); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void RWsTextCursor::Cancel() sl@0: { sl@0: if (iType!=TTextCursor::ETypeNone) sl@0: { sl@0: if (iInternalFlags&EHasFocus) sl@0: TCursorSprite::SetFocus(NULL); sl@0: iType=TTextCursor::ETypeNone; sl@0: iWin=NULL; sl@0: } sl@0: } sl@0: sl@0: void RWsTextCursor::Disable() sl@0: { sl@0: if (iWin) sl@0: { sl@0: TCursorSprite::Hide(); sl@0: } sl@0: } sl@0: sl@0: void RWsTextCursor::Enable() sl@0: { sl@0: if (iWin) sl@0: { sl@0: TCursorSprite::Reveal(); sl@0: } sl@0: } sl@0: sl@0: void RWsTextCursor::LostFocus() sl@0: { sl@0: TCursorSprite::SetFocus(NULL); sl@0: iInternalFlags &= ~EHasFocus; sl@0: } sl@0: sl@0: void RWsTextCursor::ReceivedFocus() sl@0: { sl@0: iInternalFlags |= EHasFocus; sl@0: if (iType!=TTextCursor::ETypeNone && iWin) sl@0: { sl@0: TCursorSprite::SetFocus(this,iWin); sl@0: if (iCustomTextCursor) sl@0: { sl@0: iCustomTextCursor->SetPositionNoRedraw(iPos); sl@0: } sl@0: } sl@0: } sl@0: sl@0: TRect RWsTextCursor::RectRelativeToScreen() const sl@0: { sl@0: TRect rect; sl@0: rect.iTl=iPos+iWin->Origin(); sl@0: rect.iBr=rect.iTl+iSize; sl@0: return(rect); sl@0: } sl@0: sl@0: void RWsTextCursor::doDraw(CFbsBitGc* aGc, const TRegion& aRegion) sl@0: { sl@0: TRegionFix<1> justInCase; sl@0: const TRegion *pr= &aRegion; sl@0: if (aRegion.CheckError()) sl@0: { sl@0: justInCase.AddRect(iWin->AbsRect()); sl@0: pr= &justInCase; sl@0: } sl@0: if (!pr->IsEmpty()) sl@0: { sl@0: aGc->SetUserDisplayMode(iWin->DisplayMode()); sl@0: aGc->SetDitherOrigin(iWin->Origin()); sl@0: aGc->SetDrawMode(CGraphicsContext::EDrawModeXOR); sl@0: switch (iType) sl@0: { sl@0: case TTextCursor::ETypeRectangle: sl@0: { sl@0: aGc->SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: aGc->SetPenStyle(CGraphicsContext::ENullPen); sl@0: aGc->SetBrushColor(iColor); sl@0: } sl@0: break; sl@0: case TTextCursor::ETypeHollowRectangle: sl@0: { sl@0: aGc->SetBrushStyle(CGraphicsContext::ENullBrush); sl@0: aGc->SetPenStyle(CGraphicsContext::ESolidPen); sl@0: aGc->SetPenColor(iColor); sl@0: } sl@0: break; sl@0: default: sl@0: WS_PANIC_ALWAYS(EWsPanicInvalidCursorType); sl@0: } sl@0: aGc->SetClippingRegion(pr); sl@0: aGc->DrawRect(RectRelativeToScreen()); sl@0: aGc->SetUserDisplayMode(ENone); sl@0: sl@0: TWindowServerEvent::NotifyScreenDrawingEvent(pr); sl@0: } sl@0: } sl@0: sl@0: void RWsTextCursor::Draw(CFbsBitGc* aGc, const TRegion& aRegion) sl@0: { sl@0: iDrawRegion.Copy(iWin->VisibleRegion()); sl@0: if (iFlags&ETextCursorFlagClipped) sl@0: { sl@0: TRect rect(iClipRect); sl@0: rect.Move(iWin->Origin()); sl@0: iDrawRegion.ClipRect(rect); sl@0: } sl@0: sl@0: // Need to clip against a possible recent screen size change. sl@0: iDrawRegion.ClipRect(iWin->Screen()->DrawDevice()->SizeInPixels()); sl@0: sl@0: sl@0: RWsRegion tmpRegion; sl@0: tmpRegion.Intersection(iDrawRegion, aRegion); sl@0: if (tmpRegion.CheckError()) sl@0: doDraw(aGc, iDrawRegion); sl@0: else sl@0: { sl@0: if (!tmpRegion.IsEmpty()) sl@0: { sl@0: doDraw(aGc, tmpRegion); sl@0: } sl@0: } sl@0: tmpRegion.Close(); sl@0: } sl@0: sl@0: void RWsTextCursor::WindowDisconnected(CWsWindow *aWindow) sl@0: { sl@0: if (iWin==aWindow) sl@0: Cancel(); sl@0: } sl@0: sl@0: TBool RWsTextCursor::IsStandardCursorActive() sl@0: { sl@0: return TCursorSprite::IsStandardCursorActive(); sl@0: } sl@0: sl@0: TBool RWsTextCursor::IsFlashing() const sl@0: { sl@0: return !(iFlags&TTextCursor::EFlagNoFlash); sl@0: } sl@0: sl@0: void RWsTextCursor::ScheduleReDrawNow() sl@0: { sl@0: iGroupWin->Screen()->ScheduleAnimation(RectRelativeToScreen(), 0, 0, 0); sl@0: } sl@0: sl@0: sl@0: // Cursor sprite handling sl@0: sl@0: TBool TCursorSprite::iHidden=ETrue; sl@0: RWsTextCursor *TCursorSprite::iCurrentCursor=NULL; sl@0: sl@0: // sl@0: sl@0: // Hide / Reveal text cursors. sl@0: void TCursorSprite::Hide() sl@0: { sl@0: if (!iHidden && iCurrentCursor) sl@0: { sl@0: iHidden=ETrue; sl@0: if (iCurrentCursor->iCustomTextCursor) sl@0: { sl@0: iCurrentCursor->iCustomTextCursor->Deactivate(); sl@0: } sl@0: else sl@0: { sl@0: iCurrentCursor->ScheduleReDrawNow(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void TCursorSprite::Reveal() sl@0: { sl@0: if(iHidden && iCurrentCursor) sl@0: { sl@0: iHidden=EFalse; sl@0: if (iCurrentCursor->iCustomTextCursor) sl@0: { sl@0: iCurrentCursor->iCustomTextCursor->Activate(); sl@0: } sl@0: else sl@0: { sl@0: iCurrentCursor->ScheduleReDrawNow(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void TCursorSprite::SetFocus(RWsTextCursor* aFocus,CWsClientWindow* aWin/*=NULL*/) sl@0: { sl@0: if (iCurrentCursor!=aFocus) sl@0: { sl@0: Hide(); sl@0: SetCurrentCursor(aFocus, aWin); sl@0: } sl@0: } sl@0: sl@0: void TCursorSprite::SetCurrentCursor(RWsTextCursor* aFocus, CWsClientWindow* aWin) sl@0: { sl@0: iCurrentCursor = aFocus; sl@0: if (aWin && iCurrentCursor && iCurrentCursor->iCustomTextCursor) sl@0: { sl@0: iCurrentCursor->iCustomTextCursor->SetWindow(aWin); sl@0: } sl@0: Reveal(); sl@0: } sl@0: sl@0: TBool TCursorSprite::IsStandardCursorActive() sl@0: { sl@0: return iCurrentCursor && !iCurrentCursor->iCustomTextCursor && !iHidden; sl@0: } sl@0: