javauis/lcdui_akn/lcdui/src/CMIDCanvas.cpp
branchRCL_3
changeset 24 6c158198356e
parent 23 e5618cc85d74
--- a/javauis/lcdui_akn/lcdui/src/CMIDCanvas.cpp	Thu Jul 15 18:31:06 2010 +0300
+++ b/javauis/lcdui_akn/lcdui/src/CMIDCanvas.cpp	Thu Aug 19 09:48:13 2010 +0300
@@ -134,6 +134,16 @@
     TRect iRect;
 };
 
+// ---------------------------------------------------------------------------
+// TLcduiEvent
+// ---------------------------------------------------------------------------
+//
+enum TLcduiEvent
+{
+    EFixUIOrientation,
+    EUnFixUIOrientation,
+    EVideoAdded
+};
 
 // ======== LOCAL FUNCTIONS ========
 
@@ -159,9 +169,15 @@
 // @param aDestRect Destination rect.
 // ---------------------------------------------------------------------------
 //
-inline TBool IsDownScaling(const TSize& aSourceSize, const TRect& aDestRect, TBool aM3GContent)
+TBool CMIDCanvas::IsDownScaling(const TSize& aSourceSize, const TRect& aDestRect,TBool aM3GContent) const
 {
     // if m3G is drawing then downscaling is turn off
+    // Send event in case of the M3G draw.
+    if (iM3GContent != iPrevM3GContent)
+    {
+        PostEvent(EM3GDraw, iM3GContent, 0);
+    }
+    iPrevM3GContent=iM3GContent;
     if (aM3GContent)
     {
         return EFalse;
@@ -176,7 +192,7 @@
 // @param aSourceSize Source rect size.
 // @param aDestRect Destination rect.
 // ---------------------------------------------------------------------------
-inline TBool IsDownScaling(const TSize& aSourceSize, const TRect& aDestRect)
+TBool CMIDCanvas::IsDownScaling(const TSize& aSourceSize, const TRect& aDestRect) const
 {
     return (aSourceSize.iWidth > aDestRect.Width() ||
             aSourceSize.iHeight > aDestRect.Height());
@@ -304,7 +320,7 @@
     }
 
 #ifdef RD_JAVA_NGA_ENABLED
-    CloseEgl();
+    CloseEgl(EFalse);
     DisposePixelSource();
     delete[] iTexturePixels;
     delete[] iVertexArray;
@@ -832,9 +848,9 @@
     TInt& /* aCycles */,
     java::util::Monitor* aMonitor)
 {
-    if (!iForeground)
-    {
-        DEBUG("CMIDCanvas::ProcessL() - not foreground");
+
+    if (!iForeground && iFirstPaintState == EFirstPaintNeverOccurred)
+    {
         ASSERT(!iAlfMonitor);
         aRead = aEnd;
         return EFalse;
@@ -844,9 +860,12 @@
     {
     case EDrwOpcM3GContentStart:
     {
+        // EGL surface is created if canvas window is currently visible
+        // even if MIDlet would be on background.
         if (!iM3GContent &&
                 i3DAccelerated &&
-                iDirectContents.Count() == 0)
+                iDirectContents.Count() == 0 &&
+                IsWindowVisible())
         {
             DEBUG("CMIDCanvas::ProcessL - M3G content start");
             iM3GContent = ETrue;
@@ -911,7 +930,7 @@
     return iFrameReady;
 }
 
-#else // RD_JAVA_NGA_ENABLED 
+#else // RD_JAVA_NGA_ENABLED
 
 // ---------------------------------------------------------------------------
 // From class MMIDBufferProcessor.
@@ -1090,11 +1109,9 @@
         PostEvent(EPaint, posPacked, sizePacked);
     }
 
-    // If is added first direct content, then NGA is switched off
-    // and move of iViewRect is needed.
-    if (iFullScreen && iScalingOn && iDirectContents.Count() == 1)
-    {
-        iViewRect.Move(-iPositionRelativeToScreen);
+    if (iDirectContents.Count() > 0)
+    {
+        iEnv.ToLcduiObserver().InvokeLcduiEvent(*this, EVideoAdded);
     }
 #endif // RD_JAVA_NGA_ENABLED
 }
@@ -1117,14 +1134,6 @@
         if (iDirectContents.Count() == 0)
         {
             iRestoreContentWhenUnfaded = EFalse;
-#ifdef RD_JAVA_NGA_ENABLED
-            // If is removed last direct content, then NGA is switched on
-            // and move of iViewRect is needed.
-            if (iScalingOn && iFullScreen)
-            {
-                iViewRect.Move(iPositionRelativeToScreen);
-            }
-#endif // RD_JAVA_NGA_ENABLED
         }
     }
 }
@@ -1284,11 +1293,55 @@
 //
 void CMIDCanvas::MdcNotifyContentAdded()
 {
-    DisposePixelSource();
-    CloseEgl();
+    // no implementation
 }
 #endif // RD_JAVA_NGA_ENABLED
 
+// ---------------------------------------------------------------------------
+// From class MDirectContainer.
+// CMIDCanvas::MdcFixUIOrientation(TBool aEnableFix)
+// ---------------------------------------------------------------------------
+//
+void CMIDCanvas::MdcFixUIOrientation(TBool aEnableFix)
+{
+    if (aEnableFix)
+    {
+        iEnv.ToLcduiObserver().InvokeLcduiEvent(*this, EFixUIOrientation);
+    }
+    else
+    {
+        iEnv.ToLcduiObserver().InvokeLcduiEvent(*this, EUnFixUIOrientation);
+    }
+}
+
+// ---------------------------------------------------------------------------
+// From class MMIDLcduiEventConsumer.
+// CMIDCanvas::HandleLcduiEvent(int aType)
+// ---------------------------------------------------------------------------
+//
+void CMIDCanvas::HandleLcduiEvent(int aType)
+{
+    if (!iDisplayable)
+    {
+        return;
+    }
+
+    switch (aType)
+    {
+    case EFixUIOrientation:
+        iDisplayable->FixOrientation();
+        break;
+    case EUnFixUIOrientation:
+        iDisplayable->ReleaseOrientation();
+        break;
+    case EVideoAdded:
+#ifdef RD_JAVA_NGA_ENABLED
+        DisposePixelSource();
+        CloseEgl(IsGameCanvas());
+#endif // RD_JAVA_NGA_ENABLED
+        break;
+    }
+}
 
 // ---------------------------------------------------------------------------
 // From class MMIDMediaKeysListener.
@@ -1399,7 +1452,7 @@
     {
         DEBUG("CMIDCanvas::RegisterComponentL, registering new");
 
-        iCustomComponents.Append(aComponent);
+        iCustomComponents.AppendL(aComponent);
 
         // Update custom components count in order to improve
         // the performance when counting components
@@ -1523,12 +1576,7 @@
         // Remove the old index from the components array.
         iCustomComponents.Remove(index);
 
-        // Add the component to the new index. Note that the array
-        // should contain memory for all the components since
-        // Remove should not decrease the memory used by the array
-        // Therefore, the following operation is leave-safe and
-        // return value is ignored intentionally.
-        iCustomComponents.Insert(aComponent, aNewIndex);
+        iCustomComponents.InsertL(aComponent, aNewIndex);
 
         // Redraw the whole canvas.
         DrawDeferred();
@@ -1577,19 +1625,34 @@
 //
 void CMIDCanvas::UpdateL(const TRect& aRect)
 {
+    if (!IsWindowVisible())
+    {
+        return;
+    }
+
+    // Don't update screen after canvas size has been changed,
+    // if there is no valid content from Java side yet
+    if (iWndUpdate &&
+            (iContentSize.iWidth  > aRect.Size().iWidth ||
+             iContentSize.iHeight > aRect.Size().iHeight))
+    {
+        return;
+    }
+
+    iWndUpdate = EFalse;
+
     // Drawing Network indicator only when Update is called.
     if (iFullScreen && iNetworkIndicator)
     {
         iNetworkIndicator->SetDrawIndicator(ETrue);
     }
 
-    // iRestoreContentWhenUnfaded is used when Canvas should be faded
-    // DrawNow need to be called, otherwise  Canvas will be unfaded
-    if (iDirectContents.Count() == 0 && !iRestoreContentWhenUnfaded && IsFocused())
+    if (iDirectContents.Count() == 0)
     {
         // In case direct content content was removed
         // from canvas, recreate pixel source here
-        if (!iAlfCompositionPixelSource && !IsEglAvailable())
+        if (!iAlfCompositionPixelSource &&
+                !IsEglAvailable())
         {
             InitPixelSourceL();
         }
@@ -1606,9 +1669,8 @@
         {
             DrawNow(aRect);
         }
-#ifdef RD_JAVA_NGA_ENABLED
+
         iCoeEnv->WsSession().Finish();
-#endif
 
         if (iFirstPaintState == EFirstPaintInitiated ||
                 iFirstPaintState == EFirstPaintPrepared)
@@ -1624,12 +1686,6 @@
         }
     }
 
-    // This is needed to avoid artifacting after orientation switch.
-    // It is called once after orientation change.
-    if (iWndUpdate)
-    {
-        iWndUpdate = EFalse;
-    }
 }
 
 #else // !RD_JAVA_NGA_ENABLED
@@ -1779,16 +1835,6 @@
     }
     else // M3G content, use EGL surface
     {
-        // Invalidates window so that wserv does not
-        // draw window content on top our EGL surface.
-        // This is needed only once when starting to use EGL surface.
-        if (iM3GStart)
-        {
-            DEBUG("CMIDCanvas::DrawWindow - invalidate");
-            Window().Invalidate();
-            iM3GStart = EFalse;
-        }
-
         if (iScalingOn && iFullScreen)
         {
             SetCurrentEglType(EEglPbuffer);
@@ -1815,6 +1861,16 @@
 
         SetCurrentEglType(EEglNone);
 
+        // Invalidates window so that wserv does not
+        // draw window content on top our EGL surface.
+        // This is needed only once when starting to use EGL surface.
+        if (iM3GStart)
+        {
+            DEBUG("CMIDCanvas::DrawWindow - invalidate");
+            Window().Invalidate();
+            iM3GStart = EFalse;
+        }
+
         if (iFirstPaintState != EFirstPaintOccurred)
         {
             iFirstPaintState = EFirstPaintOccurred;
@@ -2122,10 +2178,17 @@
         TBool partialVKBOpen = (aType == KAknSplitInputEnabled);
         if (partialVKBOpen != iPartialVKBOpen)
         {
+            // setting member variable
             iPartialVKBOpen = partialVKBOpen;
+
+            // First we need inform focused item, after other.
+            iCustomComponents[iFocusedComponent]->HandleResourceChange(aType);
             for (int i = 0; i < iCustomComponents.Count(); i++)
             {
-                iCustomComponents[i]->HandleResourceChange(aType);
+                if (i != iFocusedComponent)
+                {
+                    iCustomComponents[i]->HandleResourceChange(aType);
+                }
             }
         }
     }
@@ -2136,7 +2199,7 @@
     {
         // We need inform TextEditor that input language is changed.
         if ((iFocusedComponent != KComponentFocusedNone) &&
-                (iFocusedComponent < iCustomComponents.Count()))
+        (iFocusedComponent < iCustomComponents.Count()))
         {
             iCustomComponents[iFocusedComponent]->
             CustomComponentControl(KComponentMainControl)->
@@ -2321,16 +2384,6 @@
             //                                  iContentSize.iHeight - 1)
             point -= iViewRect.iTl;
 
-#ifdef RD_JAVA_NGA_ENABLED
-            // If NGA is started and scaling is on then the drawing rectangle
-            // is moved. Them we need move pointer events too.
-            if (iFullScreen && iScalingOn && iDirectContents.Count() == 0)
-            {
-                // Fix coordinates
-                point += iPositionRelativeToScreen;
-            }
-#endif // RD_JAVA_NGA_ENABLED
-
             if (javaMaxCoords != nativeMaxCoords)
             {
                 point.iX = (point.iX * javaMaxCoords.iWidth) /
@@ -2477,7 +2530,7 @@
 
 #ifdef RD_JAVA_NGA_ENABLED
         // To avoid situation when Canvas is redrawn but black area remains
-        if (iAlfCompositionPixelSource)
+        if (iAlfCompositionPixelSource && iDirectContents.Count() == 0)
         {
             TRAPD(err, ActivatePixelSourceL(EFalse));
             if (err != KErrNone)
@@ -2512,7 +2565,7 @@
 
         // To remove cursor on focused control.
         if ((iFocusedComponent != KComponentFocusedNone) &&
-                (iFocusedComponent < iCustomComponents.Count()) && 
+                (iFocusedComponent < iCustomComponents.Count()) &&
                 iCustomComponents[iFocusedComponent]->
                 CustomComponentControl(KComponentMainControl)->IsVisible())
         {
@@ -2521,14 +2574,13 @@
             SetFocus(EFalse);
         }
 
-#ifdef RD_JAVA_NGA_ENABLED
-        // Avoid the situation when the content is drawn over the menu
-        SuspendPixelSource();
-#endif // RD_JAVA_NGA_ENABLED
-
         // Repaint to ensure that fading will be displayed correctly for Alert
-        // or PopupTextBox when DSA is paused.
-        DrawDeferred();
+        // or PopupTextBox when DSA is paused. No redraw, if canvas is using
+        // background surfaces i.e. EGL or pixel source
+        if (iDirectContents.Count() > 0)
+        {
+            DrawDeferred();
+        }
     }
 
     DEBUG("- CMIDCanvas::FocusChanged");
@@ -2579,12 +2631,42 @@
 
         if ((contentSize != iContentSize) || iScalingOn)
         {
+#ifdef RD_JAVA_NGA_ENABLED
+            TSize oldContentSize = iContentSize;
             iContentSize = contentSize;
 
-#ifdef RD_JAVA_NGA_ENABLED
-            HandleSizeChanged();
+            TBool landscape = Layout_Meta_Data::IsLandscapeOrientation();
+
+            if (IsWindowVisible() &&
+                    (oldContentSize.iWidth < iContentSize.iWidth ||
+                     oldContentSize.iHeight < iContentSize.iHeight ||
+                     landscape != iLandscape))
+            {
+                iWndUpdate = ETrue;
+                if (IsEglAvailable())
+                {
+                    // Clear with black to avoid incorrectly sized
+                    // surface flashing on screen in orientation switch
+                    TRgb color(KOpaqueBlackColor);
+                    ClearEglSurface(EEglWindow, &color);
+                }
+            }
+
+            HandleSizeChanged(landscape != iLandscape);
+            iLandscape = landscape;
+
+            PostEvent(ESizeChanged, iContentSize.iWidth, iContentSize.iHeight);
+
+            if (IsWindowVisible() && iWndUpdate)
+            {
+                // Post forced paint to enable Canvas repaint behind
+                // Alert or Pop-up TextBox
+                PostForcedPaint();
+            }
+#else
+            iContentSize = contentSize;
+            PostEvent(ESizeChanged, iContentSize.iWidth, iContentSize.iHeight);
 #endif // RD_JAVA_NGA_ENABLED
-            PostEvent(ESizeChanged, iContentSize.iWidth, iContentSize.iHeight);
         }
 
 #ifdef CANVAS_DIRECT_ACCESS
@@ -2631,50 +2713,39 @@
 //
 void CMIDCanvas::Draw(const TRect& aRect) const
 {
-    if (!iStartUpTraceDone)
-    {
-        java::util::JavaOsLayer::startUpTrace("MIDP: CMIDCanvas::Draw starts", -1, -1);
-    }
     DEBUG("CMIDCanvas::Draw ++");
 
-    // While changing the orientation method DrawWindow() not called,
-    // variable iWndUpdate is set to True. If iWndUpdate is True
-    // DrawWindow() is called from method Update()
-    // This is needed to avoid artifacting after orientation switch.
-    TBool landscape = Layout_Meta_Data::IsLandscapeOrientation();
-
-    if (iLandscape != landscape && !iAlfCompositionPixelSource)
-    {
-        iLandscape = landscape;
-        iWndUpdate = ETrue;
+    if (iWndUpdate)
+    {
+        return;
+    }
+
+    if (iDirectContents.Count() > 0)
+    {
+        DrawWindow(aRect);
     }
     else
     {
-        // iRestoreContentWhenUnfaded is used when Canvas should be faded
-        // DrawWindow need to be called, otherwise  Canvas will be unfaded
-        // Sometimes iRestoreContentWhenUnfaded is not set yet and Canvas
-        // already lost focus, then IsFocused is used
-        if (iDirectContents.Count() > 0 || iRestoreContentWhenUnfaded || !IsFocused())
+        CMIDCanvas* myself = const_cast<CMIDCanvas*>(this);
+
+        if (IsEglAvailable())
         {
-            DrawWindow(aRect);
+            myself->ClearUiSurface(ETrue);
+        }
+        else if (iAlfCompositionPixelSource)
+        {
+            myself->ClearUiSurface(ETrue);
+            TRAP_IGNORE(myself->ActivatePixelSourceL(ETrue));
         }
         else
         {
-            CMIDCanvas* myself = const_cast<CMIDCanvas*>(this);
-            myself->ClearUiSurface(ETrue);
-            if (iAlfCompositionPixelSource)
-            {
-                TRAP_IGNORE(myself->ActivatePixelSourceL(ETrue));
-            }
+            // This is the case when M3G midlet is
+            // coming back to foreground and EGL
+            // surface is not re-created yet
+            DrawWindow(aRect);
         }
-        iWndUpdate = EFalse;
-    }
-
-    if (!iStartUpTraceDone)
-    {
-        java::util::JavaOsLayer::startUpTrace("MIDP: CMIDCanvas::Draw ends", -1, -1);
-        iStartUpTraceDone = ETrue;
-    }
+    }
+
     DEBUG("CMIDCanvas::Draw --");
 }
 #else // !RD_JAVA_NGA_ENABLED
@@ -2687,10 +2758,6 @@
 //
 void CMIDCanvas::Draw(const TRect& aRect) const
 {
-    if (!iStartUpTraceDone)
-    {
-        java::util::JavaOsLayer::startUpTrace("MIDP: CMIDCanvas::Draw starts", -1, -1);
-    }
     DEBUG("+ CMIDCanvas::Draw");
 
 #ifdef CANVAS_DOUBLE_BUFFER
@@ -2744,11 +2811,6 @@
 #endif // CANVAS_DOUBLE_BUFFER
 #endif // CANVAS_ASYNC_PAINT
 
-    if (!iStartUpTraceDone)
-    {
-        java::util::JavaOsLayer::startUpTrace("MIDP: CMIDCanvas::Draw ends", -1, -1);
-        iStartUpTraceDone = ETrue;
-    }
     DEBUG("- CMIDCanvas::Draw");
 }
 #endif // RD_JAVA_NGA_ENABLED
@@ -2952,7 +3014,7 @@
         iEnv.IsHardwareAcceleratedL(MMIDEnv::EHardware3D) > 0;
 
     InitPixelSourceL();
-#endif // RD_JAVA_NGA_ENABLED        
+#endif // RD_JAVA_NGA_ENABLED
 
 #ifdef RD_JAVA_S60_RELEASE_9_2
     iPartialVKBOpen = EFalse;
@@ -2980,6 +3042,7 @@
     iDisplayable = (CMIDDisplayable*) &aWindow;
     CCoeControl::SetContainerWindowL(aWindow);
     Window().SetBackgroundColor();
+    MakeVisible(aWindow.IsVisible());
 
 #ifdef RD_SCALABLE_UI_V2
     Window().SetPointerGrab(ETrue);
@@ -3188,16 +3251,6 @@
 
     if (iFullScreen)
     {
-#ifdef RD_JAVA_NGA_ENABLED
-        // If both NGA and scaling are on, then iViewRect is needed move
-        // for preverifing wrong position of Canvas.
-        if (iScalingOn && (!iFullScreen || iDirectContents.Count() == 0))
-        {
-            // Translate to screen coordinates.
-            rect.Move(iPositionRelativeToScreen);
-        }
-#endif // RD_JAVA_NGA_ENABLED
-
         if (iNetworkIndicator)
         {
             // Refresh the layout data for network indicator.
@@ -3208,13 +3261,6 @@
         // orientation.
         TSize orientedOrgMIDletScrSize(OrientedOrgMIDletScrSize());
 
-        // If Nokia-MIDlet-Target-Display-Size is defined, Canvas will be
-        // scaled to that size.
-        if (iTargetMIDletScrSize != KZeroSize)
-        {
-            viewSize = iTargetMIDletScrSize;
-        }
-
 #ifdef RD_JAVA_S60_RELEASE_9_2
         // If partial VKB is open then MIDlet is not scaled.
         // That we need set iViewRect to whole size of Canvas.
@@ -3222,8 +3268,15 @@
         {
             viewSize = Size();
         }
-#endif //RD_JAVA_S60_RELEASE_9_2
-
+        else if (iTargetMIDletScrSize != KZeroSize)
+#else
+        if (iTargetMIDletScrSize != KZeroSize)
+#endif //RD_JAVA_S60_RELEASE_9_2            
+        {
+            // If Nokia-MIDlet-Target-Display-Size is defined, Canvas will be
+            // scaled to that size.
+            viewSize = iTargetMIDletScrSize;
+        }
         // If optional JAD parameter Nokia-MIDlet-Target-Display-Size is NOT
         // defined and Nokia-MIDlet-Original-Display-Size is defined to
         // smaller size than the device's screen size, we will scale the
@@ -3322,14 +3375,6 @@
 #ifdef CANVAS_DIRECT_ACCESS
     StartDirectAccess();
 #endif // CANVAS_DIRECT_ACCESS
-#ifdef RD_JAVA_NGA_ENABLED
-    // To avoid situation when Orientation was changed and black screen is shown
-    TRAPD(err, UpdateL(iViewRect));
-    if (err != KErrNone)
-    {
-        DEBUG_INT("CMIDCanvas::Layout - update error %d", err);
-    }
-#endif // RD_JAVA_NGA_ENABLED
 
     TInt contentsCount(iDirectContents.Count());
 
@@ -3565,25 +3610,22 @@
 {
     DEBUG_INT("CMIDCanvas::HandleForeground(%d) ++", aForeground);
 
+    // If foreground/background state is changed,
+    // then we need resize all custom components.
+    if (iForeground != aForeground && iCustomComponents.Count() > 0)
+    {
+        for (int i = 0; i < iCustomComponents.Count(); i++)
+        {
+            iCustomComponents[i]->HandleForeground(aForeground);
+        }
+    }
+
     iForeground = aForeground;
 
 #ifdef RD_JAVA_NGA_ENABLED
-    if (!iForeground)
-    {
-        if (IsEglAvailable())
-        {
-            if (iEglOccupied)
-            {
-                DEBUG("CMIDCanvas::HandleForeground() - egl - pending dispose");
-                iEglPendingDispose = ETrue;
-            }
-            else
-            {
-                CloseEgl();
-            }
-        }
-
-        SuspendPixelSource();
+    if (!aForeground)
+    {
+        FreeGraphicsMemory(EFalse);
     }
 #endif // RD_JAVA_NGA_ENABLED
 
@@ -3591,6 +3633,60 @@
 }
 
 #ifdef RD_JAVA_NGA_ENABLED
+// ---------------------------------------------------------------------------
+// CMIDCanvas::HandleFullOrPartialForegroundL
+// ---------------------------------------------------------------------------
+//
+void CMIDCanvas::HandleFullOrPartialForegroundL(
+    TBool aFullOrPartialFg, TBool aCurrentDisplayable)
+{
+    if (!aFullOrPartialFg && aCurrentDisplayable)
+    {
+        FreeGraphicsMemory(ETrue);
+    }
+    else if (!iPrevM3GContent && iAlfCompositionPixelSource)
+    {
+        SuspendPixelSource();
+        ActivatePixelSourceL(ETrue);
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CMIDCanvas::FreeGraphicsMemory
+// Free GPU memory if the canvas is not visible anymore. If aForced is true,
+// visibility is not checked.
+// ---------------------------------------------------------------------------
+//
+void CMIDCanvas::FreeGraphicsMemory(TBool aForced)
+{
+    // No freeing in exit case to avoid flickering
+    if ((!aForced && IsWindowVisible()) || iExiting)
+    {
+        return;
+    }
+
+    if (IsEglAvailable())
+    {
+        if (iEglOccupied)
+        {
+            DEBUG("CMIDCanvas::FreeGraphcisMemory() - egl - pending dispose");
+            iEglPendingDispose = ETrue;
+        }
+        else
+        {
+            CloseEgl(ETrue);
+            // If MIDlet is not visible on foreground post event to Java
+            // so that M3G is notfied and frees the m3gCore memory
+            if (!iEnv.HasFullOrPartialForeground())
+            {
+                iEnv.PostMidletEvent(EFreeGraphicsMemory);
+                eglReleaseThread();
+            }
+        }
+    }
+
+    SuspendPixelSource();
+}
 
 // ---------------------------------------------------------------------------
 // CMIDCanvas::InitPixelSourceL()
@@ -3668,8 +3764,14 @@
         return;
     }
 
-    // ProduceNewFrameL() is called in some cases
-    // directly from ActivateSyncL(), need to set iFrameReady
+    // Don't activate, if there is no valid content from Java yet
+    if (!ReadyToBlit())
+    {
+        return;
+    }
+
+    // ProduceNewFrameL() is called directly from ActivateSyncL()
+    // if pixel source is suspended, need to set iFrameReady
     // before ActivateSyncL()
     iFrameReady = ETrue;
     TRAPD(err, iAlfCompositionPixelSource->ActivateSyncL());
@@ -3681,11 +3783,21 @@
 
     if (iPixelSourceSuspended)
     {
-        ClearUiSurface(aDrawingOngoing);
         iPixelSourceSuspended = EFalse;
         if (iFullScreen && iScalingOn)
         {
-            iAlfCompositionPixelSource->SetExtent(iViewRect, KPhoneScreen);
+            TRect targetRect = iViewRect;
+            targetRect.Move(iPositionRelativeToScreen);
+            iAlfCompositionPixelSource->SetExtent(targetRect, KPhoneScreen);
+            // Flag is set to in order that screen gets updated at least once
+            // after SetExtent() call
+            iFrameReady = ETrue;
+        }
+
+        if (!aDrawingOngoing)
+        {
+            ClearUiSurface(aDrawingOngoing);
+            iCoeEnv->WsSession().Finish();
         }
     }
 }
@@ -3705,14 +3817,53 @@
     gc.SetBrushColor(KTransparentClearColor);
     gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
     gc.Clear();
+
+    // Clearing is done via EGL in scaled M3G case
+    if (iScalingOn && iFullScreen && !IsEglAvailable())
+    {
+        const TRect rect = Rect();
+        if (rect != iViewRect)
+        {
+            gc.SetBrushColor(KRgbBlack);
+            gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+            DrawUtils::ClearBetweenRects(gc, rect, iViewRect);
+        }
+    }
+
     if (!aDrawing)
     {
         DeactivateGc();
         Window().EndRedraw();
     }
+}
+
+// ---------------------------------------------------------------------------
+// CMIDCanvas::DrawToWindowGc
+// Draws current frame buffer content to CWindowGc
+// ---------------------------------------------------------------------------
+//
+void CMIDCanvas::DrawToWindowGc()
+{
+    if (iDirectContents.Count() > 0 ||
+            !IsWindowVisible() ||
+            !iForeground)
+    {
+        return;
+    }
+
+    Window().BeginRedraw();
+    ActivateGc();
+
+    TRect rect = (iFullScreen && iScalingOn) ? iViewRect : Rect();
+    DrawWindow(rect);
+
+    DeactivateGc();
+    Window().EndRedraw();
+
     iCoeEnv->WsSession().Finish();
 }
 
+// ---------------------------------------------------------------------------
 // CMIDCanvas::SuspendPixelSource
 // ---------------------------------------------------------------------------
 //
@@ -3976,7 +4127,7 @@
 // Destroys EGL contexts and surfaces.
 // ---------------------------------------------------------------------------
 //
-void CMIDCanvas::CloseEgl()
+void CMIDCanvas::CloseEgl(TBool aReadback)
 {
     DEBUG("CMIDCanvas::CloseEglL() ++");
 
@@ -3992,9 +4143,8 @@
 
     // MIDlet might draw only 2D after this =>
     // need to set frame buffer opaque to be compatible with
-    // blending methods in Lcdgd. UpdateOffScreenBitmapL() does this
-    // for GameCanvas.
-    if (!IsGameCanvas() && iFrameContext)
+    // blending methods in Lcdgd. UpdateOffScreenBitmapL() does this too.
+    if (!aReadback && iFrameContext)
     {
         iFrameContext->SetBrushColor(KOpaqueClearColor);
         iFrameContext->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
@@ -4002,10 +4152,13 @@
     }
 
     // Take a snapshot from window surface to the frame buffer.
-    TRAPD(err, UpdateOffScreenBitmapL(EFalse));
-    if (err != KErrNone)
-    {
-        DEBUG("CMIDCanvas::CloseEgl() - UpdateOffScreenBitmapL() failed");
+    if (aReadback)
+    {
+        TRAPD(err, UpdateOffScreenBitmapL(ETrue));
+        if (err != KErrNone)
+        {
+            DEBUG("CMIDCanvas::CloseEgl() - UpdateOffScreenBitmapL() failed");
+        }
     }
 
     // make sure the we have no current target
@@ -4139,7 +4292,7 @@
 // next ProcessL() when M3G_CONTENT_START is recieved from Java side.
 // ---------------------------------------------------------------------------
 //
-void CMIDCanvas::HandleSizeChanged()
+void CMIDCanvas::HandleSizeChanged(TBool aOrientationChange)
 {
     DEBUG("CMIDCanvas::HandleSizeChanged ++");
 
@@ -4149,7 +4302,8 @@
     {
         TSize surfaceSize = GetEglSurfaceSize(iEglWindowSurface);
         TSize controlSize = Size();
-        if (surfaceSize.iHeight < controlSize.iHeight ||
+        if (aOrientationChange ||
+                surfaceSize.iHeight < controlSize.iHeight ||
                 surfaceSize.iWidth < controlSize.iWidth)
         {
             // Check if egl surface is currently occupied.
@@ -4157,14 +4311,14 @@
             {
                 // Delayed resizing. It is done when the ReleaseEglSurface method
                 // is called.
-                DEBUG("CMIDCanvas::HandleSizeChanged - egl - resize pending");
                 iEglPendingResize = ETrue;
             }
             else
             {
-                DEBUG("CMIDCanvas::SizeChanged - close egl");
                 // Surface recreation is done in next ProcessL() call
-                CloseEgl();
+                // No readback from EGL, because canvas needs to
+                // repaint itself anyway in new size
+                CloseEgl(EFalse);
             }
         }
     }
@@ -4211,7 +4365,7 @@
 // Return ETrue, if EGL based drawing is in use.
 // ---------------------------------------------------------------------------
 //
-TBool CMIDCanvas::IsEglAvailable()
+TBool CMIDCanvas::IsEglAvailable() const
 {
     return (iEglWindowSurface != EGL_NO_SURFACE);
 }
@@ -4253,14 +4407,18 @@
         if (iEglPendingDispose)
         {
             DEBUG("CMIDCanvas::ReleaseEglSurface() - dispose egl");
-            CloseEgl();
+            FreeGraphicsMemory(ETrue);
         }
         else if (iEglPendingResize)
         {
             DEBUG("CMIDCanvas::ReleaseEglSurface() - pending resize");
-            HandleSizeChanged();
+            HandleSizeChanged(ETrue);
         }
-        ClearFrameBuffer();
+
+        if (IsEglAvailable())
+        {
+            ClearFrameBuffer();
+        }
     }
 }
 
@@ -4443,6 +4601,17 @@
     TRect canvasRect = IsDownScaling(iContentSize, iViewRect, iM3GContent) ?
                        TRect(iViewRect.Size()) : TRect(iContentSize);
     rect.Intersection(canvasRect);
+    // Checking if rect have intersection with frameRect
+    TRect frameRect(TPoint(), iFrameBuffer->SizeInPixels());
+    if (!rect.Intersects(frameRect))
+    {
+        return;
+    }
+    rect.Intersection(frameRect);
+    if (rect.IsEmpty())
+    {
+        return;
+    }
 
     // Update the member rects
     if (iUpperUpdateRect.Intersects(rect))
@@ -4480,6 +4649,22 @@
 }
 
 // ---------------------------------------------------------------------------
+// From MMIDCanvas
+// CMIDCanvas::MidletExiting
+// Draws content to CWindowGc to enable the system effect on MIDlet exit.
+// Canvas might be in the middle of rendering new frame when this is called.
+// Having incomplete frame on screen in some exit cases is anyway better than
+// fully black always.
+// ---------------------------------------------------------------------------
+//
+void CMIDCanvas::MidletExiting()
+{
+    iExiting = ETrue;
+    TRAP_IGNORE(UpdateOffScreenBitmapL(ETrue));
+    DrawToWindowGc();
+}
+
+// ---------------------------------------------------------------------------
 // CMIDCanvas::BlitFrameBufferPixels
 // Sets up OpenGL state for 2D texture rendering and renders the textures for
 // updated frame buffer areas by calling BlitSubRect().
@@ -4614,8 +4799,11 @@
             TInt srcOffset = (canvasHeight - (yStart + ySize)) * stride +
                              xStart * KBytesPerPixel;
 
-            BlitSubRectTexture(xStart, yStart, xSize, ySize, stride,
-                               (TUint8*)iFrameBuffer->DataAddress() + srcOffset);
+            if ((xSize > 0) && (xSize <= 256) && (ySize > 0) && (ySize <= 256))
+            {
+                BlitSubRectTexture(xStart, yStart, xSize, ySize, stride,
+                                   (TUint8*)iFrameBuffer->DataAddress() + srcOffset);
+            }
         }
     }
 }
@@ -4678,7 +4866,7 @@
     if (err == GL_OUT_OF_MEMORY)
     {
         glDeleteTextures(KTexturesCount, tempTexObj);
-        DEBUG("CMIDCanvas::BlitSubRectTexture(): Out of memory when creating OpenGL texture");
+        ELOG(EJavaUI, "CMIDCanvas::BlitSubRectTexture(): Out of memory when creating OpenGL texture");
         return;
     }
     else if (err != GL_NO_ERROR)
@@ -4713,7 +4901,6 @@
     {
         // Clear the pixel data with transparent for case where
         // actual texture data does not cover the full tile.
-        // This should be actually done with glClear().
         Mem::FillZ(dst, tileWidth * tileHeight * KBytesPerPixel);
         dst += tileWidth * (tileHeight - aHeight) * KBytesPerPixel;
     }
@@ -4961,11 +5148,11 @@
     glLoadIdentity();
 
     // position texture screen coordinates
-    pos[0] = (GLshort)iViewRect.iTl.iX - iPositionRelativeToScreen.iX;
+    pos[0] = (GLshort)iViewRect.iTl.iX;
     pos[1] = (GLshort)iViewRect.Height() + (height - iViewRect.iBr.iY);
     pos[2] = pos[0];
     pos[3] = (GLshort)height - iViewRect.iBr.iY;
-    pos[4] = (GLshort)iViewRect.iBr.iX - iPositionRelativeToScreen.iX;
+    pos[4] = (GLshort)iViewRect.iBr.iX;
     pos[5] = pos[1];
     pos[6] = pos[4];
     pos[7] = pos[3];
@@ -5077,5 +5264,31 @@
     return KEglSuccess;
 }
 
+// ---------------------------------------------------------------------------
+// CMIDCanvas::IsWindowVisible
+// Checks if canvas window is currently visible on display. Canvas may be visible
+// e.g. behind task switcher or system dialogs even though MIDlet is not the
+// foreground application in that case. This function relies on
+// CMIDDisplayble setting canvas window invisible when some other full-screen
+// displayble is set as current.
+// ---------------------------------------------------------------------------
+//
+TBool CMIDCanvas::IsWindowVisible() const
+{
+    return iEnv.HasFullOrPartialForeground() && IsVisible();
+}
+
+// ---------------------------------------------------------------------------
+// CMIDCanvas::PostForcedPaint
+// Send forced paint to Java. Canvas.paint() will be called even if canvas is
+// not the current displayable.
+// ---------------------------------------------------------------------------
+//
+void CMIDCanvas::PostForcedPaint()
+{
+    TInt posPacked  = 0;
+    TInt sizePacked = (iContentSize.iWidth << 16) | (iContentSize.iHeight);
+    PostEvent(EForcedPaint, posPacked, sizePacked);
+}
 #endif // RD_JAVA_NGA_ENABLED        
 // End of File.