src/gui/kernel/qapplication_s60.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qapplication_p.h"
       
    43 #include "qsessionmanager.h"
       
    44 #include "qevent.h"
       
    45 #include "qsymbianevent.h"
       
    46 #include "qeventdispatcher_s60_p.h"
       
    47 #include "qwidget.h"
       
    48 #include "qdesktopwidget.h"
       
    49 #include "private/qbackingstore_p.h"
       
    50 #include "qt_s60_p.h"
       
    51 #include "private/qevent_p.h"
       
    52 #include "qstring.h"
       
    53 #include "qdebug.h"
       
    54 #include "qimage.h"
       
    55 #include "private/qkeymapper_p.h"
       
    56 #include "private/qfont_p.h"
       
    57 #ifndef QT_NO_STYLE_S60
       
    58 #include "private/qs60style_p.h"
       
    59 #endif
       
    60 #include "private/qwindowsurface_s60_p.h"
       
    61 #include "qpaintengine.h"
       
    62 #include "private/qmenubar_p.h"
       
    63 #include "private/qsoftkeymanager_p.h"
       
    64 
       
    65 #include "apgwgnam.h" // For CApaWindowGroupName
       
    66 #include <MdaAudioTonePlayer.h>     // For CMdaAudioToneUtility
       
    67 
       
    68 #if defined(Q_WS_S60)
       
    69 # if !defined(QT_NO_IM)
       
    70 #  include "qinputcontext.h"
       
    71 #  include <private/qcoefepinputcontext_p.h>
       
    72 # endif
       
    73 # include <private/qs60mainapplication_p.h>
       
    74 #endif
       
    75 
       
    76 #include "private/qstylesheetstyle_p.h"
       
    77 
       
    78 #include <hal.h>
       
    79 #include <hal_data.h>
       
    80 
       
    81 QT_BEGIN_NAMESPACE
       
    82 
       
    83 #if defined(QT_DEBUG)
       
    84 static bool        appNoGrab        = false;        // Grabbing enabled
       
    85 #endif
       
    86 static bool        app_do_modal        = false;        // modal mode
       
    87 Q_GLOBAL_STATIC(QS60Data, qt_s60Data);
       
    88 
       
    89 extern bool qt_sendSpontaneousEvent(QObject*,QEvent*);
       
    90 extern QWidgetList *qt_modal_stack;              // stack of modal widgets
       
    91 extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
       
    92 
       
    93 QWidget *qt_button_down = 0;                     // widget got last button-down
       
    94 
       
    95 QSymbianControl *QSymbianControl::lastFocusedControl = 0;
       
    96 
       
    97 QS60Data* qGlobalS60Data()
       
    98 {
       
    99     return qt_s60Data();
       
   100 }
       
   101 
       
   102 bool qt_nograb()                                // application no-grab option
       
   103 {
       
   104 #if defined(QT_DEBUG)
       
   105     return appNoGrab;
       
   106 #else
       
   107     return false;
       
   108 #endif
       
   109 }
       
   110 
       
   111 // Modified from http://www3.symbian.com/faq.nsf/0/0F1464EE96E737E780256D5E00503DD1?OpenDocument
       
   112 class QS60Beep : public CBase, public MMdaAudioToneObserver
       
   113 {
       
   114 public:
       
   115     static QS60Beep* NewL(TInt aFrequency,  TTimeIntervalMicroSeconds iDuration);
       
   116     void Play();
       
   117     ~QS60Beep();
       
   118 private:
       
   119     void ConstructL(TInt aFrequency,  TTimeIntervalMicroSeconds iDuration);
       
   120     void MatoPrepareComplete(TInt aError);
       
   121     void MatoPlayComplete(TInt aError);
       
   122 private:
       
   123     typedef enum
       
   124         {
       
   125         EBeepNotPrepared,
       
   126         EBeepPrepared,
       
   127         EBeepPlaying
       
   128         } TBeepState;
       
   129 private:
       
   130     CMdaAudioToneUtility* iToneUtil;
       
   131     TBeepState iState;
       
   132     TInt iFrequency;
       
   133     TTimeIntervalMicroSeconds iDuration;
       
   134 };
       
   135 
       
   136 QS60Beep::~QS60Beep()
       
   137 {
       
   138     delete iToneUtil;
       
   139 }
       
   140 
       
   141 QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
       
   142 {
       
   143     QS60Beep* self=new (ELeave) QS60Beep();
       
   144     CleanupStack::PushL(self);
       
   145     self->ConstructL(aFrequency, aDuration);
       
   146     CleanupStack::Pop();
       
   147     return self;
       
   148 };
       
   149 
       
   150 void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
       
   151 {
       
   152     iToneUtil=CMdaAudioToneUtility::NewL(*this);
       
   153     iState=EBeepNotPrepared;
       
   154     iFrequency=aFrequency;
       
   155     iDuration=aDuration;
       
   156     iToneUtil->PrepareToPlayTone(iFrequency,iDuration);
       
   157 }
       
   158 
       
   159 void QS60Beep::Play()
       
   160 {
       
   161     if (iState != EBeepNotPrepared) {
       
   162         if (iState == EBeepPlaying) {
       
   163             iToneUtil->CancelPlay();
       
   164             iState = EBeepPrepared;
       
   165         }
       
   166     }
       
   167 
       
   168     iToneUtil->Play();
       
   169     iState = EBeepPlaying;
       
   170 }
       
   171 
       
   172 void QS60Beep::MatoPrepareComplete(TInt aError)
       
   173 {
       
   174     if (aError == KErrNone) {
       
   175         iState = EBeepPrepared;
       
   176     }
       
   177 }
       
   178 
       
   179 void QS60Beep::MatoPlayComplete(TInt aError)
       
   180 {
       
   181     Q_UNUSED(aError);
       
   182     iState=EBeepPrepared;
       
   183 }
       
   184 
       
   185 
       
   186 QHash<TInt, TUint> QApplicationPrivate::scanCodeCache;
       
   187 
       
   188 static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers)
       
   189 {
       
   190     Qt::KeyboardModifiers result = Qt::NoModifier;
       
   191 
       
   192     if (s60Modifiers & EModifierKeypad)
       
   193         result |= Qt::KeypadModifier;
       
   194     if (s60Modifiers & EModifierShift || s60Modifiers & EModifierLeftShift
       
   195             || s60Modifiers & EModifierRightShift)
       
   196         result |= Qt::ShiftModifier;
       
   197     if (s60Modifiers & EModifierCtrl || s60Modifiers & EModifierLeftCtrl
       
   198             || s60Modifiers & EModifierRightCtrl)
       
   199         result |= Qt::ControlModifier;
       
   200     if (s60Modifiers & EModifierAlt || s60Modifiers & EModifierLeftAlt
       
   201             || s60Modifiers & EModifierRightAlt)
       
   202         result |= Qt::AltModifier;
       
   203 
       
   204     return result;
       
   205 }
       
   206 
       
   207 static void mapS60MouseEventTypeToQt(QEvent::Type *type, Qt::MouseButton *button, const TPointerEvent *pEvent)
       
   208 {
       
   209     switch (pEvent->iType) {
       
   210     case TPointerEvent::EButton1Down:
       
   211         *type = QEvent::MouseButtonPress;
       
   212         *button = Qt::LeftButton;
       
   213         break;
       
   214     case TPointerEvent::EButton1Up:
       
   215         *type = QEvent::MouseButtonRelease;
       
   216         *button = Qt::LeftButton;
       
   217         break;
       
   218     case TPointerEvent::EButton2Down:
       
   219         *type = QEvent::MouseButtonPress;
       
   220         *button = Qt::MidButton;
       
   221         break;
       
   222     case TPointerEvent::EButton2Up:
       
   223         *type = QEvent::MouseButtonRelease;
       
   224         *button = Qt::MidButton;
       
   225         break;
       
   226     case TPointerEvent::EButton3Down:
       
   227         *type = QEvent::MouseButtonPress;
       
   228         *button = Qt::RightButton;
       
   229         break;
       
   230     case TPointerEvent::EButton3Up:
       
   231         *type = QEvent::MouseButtonRelease;
       
   232         *button = Qt::RightButton;
       
   233         break;
       
   234     case TPointerEvent::EDrag:
       
   235         *type = QEvent::MouseMove;
       
   236         *button = Qt::NoButton;
       
   237         break;
       
   238     case TPointerEvent::EMove:
       
   239         // Qt makes no distinction between move and drag
       
   240         *type = QEvent::MouseMove;
       
   241         *button = Qt::NoButton;
       
   242         break;
       
   243     default:
       
   244         *type = QEvent::None;
       
   245         *button = Qt::NoButton;
       
   246         break;
       
   247     }
       
   248     if (pEvent->iModifiers & EModifierDoubleClick){
       
   249         *type = QEvent::MouseButtonDblClick;
       
   250     }
       
   251 
       
   252     if (*type == QEvent::MouseButtonPress || *type == QEvent::MouseButtonDblClick)
       
   253         QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | (*button);
       
   254     else if (*type == QEvent::MouseButtonRelease)
       
   255         QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~(*button));
       
   256 
       
   257     QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & Qt::MouseButtonMask;
       
   258 }
       
   259 
       
   260 //### Can be replaced with CAknLongTapDetector if animation is required.
       
   261 //NOTE: if CAknLongTapDetector is used make sure it gets variated out of 3.1 and 3.2,.
       
   262 //also MLongTapObserver needs to be changed to MAknLongTapDetectorCallBack if CAknLongTapDetector is used.
       
   263 class QLongTapTimer : public CTimer
       
   264 {
       
   265 public:
       
   266     static QLongTapTimer* NewL(QAbstractLongTapObserver *observer);
       
   267     QLongTapTimer(QAbstractLongTapObserver *observer);
       
   268     void ConstructL();
       
   269 public:
       
   270     void PointerEventL(const TPointerEvent &event);
       
   271     void RunL();
       
   272 protected:
       
   273 private:
       
   274     QAbstractLongTapObserver *m_observer;
       
   275     TPointerEvent m_event;
       
   276     QPoint m_pressedCoordinates;
       
   277     int m_dragDistance;
       
   278 };
       
   279 
       
   280 QLongTapTimer* QLongTapTimer::NewL(QAbstractLongTapObserver *observer)
       
   281 {
       
   282     QLongTapTimer* self = new QLongTapTimer(observer);
       
   283     self->ConstructL();
       
   284     return self;
       
   285 }
       
   286 void QLongTapTimer::ConstructL()
       
   287 {
       
   288     CTimer::ConstructL();
       
   289 }
       
   290 
       
   291 QLongTapTimer::QLongTapTimer(QAbstractLongTapObserver *observer):CTimer(CActive::EPriorityHigh)
       
   292 {
       
   293     m_observer = observer;
       
   294     m_dragDistance = qApp->startDragDistance();
       
   295     CActiveScheduler::Add(this);
       
   296 }
       
   297 
       
   298 void QLongTapTimer::PointerEventL(const TPointerEvent& event)
       
   299 {
       
   300     if ( event.iType == TPointerEvent::EDrag || event.iType == TPointerEvent::EButtonRepeat)
       
   301     {
       
   302         QPoint diff(QPoint(event.iPosition.iX,event.iPosition.iY) - m_pressedCoordinates);
       
   303         if (diff.manhattanLength() < m_dragDistance)
       
   304             return;
       
   305     }
       
   306     Cancel();
       
   307     m_event = event;
       
   308     if (event.iType == TPointerEvent::EButton1Down)
       
   309     {
       
   310         m_pressedCoordinates = QPoint(event.iPosition.iX,event.iPosition.iY);
       
   311         // must be same as KLongTapDelay in aknlongtapdetector.h
       
   312         After(800000);
       
   313     }
       
   314 }
       
   315 void QLongTapTimer::RunL()
       
   316 {
       
   317     if (m_observer)
       
   318         m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition);
       
   319 }
       
   320 
       
   321 QSymbianControl::QSymbianControl(QWidget *w)
       
   322     : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false)
       
   323 {
       
   324 }
       
   325 
       
   326 void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop)
       
   327 {
       
   328     if (!desktop)
       
   329     {
       
   330         if (isWindowOwning or !qwidget->parentWidget())
       
   331             CreateWindowL(S60->windowGroup());
       
   332         else
       
   333             /**
       
   334              * TODO: in order to avoid creating windows for all ancestors of
       
   335              * this widget up to the root window, the parameter passed to
       
   336              * CreateWindowL should be
       
   337              * qwidget->parentWidget()->effectiveWinId().  However, if we do
       
   338              * this, then we need to take care of re-parenting when a window
       
   339              * is created for a widget between this one and the root window.
       
   340              */
       
   341             CreateWindowL(qwidget->parentWidget()->winId());
       
   342 
       
   343         // Necessary in order to be able to track the activation status of
       
   344         // the control's window
       
   345         qwidget->d_func()->createExtra();
       
   346 
       
   347         SetFocusing(true);
       
   348         m_longTapDetector = QLongTapTimer::NewL(this);
       
   349     }
       
   350 }
       
   351 
       
   352 QSymbianControl::~QSymbianControl()
       
   353 {
       
   354     if (S60->curWin == this)
       
   355         S60->curWin = 0;
       
   356     if (!QApplicationPrivate::is_app_closing)
       
   357         setFocusSafely(false);
       
   358     S60->appUi()->RemoveFromStack(this);
       
   359     delete m_longTapDetector;
       
   360 }
       
   361 
       
   362 void QSymbianControl::setWidget(QWidget *w)
       
   363 {
       
   364     qwidget = w;
       
   365 }
       
   366 void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation )
       
   367 {
       
   368     QWidget *alienWidget;
       
   369     QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY);
       
   370     QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY);
       
   371     alienWidget = qwidget->childAt(widgetPos);
       
   372     if (!alienWidget)
       
   373         alienWidget = qwidget;
       
   374     QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~Qt::LeftButton);
       
   375     QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton;
       
   376     QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos,
       
   377         Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
       
   378 
       
   379     bool res = sendMouseEvent(alienWidget, &mEvent);
       
   380 
       
   381 #if !defined(QT_NO_CONTEXTMENU)
       
   382     QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, mEvent.modifiers());
       
   383     qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent);
       
   384 #endif
       
   385 
       
   386     m_previousEventLongTap = true;
       
   387 }
       
   388 
       
   389 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
       
   390 void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event)
       
   391 {
       
   392     QApplicationPrivate *d = QApplicationPrivate::instance();
       
   393 
       
   394     QRect screenGeometry = qApp->desktop()->screenGeometry(qwidget);
       
   395 
       
   396     while (d->appAllTouchPoints.count() <= event->PointerNumber())
       
   397         d->appAllTouchPoints.append(QTouchEvent::TouchPoint(d->appAllTouchPoints.count()));
       
   398 
       
   399     Qt::TouchPointStates allStates = 0;
       
   400     for (int i = 0; i < d->appAllTouchPoints.count(); ++i) {
       
   401         QTouchEvent::TouchPoint &touchPoint = d->appAllTouchPoints[i];
       
   402 
       
   403         if (touchPoint.id() == event->PointerNumber()) {
       
   404             Qt::TouchPointStates state;
       
   405             switch (event->iType) {
       
   406             case TPointerEvent::EButton1Down:
       
   407             case TPointerEvent::EEnterHighPressure:
       
   408                 state = Qt::TouchPointPressed;
       
   409                 break;
       
   410             case TPointerEvent::EButton1Up:
       
   411             case TPointerEvent::EExitCloseProximity:
       
   412                 state = Qt::TouchPointReleased;
       
   413                 break;
       
   414             case TPointerEvent::EDrag:
       
   415                 state = Qt::TouchPointMoved;
       
   416                 break;
       
   417             default:
       
   418                 // how likely is this to happen?
       
   419                 state = Qt::TouchPointStationary;
       
   420                 break;
       
   421             }
       
   422             if (event->PointerNumber() == 0)
       
   423                 state |= Qt::TouchPointPrimary;
       
   424             touchPoint.setState(state);
       
   425 
       
   426             QPointF screenPos = QPointF(event->iPosition.iX, event->iPosition.iY);
       
   427             touchPoint.setScreenPos(screenPos);
       
   428             touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(),
       
   429                                                 screenPos.y() / screenGeometry.height()));
       
   430 
       
   431             touchPoint.setPressure(event->Pressure() / qreal(d->maxTouchPressure));
       
   432         } else if (touchPoint.state() != Qt::TouchPointReleased) {
       
   433             // all other active touch points should be marked as stationary
       
   434             touchPoint.setState(Qt::TouchPointStationary);
       
   435         }
       
   436 
       
   437         allStates |= touchPoint.state();
       
   438     }
       
   439 
       
   440     if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) {
       
   441         // all touch points released
       
   442         d->appAllTouchPoints.clear();
       
   443     }
       
   444 
       
   445     QApplicationPrivate::translateRawTouchEvent(qwidget,
       
   446                                                 QTouchEvent::TouchScreen,
       
   447                                                 d->appAllTouchPoints);
       
   448 }
       
   449 #endif
       
   450 
       
   451 void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent)
       
   452 {
       
   453 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
       
   454     if (pEvent.IsAdvancedPointerEvent()) {
       
   455         const TAdvancedPointerEvent *advancedPointerEvent = pEvent.AdvancedPointerEvent();
       
   456         translateAdvancedPointerEvent(advancedPointerEvent);
       
   457         if (advancedPointerEvent->PointerNumber() != 0) {
       
   458             // only send mouse events for the first touch point
       
   459             return;
       
   460         }
       
   461     }
       
   462 #endif
       
   463 
       
   464     m_longTapDetector->PointerEventL(pEvent);
       
   465     QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent));
       
   466 }
       
   467 
       
   468 typedef QPair<QWidget*,QMouseEvent> Event;
       
   469 
       
   470 /*
       
   471  * Helper function called by HandlePointerEvent - separated to keep that function readable
       
   472  */
       
   473 static void generateEnterLeaveEvents(QList<Event> &events, QWidget *widgetUnderPointer,
       
   474     QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
       
   475 {
       
   476     //moved to another widget, create enter and leave events
       
   477     if (S60->lastPointerEventTarget) {
       
   478         QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(
       
   479             S60->lastCursorPos), S60->lastCursorPos, button, QApplicationPrivate::mouse_buttons,
       
   480             modifiers);
       
   481         events.append(Event(S60->lastPointerEventTarget, mEventLeave));
       
   482     }
       
   483     if (widgetUnderPointer) {
       
   484         QMouseEvent mEventEnter(QEvent::Enter, widgetUnderPointer->mapFromGlobal(globalPos),
       
   485             globalPos, button, QApplicationPrivate::mouse_buttons, modifiers);
       
   486 
       
   487         events.append(Event(widgetUnderPointer, mEventEnter));
       
   488 #ifndef QT_NO_CURSOR
       
   489         S60->curWin = widgetUnderPointer->effectiveWinId();
       
   490         if (!QApplication::overrideCursor()) {
       
   491 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
       
   492             if (S60->brokenPointerCursors)
       
   493                 qt_symbian_set_pointer_sprite(widgetUnderPointer->cursor());
       
   494             else
       
   495 #endif
       
   496                 qt_symbian_setWindowCursor(widgetUnderPointer->cursor(), S60->curWin);
       
   497         }
       
   498 #endif
       
   499     }
       
   500 }
       
   501 
       
   502 
       
   503 void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
       
   504 {
       
   505     QMouseEvent::Type type;
       
   506     Qt::MouseButton button;
       
   507     mapS60MouseEventTypeToQt(&type, &button, &pEvent);
       
   508     Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers);
       
   509 
       
   510     if (m_previousEventLongTap)
       
   511         if (type == QEvent::MouseButtonRelease){
       
   512             button = Qt::RightButton;
       
   513             QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton;
       
   514             m_previousEventLongTap = false;
       
   515         }
       
   516     if (type == QMouseEvent::None)
       
   517         return;
       
   518 
       
   519     // store events for later sending/saving
       
   520     QList<Event > events;
       
   521 
       
   522     QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
       
   523     TPoint controlScreenPos = PositionRelativeToScreen();
       
   524     QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
       
   525 
       
   526     // widgets interested in the event
       
   527     QWidget *widgetUnderPointer = qwidget->childAt(widgetPos);
       
   528     if (!widgetUnderPointer)
       
   529         widgetUnderPointer = qwidget; //i.e. this container widget
       
   530 
       
   531     QWidget *widgetWithMouseGrab = QWidget::mouseGrabber();
       
   532 
       
   533     // handle auto grab of pointer when pressing / releasing
       
   534     if (!widgetWithMouseGrab && type == QEvent::MouseButtonPress) {
       
   535         //if previously auto-grabbed, generate a fake mouse release (platform bug: mouse release event was lost)
       
   536         if (S60->mousePressTarget) {
       
   537             QMouseEvent mEvent(QEvent::MouseButtonRelease, S60->mousePressTarget->mapFromGlobal(globalPos), globalPos,
       
   538                 button, QApplicationPrivate::mouse_buttons, modifiers);
       
   539             events.append(Event(S60->mousePressTarget,mEvent));
       
   540         }
       
   541         //auto grab the mouse
       
   542         widgetWithMouseGrab = S60->mousePressTarget = widgetUnderPointer;
       
   543         widgetWithMouseGrab->grabMouse();
       
   544     }
       
   545     if (widgetWithMouseGrab && widgetWithMouseGrab == S60->mousePressTarget && type == QEvent::MouseButtonRelease) {
       
   546         //release the auto grab - note this release event still goes to the autograb widget
       
   547         S60->mousePressTarget = 0;
       
   548         widgetWithMouseGrab->releaseMouse();
       
   549     }
       
   550 
       
   551     QWidget *widgetToReceiveMouseEvent;
       
   552     if (widgetWithMouseGrab)
       
   553         widgetToReceiveMouseEvent = widgetWithMouseGrab;
       
   554     else
       
   555         widgetToReceiveMouseEvent = widgetUnderPointer;
       
   556 
       
   557     //queue QEvent::Enter and QEvent::Leave, if the pointer has moved
       
   558     if (widgetUnderPointer != S60->lastPointerEventTarget && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove))
       
   559         generateEnterLeaveEvents(events, widgetUnderPointer, globalPos, button, modifiers);
       
   560 
       
   561     //save global state
       
   562     S60->lastCursorPos = globalPos;
       
   563     S60->lastPointerEventPos = widgetPos;
       
   564     S60->lastPointerEventTarget = widgetUnderPointer;
       
   565 
       
   566 #if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS)
       
   567     if (S60->brokenPointerCursors)
       
   568         qt_symbian_move_cursor_sprite();
       
   569 #endif
       
   570 
       
   571     //queue this event.
       
   572     Q_ASSERT(widgetToReceiveMouseEvent);
       
   573     QMouseEvent mEvent(type, widgetToReceiveMouseEvent->mapFromGlobal(globalPos), globalPos,
       
   574         button, QApplicationPrivate::mouse_buttons, modifiers);
       
   575     events.append(Event(widgetToReceiveMouseEvent,mEvent));
       
   576     QEventDispatcherS60 *dispatcher;
       
   577     // It is theoretically possible for someone to install a different event dispatcher.
       
   578     if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widgetToReceiveMouseEvent->d_func()->threadData->eventDispatcher)) != 0) {
       
   579         if (dispatcher->excludeUserInputEvents()) {
       
   580             for (int i=0;i < events.count();++i)
       
   581             {
       
   582                 Event next = events[i];
       
   583                 dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second));
       
   584             }
       
   585             return;
       
   586         }
       
   587     }
       
   588 
       
   589     //send events in the queue
       
   590     for (int i=0;i < events.count();++i)
       
   591     {
       
   592         Event next = events[i];
       
   593         sendMouseEvent(next.first, &(next.second));
       
   594     }
       
   595 }
       
   596 
       
   597 bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent)
       
   598 {
       
   599     return qt_sendSpontaneousEvent(widget, mEvent);
       
   600 }
       
   601 
       
   602 TKeyResponse QSymbianControl::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCode type)
       
   603 {
       
   604     TKeyResponse r = EKeyWasNotConsumed;
       
   605     QT_TRYCATCH_LEAVING(r = OfferKeyEvent(keyEvent, type));
       
   606     return r;
       
   607 }
       
   608 
       
   609 TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type)
       
   610 {
       
   611     switch (type) {
       
   612     //case EEventKeyDown: // <-- Intentionally left out. See below.
       
   613     case EEventKeyUp:
       
   614     case EEventKey:
       
   615     {
       
   616         // S60 has a confusing way of delivering key events. There are three types of
       
   617         // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the
       
   618         // two first events are generated. When releasing the key, the last one is
       
   619         // generated.
       
   620         // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events,
       
   621         // we need to do some special tricks to map it to the Qt way. First, we completely
       
   622         // discard EKeyEventDown events, since they are redundant. Second, since
       
   623         // EKeyEventUp does not give us a keysym, we need to cache the keysyms from
       
   624         // the EKeyEvent events. This is what resolveS60ScanCode does.
       
   625 
       
   626 
       
   627         // ### hackish way to send Qt application to background when pressing right softkey
       
   628         /*
       
   629         if( keyEvent.iScanCode == EStdKeyDevice1 ) {
       
   630             S60->window_group->SetOrdinalPosition(-1);
       
   631             qApp->setActiveWindow(0);
       
   632             return EKeyWasNotConsumed;
       
   633         }
       
   634         */
       
   635 
       
   636         TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode,
       
   637                 keyEvent.iCode);
       
   638         int keyCode;
       
   639         if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
       
   640             // Normal characters keys.
       
   641             keyCode = s60Keysym;
       
   642         } else {
       
   643             // Special S60 keys.
       
   644             keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym);
       
   645         }
       
   646 
       
   647 #ifndef QT_NO_CURSOR
       
   648         if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) {
       
   649             //translate keys to pointer
       
   650             if (keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down || keyCode == Qt::Key_Select) {
       
   651                 /*Explanation about virtualMouseAccel:
       
   652                  Tapping an arrow key allows precise pixel positioning
       
   653                  Holding an arrow key down, acceleration is applied to allow cursor
       
   654                  to be quickly moved to another part of the screen by key repeats.
       
   655                  */
       
   656                 if (S60->virtualMouseLastKey == keyCode) {
       
   657                     S60->virtualMouseAccel *= 2;
       
   658                     if (S60->virtualMouseAccel > S60->virtualMouseMaxAccel)
       
   659                         S60->virtualMouseAccel = S60->virtualMouseMaxAccel;
       
   660                 }
       
   661                 else
       
   662                     S60->virtualMouseAccel = 1;
       
   663                 S60->virtualMouseLastKey = keyCode;
       
   664 
       
   665                 QPoint pos = QCursor::pos();
       
   666                 TPointerEvent fakeEvent;
       
   667                 TInt x = pos.x();
       
   668                 TInt y = pos.y();
       
   669                 if (type == EEventKeyUp) {
       
   670                     if (keyCode == Qt::Key_Select)
       
   671                         fakeEvent.iType = TPointerEvent::EButton1Up;
       
   672                     S60->virtualMouseAccel = 1;
       
   673                     S60->virtualMouseLastKey = 0;
       
   674                 }
       
   675                 else if (type == EEventKey) {
       
   676                     switch (keyCode) {
       
   677                     case Qt::Key_Left:
       
   678                         x -= S60->virtualMouseAccel;
       
   679                         fakeEvent.iType = TPointerEvent::EMove;
       
   680                         break;
       
   681                     case Qt::Key_Right:
       
   682                         x += S60->virtualMouseAccel;
       
   683                         fakeEvent.iType = TPointerEvent::EMove;
       
   684                         break;
       
   685                     case Qt::Key_Up:
       
   686                         y -= S60->virtualMouseAccel;
       
   687                         fakeEvent.iType = TPointerEvent::EMove;
       
   688                         break;
       
   689                     case Qt::Key_Down:
       
   690                         y += S60->virtualMouseAccel;
       
   691                         fakeEvent.iType = TPointerEvent::EMove;
       
   692                         break;
       
   693                     case Qt::Key_Select:
       
   694                         fakeEvent.iType = TPointerEvent::EButton1Down;
       
   695                         break;
       
   696                     }
       
   697                 }
       
   698                 //clip to screen size (window server allows a sprite hotspot to be outside the screen)
       
   699                 if (x < 0)
       
   700                     x = 0;
       
   701                 else if (x >= S60->screenWidthInPixels)
       
   702                     x = S60->screenWidthInPixels - 1;
       
   703                 if (y < 0)
       
   704                     y = 0;
       
   705                 else if (y >= S60->screenHeightInPixels)
       
   706                     y = S60->screenHeightInPixels - 1;
       
   707                 TPoint epos(x, y);
       
   708                 TPoint cpos = epos - PositionRelativeToScreen();
       
   709                 fakeEvent.iModifiers = keyEvent.iModifiers;
       
   710                 fakeEvent.iPosition = cpos;
       
   711                 fakeEvent.iParentPosition = epos;
       
   712                 HandlePointerEvent(fakeEvent);
       
   713                 return EKeyWasConsumed;
       
   714             }
       
   715             else {
       
   716                 S60->virtualMouseLastKey = keyCode;
       
   717                 S60->virtualMouseAccel = 1;
       
   718             }
       
   719         }
       
   720 #endif
       
   721 
       
   722         Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
       
   723         QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
       
   724                 mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
       
   725                 false, 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
       
   726 //        WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
       
   727 //        if (!wid)
       
   728 //             Could happen if window isn't shown yet.
       
   729 //            return EKeyWasNotConsumed;
       
   730         QWidget *widget;
       
   731         widget = QWidget::keyboardGrabber();
       
   732         if (!widget) {
       
   733             if (QApplicationPrivate::popupWidgets != 0) {
       
   734                 widget = QApplication::activePopupWidget()->focusWidget();
       
   735                 if (!widget) {
       
   736                     widget = QApplication::activePopupWidget();
       
   737                 }
       
   738             } else {
       
   739                 widget = QApplicationPrivate::focus_widget;
       
   740                 if (!widget) {
       
   741                     widget = qwidget;
       
   742                 }
       
   743             }
       
   744         }
       
   745 
       
   746         QEventDispatcherS60 *dispatcher;
       
   747         // It is theoretically possible for someone to install a different event dispatcher.
       
   748         if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) {
       
   749             if (dispatcher->excludeUserInputEvents()) {
       
   750                 dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent));
       
   751                 return EKeyWasConsumed;
       
   752             }
       
   753         }
       
   754         return sendKeyEvent(widget, &qKeyEvent);
       
   755     }
       
   756     }
       
   757     return EKeyWasNotConsumed;
       
   758 }
       
   759 
       
   760 void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent)
       
   761 {
       
   762     switch (inputEvent->type()) {
       
   763     case QEvent::KeyPress:
       
   764     case QEvent::KeyRelease:
       
   765         sendKeyEvent(widget, static_cast<QKeyEvent *>(inputEvent));
       
   766         break;
       
   767     case QEvent::MouseButtonDblClick:
       
   768     case QEvent::MouseButtonPress:
       
   769     case QEvent::MouseButtonRelease:
       
   770     case QEvent::MouseMove:
       
   771         sendMouseEvent(widget, static_cast<QMouseEvent *>(inputEvent));
       
   772         break;
       
   773     default:
       
   774         // Shouldn't get here.
       
   775         Q_ASSERT_X(0 == 1, "QSymbianControl::sendInputEvent()", "inputEvent->type() is unknown");
       
   776         break;
       
   777     }
       
   778 }
       
   779 
       
   780 TKeyResponse QSymbianControl::sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent)
       
   781 {
       
   782 #if !defined(QT_NO_IM) && defined(Q_WS_S60)
       
   783     if (widget && widget->isEnabled() && widget->testAttribute(Qt::WA_InputMethodEnabled)) {
       
   784         QInputContext *qic = widget->inputContext();
       
   785         if (qic && qic->filterEvent(keyEvent))
       
   786             return EKeyWasConsumed;
       
   787     }
       
   788 #endif // !defined(QT_NO_IM) && defined(Q_WS_S60)
       
   789 
       
   790     if (widget && qt_sendSpontaneousEvent(widget, keyEvent))
       
   791         if (keyEvent->isAccepted())
       
   792             return EKeyWasConsumed;
       
   793 
       
   794     return EKeyWasNotConsumed;
       
   795 }
       
   796 
       
   797 #if !defined(QT_NO_IM) && defined(Q_WS_S60)
       
   798 TCoeInputCapabilities QSymbianControl::InputCapabilities() const
       
   799 {
       
   800     QWidget *w = 0;
       
   801 
       
   802     if (qwidget->hasFocus())
       
   803         w = qwidget;
       
   804     else
       
   805         w = qwidget->focusWidget();
       
   806 
       
   807     QCoeFepInputContext *ic;
       
   808     if (w && w->isEnabled() && w->testAttribute(Qt::WA_InputMethodEnabled)
       
   809             && (ic = qobject_cast<QCoeFepInputContext *>(w->inputContext()))) {
       
   810         return ic->inputCapabilities();
       
   811     } else {
       
   812         return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0);
       
   813     }
       
   814 }
       
   815 #endif
       
   816 
       
   817 void QSymbianControl::Draw(const TRect& controlRect) const
       
   818 {
       
   819     QWindowSurface *surface = qwidget->windowSurface();
       
   820     QPaintEngine *engine = surface ? surface->paintDevice()->paintEngine() : NULL;
       
   821 
       
   822     if (!engine)
       
   823         return;
       
   824 
       
   825     // Map source rectangle into coordinates of the backing store.
       
   826     const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY);
       
   827     const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase);
       
   828     const TRect backingStoreRect(TPoint(backingStoreBase.x(), backingStoreBase.y()), controlRect.Size());
       
   829 
       
   830     if (engine->type() == QPaintEngine::Raster) {
       
   831         QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
       
   832         CFbsBitmap *bitmap = s60Surface->symbianBitmap();
       
   833         CWindowGc &gc = SystemGc();
       
   834 
       
   835         if(!qwidget->d_func()->extraData()->disableBlit) {
       
   836             if (qwidget->d_func()->isOpaque)
       
   837                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
       
   838             gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
       
   839 	    }
       
   840     } else {
       
   841         surface->flush(qwidget, QRegion(qt_TRect2QRect(backingStoreRect)), QPoint());
       
   842     }
       
   843 }
       
   844 
       
   845 void QSymbianControl::SizeChanged()
       
   846 {
       
   847     CCoeControl::SizeChanged();
       
   848 
       
   849     QSize oldSize = qwidget->size();
       
   850     QSize newSize(Size().iWidth, Size().iHeight);
       
   851 
       
   852     if (oldSize != newSize) {
       
   853         QRect cr = qwidget->geometry();
       
   854         cr.setSize(newSize);
       
   855         qwidget->data->crect = cr;
       
   856         if (qwidget->isVisible()) {
       
   857             QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData();
       
   858             bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
       
   859             if (!slowResize && tlwExtra)
       
   860                 tlwExtra->inTopLevelResize = true;
       
   861             QResizeEvent e(newSize, oldSize);
       
   862             qt_sendSpontaneousEvent(qwidget, &e);
       
   863             if (!qwidget->testAttribute(Qt::WA_StaticContents))
       
   864                 qwidget->d_func()->syncBackingStore();
       
   865             if (!slowResize && tlwExtra)
       
   866                 tlwExtra->inTopLevelResize = false;
       
   867         }
       
   868     }
       
   869 }
       
   870 
       
   871 void QSymbianControl::PositionChanged()
       
   872 {
       
   873     CCoeControl::PositionChanged();
       
   874 
       
   875     QPoint oldPos = qwidget->geometry().topLeft();
       
   876     QPoint newPos(Position().iX, Position().iY);
       
   877 
       
   878     if (oldPos != newPos) {
       
   879         QRect cr = qwidget->geometry();
       
   880         cr.moveTopLeft(newPos);
       
   881         qwidget->data->crect = cr;
       
   882         QTLWExtra *top = qwidget->d_func()->maybeTopData();
       
   883         if (top)
       
   884             top->normalGeometry = cr;
       
   885         if (qwidget->isVisible()) {
       
   886             QMoveEvent e(newPos, oldPos);
       
   887             qt_sendSpontaneousEvent(qwidget, &e);
       
   888         } else {
       
   889             QMoveEvent * e = new QMoveEvent(newPos, oldPos);
       
   890             QApplication::postEvent(qwidget, e);
       
   891         }
       
   892     }
       
   893 }
       
   894 
       
   895 void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
       
   896 {
       
   897     if (m_ignoreFocusChanged)
       
   898         return;
       
   899 
       
   900     // Popups never get focused, but still receive the FocusChanged when they are hidden.
       
   901     if (QApplicationPrivate::popupWidgets != 0
       
   902             || (qwidget->windowType() & Qt::Popup) == Qt::Popup)
       
   903         return;
       
   904 
       
   905     if (IsFocused() && IsVisible()) {
       
   906         QApplication::setActiveWindow(qwidget->window());
       
   907 #ifdef Q_WS_S60
       
   908         // If widget is fullscreen, hide status pane and button container
       
   909         // otherwise show them.
       
   910         CEikStatusPane* statusPane = S60->statusPane();
       
   911         CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
       
   912         bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
       
   913         if (statusPane && (statusPane->IsVisible() == isFullscreen))
       
   914             statusPane->MakeVisible(!isFullscreen);
       
   915         if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen))
       
   916             buttonGroup->MakeVisible(!isFullscreen);
       
   917 #endif
       
   918     } else if (QApplication::activeWindow() == qwidget->window()) {
       
   919         QApplication::setActiveWindow(0);
       
   920     }
       
   921     // else { We don't touch the active window unless we were explicitly activated or deactivated }
       
   922 }
       
   923 
       
   924 void QSymbianControl::HandleResourceChange(int resourceType)
       
   925 {
       
   926     switch (resourceType) {
       
   927     case KInternalStatusPaneChange:
       
   928         qwidget->d_func()->setWindowIcon_sys(true);
       
   929         break;
       
   930     case KUidValueCoeFontChangeEvent:
       
   931         // font change event
       
   932         break;
       
   933 #ifdef Q_WS_S60
       
   934     case KEikDynamicLayoutVariantSwitch:
       
   935     {
       
   936         if (qwidget->isFullScreen()) {
       
   937             SetExtentToWholeScreen();
       
   938         } else if (qwidget->isMaximized()) {
       
   939             TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
       
   940             SetExtent(r.iTl, r.Size());
       
   941         }
       
   942         break;
       
   943     }
       
   944 #endif
       
   945     default:
       
   946         break;
       
   947     }
       
   948 
       
   949     CCoeControl::HandleResourceChange(resourceType);
       
   950 
       
   951 }
       
   952 void QSymbianControl::CancelLongTapTimer()
       
   953 {
       
   954     m_longTapDetector->Cancel();
       
   955 }
       
   956 
       
   957 TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id)
       
   958 {
       
   959     if (id.iUid == ETypeId)
       
   960         return id.MakePtr(this);
       
   961 
       
   962     return CCoeControl::MopSupplyObject(id);
       
   963 }
       
   964 
       
   965 void QSymbianControl::setFocusSafely(bool focus)
       
   966 {
       
   967     // The stack hack in here is very unfortunate, but it is the only way to ensure proper
       
   968     // focus in Symbian. If this is not executed, the control which happens to be on
       
   969     // the top of the stack may randomly be assigned focus by Symbian, for example
       
   970     // when creating new windows (specifically in CCoeAppUi::HandleStackChanged()).
       
   971     if (focus) {
       
   972         S60->appUi()->RemoveFromStack(this);
       
   973         // Symbian doesn't automatically remove focus from the last focused control, so we need to
       
   974         // remember it and clear focus ourselves.
       
   975         if (lastFocusedControl && lastFocusedControl != this)
       
   976             lastFocusedControl->SetFocus(false);
       
   977         QT_TRAP_THROWING(S60->appUi()->AddToStackL(this,
       
   978                 ECoeStackPriorityDefault + 1, ECoeStackFlagStandard)); // Note the + 1
       
   979         lastFocusedControl = this;
       
   980         this->SetFocus(true);
       
   981     } else {
       
   982         S60->appUi()->RemoveFromStack(this);
       
   983         QT_TRAP_THROWING(S60->appUi()->AddToStackL(this,
       
   984                 ECoeStackPriorityDefault, ECoeStackFlagStandard));
       
   985         if(this == lastFocusedControl)
       
   986             lastFocusedControl = 0;
       
   987         this->SetFocus(false);
       
   988     }
       
   989 }
       
   990 
       
   991 /*!
       
   992     \typedef QApplication::QS60MainApplicationFactory
       
   993     \since 4.6
       
   994 
       
   995     This is a typedef for a pointer to a function with the following
       
   996     signature:
       
   997 
       
   998     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 47
       
   999 
       
  1000     \sa QApplication::QApplication()
       
  1001 */
       
  1002 
       
  1003 /*!
       
  1004     \since 4.6
       
  1005 
       
  1006     Creates an application using the application factory given in
       
  1007     \a factory, and using \a argc command line arguments in \a argv.
       
  1008     \a factory can be leaving, but the error will be converted to a
       
  1009     standard exception.
       
  1010 
       
  1011     This function is only available on S60.
       
  1012 */
       
  1013 QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv)
       
  1014     : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
       
  1015 {
       
  1016     Q_D(QApplication);
       
  1017     S60->s60ApplicationFactory = factory;
       
  1018     d->construct();
       
  1019 }
       
  1020 
       
  1021 QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal)
       
  1022     : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
       
  1023 {
       
  1024     Q_D(QApplication);
       
  1025     S60->s60ApplicationFactory = factory;
       
  1026     d->construct();
       
  1027     QApplicationPrivate::app_compile_version = _internal;
       
  1028 }
       
  1029 
       
  1030 void qt_init(QApplicationPrivate * /* priv */, int)
       
  1031 {
       
  1032     if (!CCoeEnv::Static()) {
       
  1033         // The S60 framework creates a new trap handler which will render any existing traps
       
  1034         // invalid as long as it is active. This means that all code in main() that occurs after
       
  1035         // the QApplication construction needs to be surrounded by a new trap, despite having
       
  1036         // an outer one already. To avoid this, we save the original trap handler here, and set
       
  1037         // it back after the S60 framework is constructed. Then we restore it right before the S60
       
  1038         // framework destruction.
       
  1039         TTrapHandler *origTrapHandler = User::TrapHandler();
       
  1040 
       
  1041         // The S60 framework has not been initalized. We need to do it.
       
  1042         TApaApplicationFactory factory(S60->s60ApplicationFactory ?
       
  1043                 S60->s60ApplicationFactory : newS60Application);
       
  1044         CApaCommandLine* commandLine = 0;
       
  1045         TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine);
       
  1046         // After this construction, CEikonEnv will be available from CEikonEnv::Static().
       
  1047         // (much like our qApp).
       
  1048         CEikonEnv* coe = new CEikonEnv;
       
  1049         QT_TRAP_THROWING(coe->ConstructAppFromCommandLineL(factory,*commandLine));
       
  1050         delete commandLine;
       
  1051 
       
  1052         S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler);
       
  1053 
       
  1054         S60->qtOwnsS60Environment = true;
       
  1055     } else {
       
  1056         S60->qtOwnsS60Environment = false;
       
  1057     }
       
  1058 
       
  1059 #ifdef QT_NO_DEBUG
       
  1060     if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty())
       
  1061 #endif
       
  1062         S60->wsSession().SetAutoFlush(ETrue);
       
  1063 
       
  1064     S60->updateScreenSize();
       
  1065 
       
  1066 
       
  1067     TDisplayMode mode = S60->screenDevice()->DisplayMode();
       
  1068     S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode);
       
  1069 
       
  1070     //NB: RWsSession::GetColorModeList tells you what window modes are supported,
       
  1071     //not what bitmap formats.
       
  1072     if(QSysInfo::symbianVersion() == QSysInfo::SV_9_2)
       
  1073         S60->supportsPremultipliedAlpha = 0;
       
  1074     else
       
  1075         S60->supportsPremultipliedAlpha = 1;
       
  1076 
       
  1077     RProcess me;
       
  1078     TSecureId securId = me.SecureId();
       
  1079     S60->uid = securId.operator TUid();
       
  1080 
       
  1081     // enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app,
       
  1082     // and for dimming behind modal windows
       
  1083 	S60->windowGroup().EnableFocusChangeEvents();
       
  1084 
       
  1085 	//Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this)
       
  1086     const TInt KMachineUidSamsungI8510 = 0x2000C51E;
       
  1087     // HAL::Get(HALData::EPen, TInt& result) may set 'result' to 1 on some 3.1 systems (e.g. N95).
       
  1088     // But we know that S60 systems below 5.0 did not support touch.
       
  1089     static const bool touchIsUnsupportedOnSystem =
       
  1090         QSysInfo::s60Version() == QSysInfo::SV_S60_3_1
       
  1091         || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2;
       
  1092     TInt machineUID;
       
  1093     TInt mouse;
       
  1094     TInt touch;
       
  1095     TInt err;
       
  1096     err = HAL::Get(HALData::EMouse, mouse);
       
  1097     if (err != KErrNone)
       
  1098         mouse = 0;
       
  1099     err = HAL::Get(HALData::EMachineUid, machineUID);
       
  1100     if (err != KErrNone)
       
  1101         machineUID = 0;
       
  1102     err = HAL::Get(HALData::EPen, touch);
       
  1103     if (err != KErrNone || touchIsUnsupportedOnSystem)
       
  1104         touch = 0;
       
  1105 #ifdef __WINS__
       
  1106     if(QSysInfo::symbianVersion() <= QSysInfo::SV_9_4) {
       
  1107         //for symbian SDK emulator, force values to match typical devices.
       
  1108         mouse = 0;
       
  1109         touch = touchIsUnsupportedOnSystem ? 0 : 1;
       
  1110     }
       
  1111 #endif
       
  1112     if (mouse || machineUID == KMachineUidSamsungI8510) {
       
  1113         S60->hasTouchscreen = false;
       
  1114         S60->virtualMouseRequired = false;
       
  1115     }
       
  1116     else if (!touch) {
       
  1117         S60->hasTouchscreen = false;
       
  1118         S60->virtualMouseRequired = true;
       
  1119     }
       
  1120     else {
       
  1121         S60->hasTouchscreen = true;
       
  1122         S60->virtualMouseRequired = false;
       
  1123     }
       
  1124 
       
  1125     if (touch) {
       
  1126         QApplicationPrivate::navigationMode = Qt::NavigationModeNone;
       
  1127     } else {
       
  1128         QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional;
       
  1129     }
       
  1130 
       
  1131 #ifndef QT_NO_CURSOR
       
  1132     //Check if window server pointer cursors are supported or not
       
  1133 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
       
  1134     //In generic binary, use the HAL and OS version
       
  1135     //Any other known good phones should be added here.
       
  1136     if (machineUID == KMachineUidSamsungI8510 || (QSysInfo::symbianVersion() != QSysInfo::SV_9_4
       
  1137         && QSysInfo::symbianVersion() != QSysInfo::SV_9_3 && QSysInfo::symbianVersion()
       
  1138         != QSysInfo::SV_9_2)) {
       
  1139         S60->brokenPointerCursors = false;
       
  1140         qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup());
       
  1141     }
       
  1142     else
       
  1143         S60->brokenPointerCursors = true;
       
  1144 #endif
       
  1145 
       
  1146     if (S60->mouseInteractionEnabled) {
       
  1147 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
       
  1148         if (S60->brokenPointerCursors) {
       
  1149             qt_symbian_set_pointer_sprite(Qt::ArrowCursor);
       
  1150             qt_symbian_show_pointer_sprite();
       
  1151         }
       
  1152         else
       
  1153 #endif
       
  1154             S60->wsSession().SetPointerCursorMode(EPointerCursorNormal);
       
  1155     }
       
  1156 #endif
       
  1157 
       
  1158     QFont systemFont;
       
  1159     systemFont.setFamily(systemFont.defaultFamily());
       
  1160     QApplicationPrivate::setSystemFont(systemFont);
       
  1161 
       
  1162 /*
       
  1163  ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag
       
  1164     int argc = priv->argc;
       
  1165     char **argv = priv->argv;
       
  1166 
       
  1167     // Get command line params
       
  1168     int j = argc ? 1 : 0;
       
  1169     for (int i=1; i<argc; i++) {
       
  1170         if (argv[i] && *argv[i] != '-') {
       
  1171             argv[j++] = argv[i];
       
  1172             continue;
       
  1173         }
       
  1174 
       
  1175 #if defined(QT_DEBUG)
       
  1176         if (qstrcmp(argv[i], "-nograb") == 0)
       
  1177             appNoGrab = !appNoGrab;
       
  1178         else
       
  1179 #endif // QT_DEBUG
       
  1180             ;
       
  1181     }
       
  1182 */
       
  1183 
       
  1184     // Register WId with the metatype system.  This is to enable
       
  1185     // QWidgetPrivate::create_sys to used delayed slot invokation in order
       
  1186     // to destroy WId objects during reparenting.
       
  1187     qRegisterMetaType<WId>("WId");
       
  1188 }
       
  1189 
       
  1190 /*****************************************************************************
       
  1191   qt_cleanup() - cleans up when the application is finished
       
  1192  *****************************************************************************/
       
  1193 void qt_cleanup()
       
  1194 {
       
  1195     QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
       
  1196 // S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
       
  1197 
       
  1198     // It's important that this happens here, before the event dispatcher gets
       
  1199     // deleted, because the input context needs the event loop one last time before
       
  1200     // it dies.
       
  1201     delete QApplicationPrivate::inputContext;
       
  1202     QApplicationPrivate::inputContext = 0;
       
  1203 
       
  1204     //Change mouse pointer back
       
  1205     S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
       
  1206 
       
  1207     if (S60->qtOwnsS60Environment) {
       
  1208         // Restore the S60 framework trap handler. See qt_init().
       
  1209         User::SetTrapHandler(S60->s60InstalledTrapHandler);
       
  1210 
       
  1211         CEikonEnv* coe = CEikonEnv::Static();
       
  1212         coe->PrepareToExit();
       
  1213         // The CEikonEnv itself is destroyed in here.
       
  1214         coe->DestroyEnvironment();
       
  1215     }
       
  1216 }
       
  1217 
       
  1218 void QApplicationPrivate::initializeWidgetPaletteHash()
       
  1219 {
       
  1220     // TODO: Implement QApplicationPrivate::initializeWidgetPaletteHash()
       
  1221     // Possibly a task fot the S60Style guys
       
  1222 }
       
  1223 
       
  1224 void QApplicationPrivate::createEventDispatcher()
       
  1225 {
       
  1226     Q_Q(QApplication);
       
  1227     eventDispatcher = new QEventDispatcherS60(q);
       
  1228 }
       
  1229 
       
  1230 QString QApplicationPrivate::appName() const
       
  1231 {
       
  1232     return QCoreApplicationPrivate::appName();
       
  1233 }
       
  1234 
       
  1235 bool QApplicationPrivate::modalState()
       
  1236 {
       
  1237     return app_do_modal;
       
  1238 }
       
  1239 
       
  1240 void QApplicationPrivate::enterModal_sys(QWidget *widget)
       
  1241 {
       
  1242     if (widget) {
       
  1243         widget->effectiveWinId()->DrawableWindow()->FadeBehind(ETrue);
       
  1244         // Modal partial screen dialogs (like queries) capture pointer events.
       
  1245         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
       
  1246         widget->effectiveWinId()->SetGloballyCapturing(ETrue);
       
  1247         widget->effectiveWinId()->SetPointerCapture(ETrue);
       
  1248     }
       
  1249     if (!qt_modal_stack)
       
  1250         qt_modal_stack = new QWidgetList;
       
  1251     qt_modal_stack->insert(0, widget);
       
  1252     app_do_modal = true;
       
  1253 }
       
  1254 
       
  1255 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
       
  1256 {
       
  1257     if (widget) {
       
  1258         widget->effectiveWinId()->DrawableWindow()->FadeBehind(EFalse);
       
  1259         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
       
  1260         widget->effectiveWinId()->SetGloballyCapturing(EFalse);
       
  1261         widget->effectiveWinId()->SetPointerCapture(EFalse);
       
  1262     }
       
  1263     if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
       
  1264         if (qt_modal_stack->isEmpty()) {
       
  1265             delete qt_modal_stack;
       
  1266             qt_modal_stack = 0;
       
  1267         }
       
  1268     }
       
  1269     app_do_modal = qt_modal_stack != 0;
       
  1270 }
       
  1271 
       
  1272 void QApplicationPrivate::openPopup(QWidget *popup)
       
  1273 {
       
  1274     if (!QApplicationPrivate::popupWidgets)
       
  1275         QApplicationPrivate::popupWidgets = new QWidgetList;
       
  1276     QApplicationPrivate::popupWidgets->append(popup);
       
  1277 
       
  1278 
       
  1279     // Cancel focus widget pointer capture and long tap timer
       
  1280     if (QApplication::focusWidget()) {
       
  1281         static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer();
       
  1282         QApplication::focusWidget()->effectiveWinId()->SetPointerCapture(false);
       
  1283         }
       
  1284 
       
  1285     if (!qt_nograb()) {
       
  1286         // Cancel pointer capture and long tap timer for earlier popup
       
  1287         int popupCount = QApplicationPrivate::popupWidgets->count();
       
  1288         if (popupCount > 1) {
       
  1289             QWidget* prevPopup = QApplicationPrivate::popupWidgets->at(popupCount-2);
       
  1290             static_cast<QSymbianControl*>(prevPopup->effectiveWinId())->CancelLongTapTimer();
       
  1291             prevPopup->effectiveWinId()->SetPointerCapture(false);
       
  1292         }
       
  1293 
       
  1294         // Enable pointer capture for this (topmost) popup
       
  1295         Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
       
  1296         WId id = popup->effectiveWinId();
       
  1297         id->SetPointerCapture(true);
       
  1298     }
       
  1299 
       
  1300     // popups are not focus-handled by the window system (the first
       
  1301     // popup grabbed the keyboard), so we have to do that manually: A
       
  1302     // new popup gets the focus
       
  1303     QWidget *fw = popup->focusWidget();
       
  1304     if (fw) {
       
  1305         fw->setFocus(Qt::PopupFocusReason);
       
  1306     } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
       
  1307         fw = QApplication::focusWidget();
       
  1308         if (fw) {
       
  1309             QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
       
  1310             q_func()->sendEvent(fw, &e);
       
  1311         }
       
  1312     }
       
  1313 }
       
  1314 
       
  1315 void QApplicationPrivate::closePopup(QWidget *popup)
       
  1316 {
       
  1317     if (!QApplicationPrivate::popupWidgets)
       
  1318         return;
       
  1319     QApplicationPrivate::popupWidgets->removeAll(popup);
       
  1320 
       
  1321     // Cancel pointer capture and long tap for this popup
       
  1322     WId id = popup->effectiveWinId();
       
  1323     id->SetPointerCapture(false);
       
  1324     static_cast<QSymbianControl*>(id)->CancelLongTapTimer();
       
  1325 
       
  1326     if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
       
  1327         delete QApplicationPrivate::popupWidgets;
       
  1328         QApplicationPrivate::popupWidgets = 0;
       
  1329         if (!qt_nograb()) {                        // grabbing not disabled
       
  1330             Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
       
  1331             if (QWidgetPrivate::mouseGrabber != 0)
       
  1332                 QWidgetPrivate::mouseGrabber->grabMouse();
       
  1333 
       
  1334             if (QWidgetPrivate::keyboardGrabber != 0)
       
  1335                 QWidgetPrivate::keyboardGrabber->grabKeyboard();
       
  1336 
       
  1337         QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
       
  1338               : q_func()->focusWidget();
       
  1339           if (fw) {
       
  1340               if (fw != q_func()->focusWidget()) {
       
  1341                   fw->setFocus(Qt::PopupFocusReason);
       
  1342               } else {
       
  1343                   QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
       
  1344                   q_func()->sendEvent(fw, &e);
       
  1345               }
       
  1346           }
       
  1347         }
       
  1348     } else {
       
  1349 
       
  1350         // popups are not focus-handled by the window system (the
       
  1351         // first popup grabbed the keyboard), so we have to do that
       
  1352         // manually: A popup was closed, so the previous popup gets
       
  1353         // the focus.
       
  1354         QWidget* aw = QApplicationPrivate::popupWidgets->last();
       
  1355         if (QWidget *fw = QApplication::focusWidget()) {
       
  1356             QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
       
  1357             q_func()->sendEvent(fw, &e);
       
  1358         }
       
  1359 
       
  1360         // Enable pointer capture for previous popup
       
  1361         if (aw) {
       
  1362             aw->effectiveWinId()->SetPointerCapture(true);
       
  1363         }
       
  1364     }
       
  1365 }
       
  1366 
       
  1367 QWidget * QApplication::topLevelAt(QPoint const& point)
       
  1368 {
       
  1369     QWidget *found = 0;
       
  1370     int lowestZ = INT_MAX;
       
  1371     QWidgetList list = QApplication::topLevelWidgets();
       
  1372     for (int i = 0; i < list.count(); ++i) {
       
  1373         QWidget *widget = list.at(i);
       
  1374         if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) {
       
  1375             Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
       
  1376             if (widget->geometry().adjusted(0,0,1,1).contains(point)) {
       
  1377                 // At this point we know there is a Qt widget under the point.
       
  1378                 // Now we need to make sure it is the top most in the z-order.
       
  1379                 RDrawableWindow *const window = widget->effectiveWinId()->DrawableWindow();
       
  1380                 int z = window->OrdinalPosition();
       
  1381                 if (z < lowestZ) {
       
  1382                     lowestZ = z;
       
  1383                     found = widget;
       
  1384                 }
       
  1385             }
       
  1386         }
       
  1387     }
       
  1388     return found;
       
  1389 }
       
  1390 
       
  1391 void QApplication::alert(QWidget * /* widget */, int /* duration */)
       
  1392 {
       
  1393     // TODO: Implement QApplication::alert(QWidget *widget, int duration)
       
  1394 }
       
  1395 
       
  1396 int QApplication::doubleClickInterval()
       
  1397 {
       
  1398     TTimeIntervalMicroSeconds32 us;
       
  1399     TInt distance;
       
  1400     S60->wsSession().GetDoubleClickSettings(us, distance);
       
  1401     return (us.Int() / 1000);
       
  1402 }
       
  1403 
       
  1404 void QApplication::setDoubleClickInterval(int ms)
       
  1405 {
       
  1406     TTimeIntervalMicroSeconds32 newUs( ms * 1000);
       
  1407     TTimeIntervalMicroSeconds32 us;
       
  1408     TInt distance;
       
  1409     S60->wsSession().GetDoubleClickSettings(us, distance);
       
  1410     if (us != newUs)
       
  1411         S60->wsSession().SetDoubleClick(newUs, distance);
       
  1412 }
       
  1413 
       
  1414 int QApplication::keyboardInputInterval()
       
  1415 {
       
  1416     return QApplicationPrivate::keyboard_input_time;
       
  1417 }
       
  1418 
       
  1419 void QApplication::setKeyboardInputInterval(int ms)
       
  1420 {
       
  1421     QApplicationPrivate::keyboard_input_time = ms;
       
  1422 }
       
  1423 
       
  1424 int QApplication::cursorFlashTime()
       
  1425 {
       
  1426     return QApplicationPrivate::cursor_flash_time;
       
  1427 }
       
  1428 
       
  1429 void QApplication::setCursorFlashTime(int msecs)
       
  1430 {
       
  1431     QApplicationPrivate::cursor_flash_time = msecs;
       
  1432 }
       
  1433 
       
  1434 void QApplication::beep()
       
  1435 {
       
  1436     TInt frequency=440;
       
  1437     TTimeIntervalMicroSeconds duration(500000);
       
  1438     QS60Beep* beep=NULL;
       
  1439     TRAPD(err, beep=QS60Beep::NewL(frequency, duration));
       
  1440     if (!err)
       
  1441         beep->Play();
       
  1442     delete beep;
       
  1443     beep=NULL;
       
  1444 }
       
  1445 
       
  1446 /*!
       
  1447     \warning This function is only available on Symbian.
       
  1448     \since 4.6
       
  1449 
       
  1450     This function processes an individual Symbian event
       
  1451     \a event. It returns 1 if the event was handled, 0 if
       
  1452     the \a event was not handled, and -1 if the event was
       
  1453     not handled because the event is not known to Qt.
       
  1454  */
       
  1455 
       
  1456 int QApplication::symbianProcessEvent(const QSymbianEvent *event)
       
  1457 {
       
  1458     Q_D(QApplication);
       
  1459 
       
  1460     QScopedLoopLevelCounter counter(d->threadData);
       
  1461 
       
  1462     QWidget *w = qApp ? qApp->focusWidget() : 0;
       
  1463     if (w) {
       
  1464         QInputContext *ic = w->inputContext();
       
  1465         if (ic && ic->symbianFilterEvent(w, event))
       
  1466             return 1;
       
  1467     }
       
  1468 
       
  1469     if (symbianEventFilter(event))
       
  1470         return 1;
       
  1471 
       
  1472     switch (event->type()) {
       
  1473     case QSymbianEvent::WindowServerEvent:
       
  1474         return d->symbianProcessWsEvent(event->windowServerEvent());
       
  1475     case QSymbianEvent::CommandEvent:
       
  1476         return d->symbianHandleCommand(event->command());
       
  1477     case QSymbianEvent::ResourceChangeEvent:
       
  1478         return d->symbianResourceChange(event->resourceChangeType());
       
  1479     default:
       
  1480         return -1;
       
  1481     }
       
  1482 }
       
  1483 
       
  1484 int QApplicationPrivate::symbianProcessWsEvent(const TWsEvent *event)
       
  1485 {
       
  1486     // Qt event handling. Handle some events regardless of if the handle is in our
       
  1487     // widget map or not.
       
  1488     CCoeControl* control = reinterpret_cast<CCoeControl*>(event->Handle());
       
  1489     const bool controlInMap = QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control);
       
  1490     switch (event->Type()) {
       
  1491     case EEventPointerEnter:
       
  1492         if (controlInMap)
       
  1493             return 1; // Qt::Enter will be generated in HandlePointerL
       
  1494         break;
       
  1495     case EEventPointerExit:
       
  1496         if (controlInMap) {
       
  1497             if (S60) {
       
  1498                 // mouseEvent outside our window, send leave event to last focused widget
       
  1499                 QMouseEvent mEvent(QEvent::Leave, S60->lastPointerEventPos, S60->lastCursorPos,
       
  1500                     Qt::NoButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
       
  1501                 if (S60->lastPointerEventTarget)
       
  1502                     qt_sendSpontaneousEvent(S60->lastPointerEventTarget,&mEvent);
       
  1503                 S60->lastPointerEventTarget = 0;
       
  1504             }
       
  1505             return 1;
       
  1506         }
       
  1507         break;
       
  1508     case EEventScreenDeviceChanged:
       
  1509         if (S60)
       
  1510             S60->updateScreenSize();
       
  1511         if (qt_desktopWidget) {
       
  1512             QSize oldSize = qt_desktopWidget->size();
       
  1513             qt_desktopWidget->data->crect.setWidth(S60->screenWidthInPixels);
       
  1514             qt_desktopWidget->data->crect.setHeight(S60->screenHeightInPixels);
       
  1515             QResizeEvent e(qt_desktopWidget->size(), oldSize);
       
  1516             QApplication::sendEvent(qt_desktopWidget, &e);
       
  1517         }
       
  1518         return 0; // Propagate to CONE
       
  1519     case EEventWindowVisibilityChanged:
       
  1520         if (controlInMap) {
       
  1521             const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged();
       
  1522             QWidget *w = QWidgetPrivate::mapper->value(control);
       
  1523             if (!w->d_func()->maybeTopData())
       
  1524                 break;
       
  1525             if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) {
       
  1526                 delete w->d_func()->topData()->backingStore;
       
  1527                 w->d_func()->topData()->backingStore = 0;
       
  1528                 // :QTP:QT-2506:remove this when QT-2506 is fixed
       
  1529                 if (S60)
       
  1530                     S60->wsSession().Flush();
       
  1531             } else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
       
  1532                        && !w->d_func()->maybeBackingStore()) {
       
  1533                 w->d_func()->topData()->backingStore = new QWidgetBackingStore(w);
       
  1534                 w->d_func()->invalidateBuffer(w->rect());
       
  1535                 w->repaint();
       
  1536             }
       
  1537             return 1;
       
  1538         }
       
  1539         break;
       
  1540     case EEventFocusGained:
       
  1541 #ifndef QT_NO_CURSOR
       
  1542         //re-enable mouse interaction
       
  1543         if (S60->mouseInteractionEnabled) {
       
  1544 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
       
  1545             if (S60->brokenPointerCursors)
       
  1546                 qt_symbian_show_pointer_sprite();
       
  1547             else
       
  1548 #endif
       
  1549                 S60->wsSession().SetPointerCursorMode(EPointerCursorNormal);
       
  1550         }
       
  1551 #endif
       
  1552         break;
       
  1553     case EEventFocusLost:
       
  1554 #ifndef QT_NO_CURSOR
       
  1555         //disable mouse as may be moving to application that does not support it
       
  1556         if (S60->mouseInteractionEnabled) {
       
  1557 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
       
  1558             if (S60->brokenPointerCursors)
       
  1559                 qt_symbian_hide_pointer_sprite();
       
  1560             else
       
  1561 #endif
       
  1562                 S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
       
  1563         }
       
  1564 #endif
       
  1565         break;
       
  1566 	default:
       
  1567         break;
       
  1568     }
       
  1569 
       
  1570     if (!controlInMap)
       
  1571         return -1;
       
  1572 
       
  1573     return 0;
       
  1574 }
       
  1575 
       
  1576 /*!
       
  1577   \warning This virtual function is only available on Symbian.
       
  1578   \since 4.6
       
  1579 
       
  1580   If you create an application that inherits QApplication and reimplement
       
  1581   this function, you get direct access to events that the are received
       
  1582   from Symbian. The events are passed in the \a event parameter.
       
  1583 
       
  1584   Return true if you want to stop the event from being processed. Return
       
  1585   false for normal event dispatching. The default implementation returns
       
  1586   false, and does nothing with \a event.
       
  1587  */
       
  1588 bool QApplication::symbianEventFilter(const QSymbianEvent *event)
       
  1589 {
       
  1590     Q_UNUSED(event);
       
  1591     return false;
       
  1592 }
       
  1593 
       
  1594 /*!
       
  1595   \warning This function is only available on Symbian.
       
  1596   \since 4.6
       
  1597 
       
  1598   Handles \a{command}s which are typically handled by
       
  1599   CAknAppUi::HandleCommandL(). Qts Ui integration into Symbian is
       
  1600   partially achieved by deriving from CAknAppUi. Currently, exit,
       
  1601   menu and softkey commands are handled.
       
  1602 
       
  1603   \sa s60EventFilter(), s60ProcessEvent()
       
  1604 */
       
  1605 int QApplicationPrivate::symbianHandleCommand(int command)
       
  1606 {
       
  1607     Q_Q(QApplication);
       
  1608     int ret = 0;
       
  1609 
       
  1610     switch (command) {
       
  1611 #ifdef Q_WS_S60
       
  1612     case EAknSoftkeyExit: {
       
  1613         QCloseEvent ev;
       
  1614         QApplication::sendSpontaneousEvent(q, &ev);
       
  1615         if (ev.isAccepted()) {
       
  1616             q->quit();
       
  1617             ret = 1;
       
  1618         }
       
  1619         break;
       
  1620     }
       
  1621 #endif
       
  1622     case EEikCmdExit:
       
  1623         q->quit();
       
  1624         ret = 1;
       
  1625         break;
       
  1626     default:
       
  1627         bool handled = QSoftKeyManager::handleCommand(command);
       
  1628         if (handled)
       
  1629             ret = 1;
       
  1630 #ifdef Q_WS_S60
       
  1631         else
       
  1632             ret = QMenuBarPrivate::symbianCommands(command);
       
  1633 #endif
       
  1634         break;
       
  1635     }
       
  1636 
       
  1637     return ret;
       
  1638 }
       
  1639 
       
  1640 /*!
       
  1641   \warning This function is only available on Symbian.
       
  1642   \since 4.6
       
  1643 
       
  1644   Handles the resource change specified by \a type.
       
  1645 
       
  1646   Currently, KEikDynamicLayoutVariantSwitch and
       
  1647   KAknsMessageSkinChange are handled.
       
  1648  */
       
  1649 int QApplicationPrivate::symbianResourceChange(int type)
       
  1650 {
       
  1651     int ret = 0;
       
  1652 
       
  1653     switch (type) {
       
  1654 #ifdef Q_WS_S60
       
  1655     case KEikDynamicLayoutVariantSwitch:
       
  1656         {
       
  1657         if (S60)
       
  1658             S60->updateScreenSize();
       
  1659 
       
  1660 #ifndef QT_NO_STYLE_S60
       
  1661         QS60Style *s60Style = 0;
       
  1662 
       
  1663 #ifndef QT_NO_STYLE_STYLESHEET
       
  1664         QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplication::style());
       
  1665         if (proxy)
       
  1666             s60Style = qobject_cast<QS60Style*>(proxy->baseStyle());
       
  1667         else
       
  1668 #endif
       
  1669             s60Style = qobject_cast<QS60Style*>(QApplication::style());
       
  1670 
       
  1671         if (s60Style) {
       
  1672             s60Style->d_func()->handleDynamicLayoutVariantSwitch();
       
  1673             ret = 1;
       
  1674         }
       
  1675 #endif
       
  1676         }
       
  1677         break;
       
  1678 
       
  1679 #ifndef QT_NO_STYLE_S60
       
  1680     case KAknsMessageSkinChange:
       
  1681         if (QS60Style *s60Style = qobject_cast<QS60Style*>(QApplication::style())) {
       
  1682             s60Style->d_func()->handleSkinChange();
       
  1683             ret = 1;
       
  1684         }
       
  1685         break;
       
  1686 #endif
       
  1687 #endif // Q_WS_S60
       
  1688     default:
       
  1689         break;
       
  1690     }
       
  1691 
       
  1692     return ret;
       
  1693 }
       
  1694 
       
  1695 #ifndef QT_NO_WHEELEVENT
       
  1696 int QApplication::wheelScrollLines()
       
  1697 {
       
  1698     return QApplicationPrivate::wheel_scroll_lines;
       
  1699 }
       
  1700 
       
  1701 void QApplication::setWheelScrollLines(int n)
       
  1702 {
       
  1703     QApplicationPrivate::wheel_scroll_lines = n;
       
  1704 }
       
  1705 #endif //QT_NO_WHEELEVENT
       
  1706 
       
  1707 bool QApplication::isEffectEnabled(Qt::UIEffect /* effect */)
       
  1708 {
       
  1709     // TODO: Implement QApplication::isEffectEnabled(Qt::UIEffect effect)
       
  1710     return false;
       
  1711 }
       
  1712 
       
  1713 void QApplication::setEffectEnabled(Qt::UIEffect /* effect */, bool /* enable */)
       
  1714 {
       
  1715     // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
       
  1716 }
       
  1717 
       
  1718 TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym)
       
  1719 {
       
  1720     if (keysym) {
       
  1721         // If keysym is specified, cache it.
       
  1722         scanCodeCache.insert(scanCode, keysym);
       
  1723         return keysym;
       
  1724     } else {
       
  1725         // If not, retrieve the cached version.
       
  1726         return scanCodeCache[scanCode];
       
  1727     }
       
  1728 }
       
  1729 
       
  1730 void QApplicationPrivate::initializeMultitouch_sys()
       
  1731 {
       
  1732 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
       
  1733     if (HAL::Get(HALData::EPointer3DMaxPressure, maxTouchPressure) != KErrNone)
       
  1734         maxTouchPressure = KMaxTInt;
       
  1735 #endif
       
  1736 }
       
  1737 
       
  1738 void QApplicationPrivate::cleanupMultitouch_sys()
       
  1739 { }
       
  1740 
       
  1741 #ifndef QT_NO_SESSIONMANAGER
       
  1742 QSessionManager::QSessionManager(QApplication * /* app */, QString & /* id */, QString& /* key */)
       
  1743 {
       
  1744 
       
  1745 }
       
  1746 
       
  1747 QSessionManager::~QSessionManager()
       
  1748 {
       
  1749 
       
  1750 }
       
  1751 
       
  1752 bool QSessionManager::allowsInteraction()
       
  1753 {
       
  1754     return false;
       
  1755 }
       
  1756 
       
  1757 void QSessionManager::cancel()
       
  1758 {
       
  1759 
       
  1760 }
       
  1761 #endif //QT_NO_SESSIONMANAGER
       
  1762 
       
  1763 #ifdef QT_KEYPAD_NAVIGATION
       
  1764 /*
       
  1765  * Show/Hide the mouse cursor depending on phone type and chosen mode
       
  1766  */
       
  1767 void QApplicationPrivate::setNavigationMode(Qt::NavigationMode mode)
       
  1768 {
       
  1769 #ifndef QT_NO_CURSOR
       
  1770     const bool wasCursorOn = (QApplicationPrivate::navigationMode == Qt::NavigationModeCursorAuto
       
  1771         && !S60->hasTouchscreen)
       
  1772         || QApplicationPrivate::navigationMode == Qt::NavigationModeCursorForceVisible;
       
  1773     const bool isCursorOn = (mode == Qt::NavigationModeCursorAuto
       
  1774         && !S60->hasTouchscreen)
       
  1775         || mode == Qt::NavigationModeCursorForceVisible;
       
  1776 
       
  1777     if (!wasCursorOn && isCursorOn) {
       
  1778         //Show the cursor, when changing from another mode to cursor mode
       
  1779         qt_symbian_set_cursor_visible(true);
       
  1780     }
       
  1781     else if (wasCursorOn && !isCursorOn) {
       
  1782         //Hide the cursor, when leaving cursor mode
       
  1783         qt_symbian_set_cursor_visible(false);
       
  1784     }
       
  1785 #endif
       
  1786     QApplicationPrivate::navigationMode = mode;
       
  1787 }
       
  1788 #endif
       
  1789 
       
  1790 #ifndef QT_NO_CURSOR
       
  1791 /*****************************************************************************
       
  1792  QApplication cursor stack
       
  1793  *****************************************************************************/
       
  1794 
       
  1795 void QApplication::setOverrideCursor(const QCursor &cursor)
       
  1796 {
       
  1797     qApp->d_func()->cursor_list.prepend(cursor);
       
  1798     qt_symbian_setGlobalCursor(cursor);
       
  1799 }
       
  1800 
       
  1801 void QApplication::restoreOverrideCursor()
       
  1802 {
       
  1803     if (qApp->d_func()->cursor_list.isEmpty())
       
  1804         return;
       
  1805     qApp->d_func()->cursor_list.removeFirst();
       
  1806 
       
  1807     if (!qApp->d_func()->cursor_list.isEmpty()) {
       
  1808         qt_symbian_setGlobalCursor(qApp->d_func()->cursor_list.first());
       
  1809     }
       
  1810     else {
       
  1811         //determine which widget has focus
       
  1812         QWidget *w = QApplication::widgetAt(QCursor::pos());
       
  1813 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
       
  1814         if (S60->brokenPointerCursors) {
       
  1815             qt_symbian_set_pointer_sprite(w ? w->cursor() : Qt::ArrowCursor);
       
  1816         }
       
  1817         else
       
  1818 #endif
       
  1819         {
       
  1820             //because of the internals of window server, we need to force the cursor
       
  1821             //to be set in all child windows too, otherwise when the cursor is over
       
  1822             //the child window it may show a widget cursor or arrow cursor instead,
       
  1823             //depending on construction order.
       
  1824             QListIterator<WId> iter(QWidgetPrivate::mapper->uniqueKeys());
       
  1825             while (iter.hasNext()) {
       
  1826                 CCoeControl *ctrl = iter.next();
       
  1827                 if(ctrl->OwnsWindow()) {
       
  1828                     ctrl->DrawableWindow()->ClearPointerCursor();
       
  1829                 }
       
  1830             }
       
  1831             if (w)
       
  1832                 qt_symbian_setWindowCursor(w->cursor(), w->effectiveWinId());
       
  1833             else
       
  1834                 qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup());
       
  1835         }
       
  1836     }
       
  1837 }
       
  1838 
       
  1839 #endif // QT_NO_CURSOR
       
  1840 
       
  1841 QT_END_NAMESPACE