src/gui/kernel/qapplication_s60.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
--- a/src/gui/kernel/qapplication_s60.cpp	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/gui/kernel/qapplication_s60.cpp	Tue Feb 02 00:43:10 2010 +0200
@@ -4,7 +4,7 @@
 ** All rights reserved.
 ** Contact: Nokia Corporation (qt-info@nokia.com)
 **
-** This file is part of the QtGui of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
 ** No Commercial Usage
@@ -63,7 +63,7 @@
 #include "private/qsoftkeymanager_p.h"
 
 #include "apgwgnam.h" // For CApaWindowGroupName
-#include <MdaAudioTonePlayer.h>     // For CMdaAudioToneUtility
+#include <mdaaudiotoneplayer.h>     // For CMdaAudioToneUtility
 
 #if defined(Q_WS_S60)
 # if !defined(QT_NO_IM)
@@ -133,36 +133,46 @@
     TTimeIntervalMicroSeconds iDuration;
 };
 
+static QS60Beep* qt_S60Beep = 0;
+
 QS60Beep::~QS60Beep()
 {
+    if (iToneUtil) {
+        switch (iState) {
+        case EBeepPlaying:
+            iToneUtil->CancelPlay();
+            break;
+        case EBeepNotPrepared:
+            iToneUtil->CancelPrepare();
+            break;
+        }
+    }
     delete iToneUtil;
 }
 
 QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
 {
-    QS60Beep* self=new (ELeave) QS60Beep();
+    QS60Beep* self = new (ELeave) QS60Beep();
     CleanupStack::PushL(self);
     self->ConstructL(aFrequency, aDuration);
     CleanupStack::Pop();
     return self;
-};
+}
 
 void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
 {
-    iToneUtil=CMdaAudioToneUtility::NewL(*this);
-    iState=EBeepNotPrepared;
-    iFrequency=aFrequency;
-    iDuration=aDuration;
-    iToneUtil->PrepareToPlayTone(iFrequency,iDuration);
+    iToneUtil = CMdaAudioToneUtility::NewL(*this);
+    iState = EBeepNotPrepared;
+    iFrequency = aFrequency;
+    iDuration = aDuration;
+    iToneUtil->PrepareToPlayTone(iFrequency, iDuration);
 }
 
 void QS60Beep::Play()
 {
-    if (iState != EBeepNotPrepared) {
-        if (iState == EBeepPlaying) {
-            iToneUtil->CancelPlay();
-            iState = EBeepPrepared;
-        }
+    if (iState == EBeepPlaying) {
+        iToneUtil->CancelPlay();
+        iState = EBeepPrepared;
     }
 
     iToneUtil->Play();
@@ -173,13 +183,14 @@
 {
     if (aError == KErrNone) {
         iState = EBeepPrepared;
+        Play();
     }
 }
 
 void QS60Beep::MatoPlayComplete(TInt aError)
 {
     Q_UNUSED(aError);
-    iState=EBeepPrepared;
+    iState = EBeepPrepared;
 }
 
 
@@ -319,7 +330,11 @@
 }
 
 QSymbianControl::QSymbianControl(QWidget *w)
-    : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false)
+    : CCoeControl()
+    , qwidget(w)
+    , m_longTapDetector(0)
+    , m_ignoreFocusChanged(0)
+    , m_symbianPopupIsOpen(0)
 {
 }
 
@@ -346,6 +361,8 @@
 
         SetFocusing(true);
         m_longTapDetector = QLongTapTimer::NewL(this);
+
+        DrawableWindow()->SetPointerGrab(ETrue);
     }
 }
 
@@ -371,19 +388,11 @@
     alienWidget = qwidget->childAt(widgetPos);
     if (!alienWidget)
         alienWidget = qwidget;
-    QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~Qt::LeftButton);
-    QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton;
-    QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos,
-        Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
-
-    bool res = sendMouseEvent(alienWidget, &mEvent);
 
 #if !defined(QT_NO_CONTEXTMENU)
-    QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, mEvent.modifiers());
+    QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, Qt::NoModifier);
     qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent);
 #endif
-
-    m_previousEventLongTap = true;
 }
 
 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
@@ -465,41 +474,6 @@
     QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent));
 }
 
-typedef QPair<QWidget*,QMouseEvent> Event;
-
-/*
- * Helper function called by HandlePointerEvent - separated to keep that function readable
- */
-static void generateEnterLeaveEvents(QList<Event> &events, QWidget *widgetUnderPointer,
-    QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
-{
-    //moved to another widget, create enter and leave events
-    if (S60->lastPointerEventTarget) {
-        QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(
-            S60->lastCursorPos), S60->lastCursorPos, button, QApplicationPrivate::mouse_buttons,
-            modifiers);
-        events.append(Event(S60->lastPointerEventTarget, mEventLeave));
-    }
-    if (widgetUnderPointer) {
-        QMouseEvent mEventEnter(QEvent::Enter, widgetUnderPointer->mapFromGlobal(globalPos),
-            globalPos, button, QApplicationPrivate::mouse_buttons, modifiers);
-
-        events.append(Event(widgetUnderPointer, mEventEnter));
-#ifndef QT_NO_CURSOR
-        S60->curWin = widgetUnderPointer->effectiveWinId();
-        if (!QApplication::overrideCursor()) {
-#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
-            if (S60->brokenPointerCursors)
-                qt_symbian_set_pointer_sprite(widgetUnderPointer->cursor());
-            else
-#endif
-                qt_symbian_setWindowCursor(widgetUnderPointer->cursor(), S60->curWin);
-        }
-#endif
-    }
-}
-
-
 void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
 {
     QMouseEvent::Type type;
@@ -507,91 +481,77 @@
     mapS60MouseEventTypeToQt(&type, &button, &pEvent);
     Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers);
 
-    if (m_previousEventLongTap)
-        if (type == QEvent::MouseButtonRelease){
-            button = Qt::RightButton;
-            QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton;
-            m_previousEventLongTap = false;
-        }
-    if (type == QMouseEvent::None)
-        return;
-
-    // store events for later sending/saving
-    QList<Event > events;
-
     QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
     TPoint controlScreenPos = PositionRelativeToScreen();
     QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
+    S60->lastCursorPos = globalPos;
+    S60->lastPointerEventPos = widgetPos;
 
-    // widgets interested in the event
+    QWidget *mouseGrabber = QWidget::mouseGrabber();
+
+    QWidget *popupWidget = qApp->activePopupWidget();
+    QWidget *popupReceiver = 0;
+    if (popupWidget) {
+        QWidget *popupChild = popupWidget->childAt(popupWidget->mapFromGlobal(globalPos));
+        popupReceiver = popupChild ? popupChild : popupWidget;
+    }
+
+    if (mouseGrabber) {
+        if (popupReceiver) {
+            sendMouseEvent(popupReceiver, type, globalPos, button, modifiers);
+        } else {
+            sendMouseEvent(mouseGrabber, type, globalPos, button, modifiers);
+        }
+        // No Enter/Leave events in grabbing mode.
+        return;
+    }
+
     QWidget *widgetUnderPointer = qwidget->childAt(widgetPos);
     if (!widgetUnderPointer)
-        widgetUnderPointer = qwidget; //i.e. this container widget
+        widgetUnderPointer = qwidget;
 
-    QWidget *widgetWithMouseGrab = QWidget::mouseGrabber();
+    QApplicationPrivate::dispatchEnterLeave(widgetUnderPointer, S60->lastPointerEventTarget);
+    S60->lastPointerEventTarget = widgetUnderPointer;
 
-    // handle auto grab of pointer when pressing / releasing
-    if (!widgetWithMouseGrab && type == QEvent::MouseButtonPress) {
-        //if previously auto-grabbed, generate a fake mouse release (platform bug: mouse release event was lost)
-        if (S60->mousePressTarget) {
-            QMouseEvent mEvent(QEvent::MouseButtonRelease, S60->mousePressTarget->mapFromGlobal(globalPos), globalPos,
-                button, QApplicationPrivate::mouse_buttons, modifiers);
-            events.append(Event(S60->mousePressTarget,mEvent));
-        }
-        //auto grab the mouse
-        widgetWithMouseGrab = S60->mousePressTarget = widgetUnderPointer;
-        widgetWithMouseGrab->grabMouse();
+    QWidget *receiver;
+    if (!popupReceiver && S60->mousePressTarget && type != QEvent::MouseButtonPress) {
+        receiver = S60->mousePressTarget;
+        if (type == QEvent::MouseButtonRelease)
+            S60->mousePressTarget = 0;
+    } else {
+        receiver = popupReceiver ? popupReceiver : widgetUnderPointer;
+        if (type == QEvent::MouseButtonPress)
+            S60->mousePressTarget = receiver;
     }
-    if (widgetWithMouseGrab && widgetWithMouseGrab == S60->mousePressTarget && type == QEvent::MouseButtonRelease) {
-        //release the auto grab - note this release event still goes to the autograb widget
-        S60->mousePressTarget = 0;
-        widgetWithMouseGrab->releaseMouse();
-    }
-
-    QWidget *widgetToReceiveMouseEvent;
-    if (widgetWithMouseGrab)
-        widgetToReceiveMouseEvent = widgetWithMouseGrab;
-    else
-        widgetToReceiveMouseEvent = widgetUnderPointer;
-
-    //queue QEvent::Enter and QEvent::Leave, if the pointer has moved
-    if (widgetUnderPointer != S60->lastPointerEventTarget && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove))
-        generateEnterLeaveEvents(events, widgetUnderPointer, globalPos, button, modifiers);
-
-    //save global state
-    S60->lastCursorPos = globalPos;
-    S60->lastPointerEventPos = widgetPos;
-    S60->lastPointerEventTarget = widgetUnderPointer;
 
 #if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS)
     if (S60->brokenPointerCursors)
         qt_symbian_move_cursor_sprite();
 #endif
 
-    //queue this event.
-    Q_ASSERT(widgetToReceiveMouseEvent);
-    QMouseEvent mEvent(type, widgetToReceiveMouseEvent->mapFromGlobal(globalPos), globalPos,
+    sendMouseEvent(receiver, type, globalPos, button, modifiers);
+}
+
+void QSymbianControl::sendMouseEvent(
+        QWidget *receiver,
+        QEvent::Type type,
+        const QPoint &globalPos,
+        Qt::MouseButton button,
+        Qt::KeyboardModifiers modifiers)
+{
+    Q_ASSERT(receiver);
+    QMouseEvent mEvent(type, receiver->mapFromGlobal(globalPos), globalPos,
         button, QApplicationPrivate::mouse_buttons, modifiers);
-    events.append(Event(widgetToReceiveMouseEvent,mEvent));
     QEventDispatcherS60 *dispatcher;
     // It is theoretically possible for someone to install a different event dispatcher.
-    if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widgetToReceiveMouseEvent->d_func()->threadData->eventDispatcher)) != 0) {
+    if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(receiver->d_func()->threadData->eventDispatcher)) != 0) {
         if (dispatcher->excludeUserInputEvents()) {
-            for (int i=0;i < events.count();++i)
-            {
-                Event next = events[i];
-                dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second));
-            }
+            dispatcher->saveInputEvent(this, receiver, new QMouseEvent(mEvent));
             return;
         }
     }
 
-    //send events in the queue
-    for (int i=0;i < events.count();++i)
-    {
-        Event next = events[i];
-        sendMouseEvent(next.first, &(next.second));
-    }
+    sendMouseEvent(receiver, &mEvent);
 }
 
 bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent)
@@ -671,27 +631,58 @@
                         fakeEvent.iType = TPointerEvent::EButton1Up;
                     S60->virtualMouseAccel = 1;
                     S60->virtualMouseLastKey = 0;
+                    switch (keyCode) {
+                    case Qt::Key_Left:
+                        S60->virtualMousePressedKeys &= ~QS60Data::Left;
+                        break;
+                    case Qt::Key_Right:
+                        S60->virtualMousePressedKeys &= ~QS60Data::Right;
+                        break;
+                    case Qt::Key_Up:
+                        S60->virtualMousePressedKeys &= ~QS60Data::Up;
+                        break;
+                    case Qt::Key_Down:
+                        S60->virtualMousePressedKeys &= ~QS60Data::Down;
+                        break;
+                    case Qt::Key_Select:
+                        S60->virtualMousePressedKeys &= ~QS60Data::Select;
+                        break;
+                    }
                 }
                 else if (type == EEventKey) {
                     switch (keyCode) {
                     case Qt::Key_Left:
+                        S60->virtualMousePressedKeys |= QS60Data::Left;
                         x -= S60->virtualMouseAccel;
                         fakeEvent.iType = TPointerEvent::EMove;
                         break;
                     case Qt::Key_Right:
+                        S60->virtualMousePressedKeys |= QS60Data::Right;
                         x += S60->virtualMouseAccel;
                         fakeEvent.iType = TPointerEvent::EMove;
                         break;
                     case Qt::Key_Up:
+                        S60->virtualMousePressedKeys |= QS60Data::Up;
                         y -= S60->virtualMouseAccel;
                         fakeEvent.iType = TPointerEvent::EMove;
                         break;
                     case Qt::Key_Down:
+                        S60->virtualMousePressedKeys |= QS60Data::Down;
                         y += S60->virtualMouseAccel;
                         fakeEvent.iType = TPointerEvent::EMove;
                         break;
                     case Qt::Key_Select:
-                        fakeEvent.iType = TPointerEvent::EButton1Down;
+                        // Platform bug. If you start pressing several keys simultaneously (for
+                        // example for drag'n'drop), Symbian starts producing spurious up and
+                        // down messages for some keys. Therefore, make sure we have a clean slate
+                        // of pressed keys before starting a new button press.
+                        if (S60->virtualMousePressedKeys != 0) {
+                            S60->virtualMousePressedKeys |= QS60Data::Select;
+                            return EKeyWasConsumed;
+                        } else {
+                            S60->virtualMousePressedKeys |= QS60Data::Select;
+                            fakeEvent.iType = TPointerEvent::EButton1Down;
+                        }
                         break;
                     }
                 }
@@ -722,7 +713,7 @@
         Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
         QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
                 mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
-                false, 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
+                (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
 //        WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
 //        if (!wid)
 //             Could happen if window isn't shown yet.
@@ -822,6 +813,12 @@
     if (!engine)
         return;
 
+    const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents;
+    if (sendNativePaintEvents) {
+        const QRect r = qt_TRect2QRect(controlRect);
+        QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r));
+    }
+
     // Map source rectangle into coordinates of the backing store.
     const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY);
     const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase);
@@ -832,14 +829,48 @@
         CFbsBitmap *bitmap = s60Surface->symbianBitmap();
         CWindowGc &gc = SystemGc();
 
-        if(!qwidget->d_func()->extraData()->disableBlit) {
+        switch(qwidget->d_func()->extraData()->nativePaintMode) {
+        case QWExtra::Disable:
+            // Do nothing
+            break;
+
+        case QWExtra::Blit:
             if (qwidget->d_func()->isOpaque)
                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
             gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
-	    }
+            break;
+
+        case QWExtra::ZeroFill:
+            if (Window().DisplayMode() == EColor16MA) {
+                gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+                gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
+                gc.SetBrushColor(TRgb::Color16MA(0));
+                gc.Clear(controlRect);
+            } else {
+                gc.SetBrushColor(TRgb(0x000000));
+                gc.Clear(controlRect);
+            };
+            break;
+
+        default:
+            Q_ASSERT(false);
+        }
     } else {
         surface->flush(qwidget, QRegion(qt_TRect2QRect(backingStoreRect)), QPoint());
     }
+
+    if (sendNativePaintEvents) {
+        const QRect r = qt_TRect2QRect(controlRect);
+        // The draw ops aren't actually sent to WSERV until the graphics
+        // context is deactivated, which happens in the function calling
+        // this one.  We therefore delay the delivery of endNativePaintEvent,
+        // to ensure that drawing has completed by the time the widget
+        // receives the event.  Note that, if the widget needs to ensure
+        // that the draw ops have actually been executed into the output
+        // framebuffer, a call to RWsSession::Flush is required in the
+        // endNativePaintEvent implementation.
+        QMetaObject::invokeMethod(qwidget, "endNativePaintEvent", Qt::QueuedConnection, Q_ARG(QRect, r));
+    }
 }
 
 void QSymbianControl::SizeChanged()
@@ -866,6 +897,11 @@
                 tlwExtra->inTopLevelResize = false;
         }
     }
+
+    // CCoeControl::SetExtent calls SizeChanged, but does not call
+    // PositionChanged, so we call it here to ensure that the widget's
+    // position is updated.
+    PositionChanged();
 }
 
 void QSymbianControl::PositionChanged()
@@ -903,19 +939,40 @@
         return;
 
     if (IsFocused() && IsVisible()) {
+        if (m_symbianPopupIsOpen) {
+            QWidget *fw = QApplication::focusWidget();
+            if (fw) {
+                QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason);
+                QCoreApplication::sendEvent(fw, &event);
+            }
+            m_symbianPopupIsOpen = false;
+        }
+
         QApplication::setActiveWindow(qwidget->window());
+        qwidget->d_func()->setWindowIcon_sys(true);
+        qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
 #ifdef Q_WS_S60
         // If widget is fullscreen, hide status pane and button container
         // otherwise show them.
         CEikStatusPane* statusPane = S60->statusPane();
         CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
         bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
-        if (statusPane && (statusPane->IsVisible() == isFullscreen))
+        if (statusPane && (bool)statusPane->IsVisible() == isFullscreen)
             statusPane->MakeVisible(!isFullscreen);
-        if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen))
+        if (buttonGroup && (bool)buttonGroup->IsVisible() == isFullscreen)
             buttonGroup->MakeVisible(!isFullscreen);
 #endif
     } else if (QApplication::activeWindow() == qwidget->window()) {
+        if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) {
+            QWidget *fw = QApplication::focusWidget();
+            if (fw) {
+                QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
+                QCoreApplication::sendEvent(fw, &event);
+            }
+            m_symbianPopupIsOpen = true;
+            return;
+        }
+
         QApplication::setActiveWindow(0);
     }
     // else { We don't touch the active window unless we were explicitly activated or deactivated }
@@ -925,7 +982,16 @@
 {
     switch (resourceType) {
     case KInternalStatusPaneChange:
-        qwidget->d_func()->setWindowIcon_sys(true);
+        if (qwidget->isFullScreen()) {
+            SetExtentToWholeScreen();
+        } else if (qwidget->isMaximized()) {
+            TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+            SetExtent(r.iTl, r.Size());
+        }
+        if (IsFocused() && IsVisible()) {
+            qwidget->d_func()->setWindowIcon_sys(true);
+            qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
+        }
         break;
     case KUidValueCoeFontChangeEvent:
         // font change event
@@ -1046,8 +1112,17 @@
         // After this construction, CEikonEnv will be available from CEikonEnv::Static().
         // (much like our qApp).
         CEikonEnv* coe = new CEikonEnv;
-        QT_TRAP_THROWING(coe->ConstructAppFromCommandLineL(factory,*commandLine));
+        //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there.
+        if(err == KErrNone)
+            TRAP(err, coe->ConstructAppFromCommandLineL(factory,*commandLine));
         delete commandLine;
+        if(err != KErrNone) {
+            qWarning() << "qt_init: Eikon application construct failed ("
+                       << err
+                       << "), maybe missing resource file on S60 3.1?";
+            delete coe;
+            qt_symbian_throwIfError(err);
+        }
 
         S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler);
 
@@ -1080,9 +1155,9 @@
 
     // enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app,
     // and for dimming behind modal windows
-	S60->windowGroup().EnableFocusChangeEvents();
+    S60->windowGroup().EnableFocusChangeEvents();
 
-	//Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this)
+    //Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this)
     const TInt KMachineUidSamsungI8510 = 0x2000C51E;
     // HAL::Get(HALData::EPen, TInt& result) may set 'result' to 1 on some 3.1 systems (e.g. N95).
     // But we know that S60 systems below 5.0 did not support touch.
@@ -1192,6 +1267,10 @@
  *****************************************************************************/
 void qt_cleanup()
 {
+    if(qt_S60Beep) {
+        delete qt_S60Beep;
+        qt_S60Beep = 0;
+    }
     QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
 // S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
 
@@ -1240,7 +1319,7 @@
 void QApplicationPrivate::enterModal_sys(QWidget *widget)
 {
     if (widget) {
-        widget->effectiveWinId()->DrawableWindow()->FadeBehind(ETrue);
+        static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue);
         // Modal partial screen dialogs (like queries) capture pointer events.
         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
         widget->effectiveWinId()->SetGloballyCapturing(ETrue);
@@ -1255,7 +1334,7 @@
 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
 {
     if (widget) {
-        widget->effectiveWinId()->DrawableWindow()->FadeBehind(EFalse);
+        static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse);
         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
         widget->effectiveWinId()->SetGloballyCapturing(EFalse);
         widget->effectiveWinId()->SetPointerCapture(EFalse);
@@ -1433,14 +1512,13 @@
 
 void QApplication::beep()
 {
-    TInt frequency=440;
-    TTimeIntervalMicroSeconds duration(500000);
-    QS60Beep* beep=NULL;
-    TRAPD(err, beep=QS60Beep::NewL(frequency, duration));
-    if (!err)
-        beep->Play();
-    delete beep;
-    beep=NULL;
+    if (!qt_S60Beep) {
+        TInt frequency = 880;
+        TTimeIntervalMicroSeconds duration(500000);
+        TRAP_IGNORE(qt_S60Beep=QS60Beep::NewL(frequency, duration));
+    }
+    if (qt_S60Beep)
+        qt_S60Beep->Play();
 }
 
 /*!
@@ -1563,7 +1641,7 @@
         }
 #endif
         break;
-	default:
+    default:
         break;
     }