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