src/gui/kernel/qapplication_s60.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtGui of the Qt Toolkit.
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     8 **
     8 **
     9 ** $QT_BEGIN_LICENSE:LGPL$
     9 ** $QT_BEGIN_LICENSE:LGPL$
    10 ** No Commercial Usage
    10 ** No Commercial Usage
    11 ** This file contains pre-release code and may not be distributed.
    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
    12 ** You may use this file in accordance with the terms and conditions
    61 #include "qpaintengine.h"
    61 #include "qpaintengine.h"
    62 #include "private/qmenubar_p.h"
    62 #include "private/qmenubar_p.h"
    63 #include "private/qsoftkeymanager_p.h"
    63 #include "private/qsoftkeymanager_p.h"
    64 
    64 
    65 #include "apgwgnam.h" // For CApaWindowGroupName
    65 #include "apgwgnam.h" // For CApaWindowGroupName
    66 #include <MdaAudioTonePlayer.h>     // For CMdaAudioToneUtility
    66 #include <mdaaudiotoneplayer.h>     // For CMdaAudioToneUtility
    67 
    67 
    68 #if defined(Q_WS_S60)
    68 #if defined(Q_WS_S60)
    69 # if !defined(QT_NO_IM)
    69 # if !defined(QT_NO_IM)
    70 #  include "qinputcontext.h"
    70 #  include "qinputcontext.h"
    71 #  include <private/qcoefepinputcontext_p.h>
    71 #  include <private/qcoefepinputcontext_p.h>
   131     TBeepState iState;
   131     TBeepState iState;
   132     TInt iFrequency;
   132     TInt iFrequency;
   133     TTimeIntervalMicroSeconds iDuration;
   133     TTimeIntervalMicroSeconds iDuration;
   134 };
   134 };
   135 
   135 
       
   136 static QS60Beep* qt_S60Beep = 0;
       
   137 
   136 QS60Beep::~QS60Beep()
   138 QS60Beep::~QS60Beep()
   137 {
   139 {
       
   140     if (iToneUtil) {
       
   141         switch (iState) {
       
   142         case EBeepPlaying:
       
   143             iToneUtil->CancelPlay();
       
   144             break;
       
   145         case EBeepNotPrepared:
       
   146             iToneUtil->CancelPrepare();
       
   147             break;
       
   148         }
       
   149     }
   138     delete iToneUtil;
   150     delete iToneUtil;
   139 }
   151 }
   140 
   152 
   141 QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
   153 QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
   142 {
   154 {
   143     QS60Beep* self=new (ELeave) QS60Beep();
   155     QS60Beep* self = new (ELeave) QS60Beep();
   144     CleanupStack::PushL(self);
   156     CleanupStack::PushL(self);
   145     self->ConstructL(aFrequency, aDuration);
   157     self->ConstructL(aFrequency, aDuration);
   146     CleanupStack::Pop();
   158     CleanupStack::Pop();
   147     return self;
   159     return self;
   148 };
   160 }
   149 
   161 
   150 void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
   162 void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
   151 {
   163 {
   152     iToneUtil=CMdaAudioToneUtility::NewL(*this);
   164     iToneUtil = CMdaAudioToneUtility::NewL(*this);
   153     iState=EBeepNotPrepared;
   165     iState = EBeepNotPrepared;
   154     iFrequency=aFrequency;
   166     iFrequency = aFrequency;
   155     iDuration=aDuration;
   167     iDuration = aDuration;
   156     iToneUtil->PrepareToPlayTone(iFrequency,iDuration);
   168     iToneUtil->PrepareToPlayTone(iFrequency, iDuration);
   157 }
   169 }
   158 
   170 
   159 void QS60Beep::Play()
   171 void QS60Beep::Play()
   160 {
   172 {
   161     if (iState != EBeepNotPrepared) {
   173     if (iState == EBeepPlaying) {
   162         if (iState == EBeepPlaying) {
   174         iToneUtil->CancelPlay();
   163             iToneUtil->CancelPlay();
   175         iState = EBeepPrepared;
   164             iState = EBeepPrepared;
       
   165         }
       
   166     }
   176     }
   167 
   177 
   168     iToneUtil->Play();
   178     iToneUtil->Play();
   169     iState = EBeepPlaying;
   179     iState = EBeepPlaying;
   170 }
   180 }
   171 
   181 
   172 void QS60Beep::MatoPrepareComplete(TInt aError)
   182 void QS60Beep::MatoPrepareComplete(TInt aError)
   173 {
   183 {
   174     if (aError == KErrNone) {
   184     if (aError == KErrNone) {
   175         iState = EBeepPrepared;
   185         iState = EBeepPrepared;
       
   186         Play();
   176     }
   187     }
   177 }
   188 }
   178 
   189 
   179 void QS60Beep::MatoPlayComplete(TInt aError)
   190 void QS60Beep::MatoPlayComplete(TInt aError)
   180 {
   191 {
   181     Q_UNUSED(aError);
   192     Q_UNUSED(aError);
   182     iState=EBeepPrepared;
   193     iState = EBeepPrepared;
   183 }
   194 }
   184 
   195 
   185 
   196 
   186 QHash<TInt, TUint> QApplicationPrivate::scanCodeCache;
   197 QHash<TInt, TUint> QApplicationPrivate::scanCodeCache;
   187 
   198 
   317     if (m_observer)
   328     if (m_observer)
   318         m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition);
   329         m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition);
   319 }
   330 }
   320 
   331 
   321 QSymbianControl::QSymbianControl(QWidget *w)
   332 QSymbianControl::QSymbianControl(QWidget *w)
   322     : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false)
   333     : CCoeControl()
       
   334     , qwidget(w)
       
   335     , m_longTapDetector(0)
       
   336     , m_ignoreFocusChanged(0)
       
   337     , m_symbianPopupIsOpen(0)
   323 {
   338 {
   324 }
   339 }
   325 
   340 
   326 void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop)
   341 void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop)
   327 {
   342 {
   344         // the control's window
   359         // the control's window
   345         qwidget->d_func()->createExtra();
   360         qwidget->d_func()->createExtra();
   346 
   361 
   347         SetFocusing(true);
   362         SetFocusing(true);
   348         m_longTapDetector = QLongTapTimer::NewL(this);
   363         m_longTapDetector = QLongTapTimer::NewL(this);
       
   364 
       
   365         DrawableWindow()->SetPointerGrab(ETrue);
   349     }
   366     }
   350 }
   367 }
   351 
   368 
   352 QSymbianControl::~QSymbianControl()
   369 QSymbianControl::~QSymbianControl()
   353 {
   370 {
   369     QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY);
   386     QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY);
   370     QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY);
   387     QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY);
   371     alienWidget = qwidget->childAt(widgetPos);
   388     alienWidget = qwidget->childAt(widgetPos);
   372     if (!alienWidget)
   389     if (!alienWidget)
   373         alienWidget = qwidget;
   390         alienWidget = qwidget;
   374     QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~Qt::LeftButton);
       
   375     QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton;
       
   376     QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos,
       
   377         Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
       
   378 
       
   379     bool res = sendMouseEvent(alienWidget, &mEvent);
       
   380 
   391 
   381 #if !defined(QT_NO_CONTEXTMENU)
   392 #if !defined(QT_NO_CONTEXTMENU)
   382     QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, mEvent.modifiers());
   393     QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, Qt::NoModifier);
   383     qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent);
   394     qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent);
   384 #endif
   395 #endif
   385 
       
   386     m_previousEventLongTap = true;
       
   387 }
   396 }
   388 
   397 
   389 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
   398 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
   390 void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event)
   399 void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event)
   391 {
   400 {
   463 
   472 
   464     m_longTapDetector->PointerEventL(pEvent);
   473     m_longTapDetector->PointerEventL(pEvent);
   465     QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent));
   474     QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent));
   466 }
   475 }
   467 
   476 
   468 typedef QPair<QWidget*,QMouseEvent> Event;
       
   469 
       
   470 /*
       
   471  * Helper function called by HandlePointerEvent - separated to keep that function readable
       
   472  */
       
   473 static void generateEnterLeaveEvents(QList<Event> &events, QWidget *widgetUnderPointer,
       
   474     QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
       
   475 {
       
   476     //moved to another widget, create enter and leave events
       
   477     if (S60->lastPointerEventTarget) {
       
   478         QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(
       
   479             S60->lastCursorPos), S60->lastCursorPos, button, QApplicationPrivate::mouse_buttons,
       
   480             modifiers);
       
   481         events.append(Event(S60->lastPointerEventTarget, mEventLeave));
       
   482     }
       
   483     if (widgetUnderPointer) {
       
   484         QMouseEvent mEventEnter(QEvent::Enter, widgetUnderPointer->mapFromGlobal(globalPos),
       
   485             globalPos, button, QApplicationPrivate::mouse_buttons, modifiers);
       
   486 
       
   487         events.append(Event(widgetUnderPointer, mEventEnter));
       
   488 #ifndef QT_NO_CURSOR
       
   489         S60->curWin = widgetUnderPointer->effectiveWinId();
       
   490         if (!QApplication::overrideCursor()) {
       
   491 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
       
   492             if (S60->brokenPointerCursors)
       
   493                 qt_symbian_set_pointer_sprite(widgetUnderPointer->cursor());
       
   494             else
       
   495 #endif
       
   496                 qt_symbian_setWindowCursor(widgetUnderPointer->cursor(), S60->curWin);
       
   497         }
       
   498 #endif
       
   499     }
       
   500 }
       
   501 
       
   502 
       
   503 void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
   477 void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
   504 {
   478 {
   505     QMouseEvent::Type type;
   479     QMouseEvent::Type type;
   506     Qt::MouseButton button;
   480     Qt::MouseButton button;
   507     mapS60MouseEventTypeToQt(&type, &button, &pEvent);
   481     mapS60MouseEventTypeToQt(&type, &button, &pEvent);
   508     Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers);
   482     Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers);
   509 
   483 
   510     if (m_previousEventLongTap)
       
   511         if (type == QEvent::MouseButtonRelease){
       
   512             button = Qt::RightButton;
       
   513             QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton;
       
   514             m_previousEventLongTap = false;
       
   515         }
       
   516     if (type == QMouseEvent::None)
       
   517         return;
       
   518 
       
   519     // store events for later sending/saving
       
   520     QList<Event > events;
       
   521 
       
   522     QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
   484     QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
   523     TPoint controlScreenPos = PositionRelativeToScreen();
   485     TPoint controlScreenPos = PositionRelativeToScreen();
   524     QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
   486     QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
   525 
   487     S60->lastCursorPos = globalPos;
   526     // widgets interested in the event
   488     S60->lastPointerEventPos = widgetPos;
       
   489 
       
   490     QWidget *mouseGrabber = QWidget::mouseGrabber();
       
   491 
       
   492     QWidget *popupWidget = qApp->activePopupWidget();
       
   493     QWidget *popupReceiver = 0;
       
   494     if (popupWidget) {
       
   495         QWidget *popupChild = popupWidget->childAt(popupWidget->mapFromGlobal(globalPos));
       
   496         popupReceiver = popupChild ? popupChild : popupWidget;
       
   497     }
       
   498 
       
   499     if (mouseGrabber) {
       
   500         if (popupReceiver) {
       
   501             sendMouseEvent(popupReceiver, type, globalPos, button, modifiers);
       
   502         } else {
       
   503             sendMouseEvent(mouseGrabber, type, globalPos, button, modifiers);
       
   504         }
       
   505         // No Enter/Leave events in grabbing mode.
       
   506         return;
       
   507     }
       
   508 
   527     QWidget *widgetUnderPointer = qwidget->childAt(widgetPos);
   509     QWidget *widgetUnderPointer = qwidget->childAt(widgetPos);
   528     if (!widgetUnderPointer)
   510     if (!widgetUnderPointer)
   529         widgetUnderPointer = qwidget; //i.e. this container widget
   511         widgetUnderPointer = qwidget;
   530 
   512 
   531     QWidget *widgetWithMouseGrab = QWidget::mouseGrabber();
   513     QApplicationPrivate::dispatchEnterLeave(widgetUnderPointer, S60->lastPointerEventTarget);
   532 
       
   533     // handle auto grab of pointer when pressing / releasing
       
   534     if (!widgetWithMouseGrab && type == QEvent::MouseButtonPress) {
       
   535         //if previously auto-grabbed, generate a fake mouse release (platform bug: mouse release event was lost)
       
   536         if (S60->mousePressTarget) {
       
   537             QMouseEvent mEvent(QEvent::MouseButtonRelease, S60->mousePressTarget->mapFromGlobal(globalPos), globalPos,
       
   538                 button, QApplicationPrivate::mouse_buttons, modifiers);
       
   539             events.append(Event(S60->mousePressTarget,mEvent));
       
   540         }
       
   541         //auto grab the mouse
       
   542         widgetWithMouseGrab = S60->mousePressTarget = widgetUnderPointer;
       
   543         widgetWithMouseGrab->grabMouse();
       
   544     }
       
   545     if (widgetWithMouseGrab && widgetWithMouseGrab == S60->mousePressTarget && type == QEvent::MouseButtonRelease) {
       
   546         //release the auto grab - note this release event still goes to the autograb widget
       
   547         S60->mousePressTarget = 0;
       
   548         widgetWithMouseGrab->releaseMouse();
       
   549     }
       
   550 
       
   551     QWidget *widgetToReceiveMouseEvent;
       
   552     if (widgetWithMouseGrab)
       
   553         widgetToReceiveMouseEvent = widgetWithMouseGrab;
       
   554     else
       
   555         widgetToReceiveMouseEvent = widgetUnderPointer;
       
   556 
       
   557     //queue QEvent::Enter and QEvent::Leave, if the pointer has moved
       
   558     if (widgetUnderPointer != S60->lastPointerEventTarget && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove))
       
   559         generateEnterLeaveEvents(events, widgetUnderPointer, globalPos, button, modifiers);
       
   560 
       
   561     //save global state
       
   562     S60->lastCursorPos = globalPos;
       
   563     S60->lastPointerEventPos = widgetPos;
       
   564     S60->lastPointerEventTarget = widgetUnderPointer;
   514     S60->lastPointerEventTarget = widgetUnderPointer;
       
   515 
       
   516     QWidget *receiver;
       
   517     if (!popupReceiver && S60->mousePressTarget && type != QEvent::MouseButtonPress) {
       
   518         receiver = S60->mousePressTarget;
       
   519         if (type == QEvent::MouseButtonRelease)
       
   520             S60->mousePressTarget = 0;
       
   521     } else {
       
   522         receiver = popupReceiver ? popupReceiver : widgetUnderPointer;
       
   523         if (type == QEvent::MouseButtonPress)
       
   524             S60->mousePressTarget = receiver;
       
   525     }
   565 
   526 
   566 #if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS)
   527 #if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS)
   567     if (S60->brokenPointerCursors)
   528     if (S60->brokenPointerCursors)
   568         qt_symbian_move_cursor_sprite();
   529         qt_symbian_move_cursor_sprite();
   569 #endif
   530 #endif
   570 
   531 
   571     //queue this event.
   532     sendMouseEvent(receiver, type, globalPos, button, modifiers);
   572     Q_ASSERT(widgetToReceiveMouseEvent);
   533 }
   573     QMouseEvent mEvent(type, widgetToReceiveMouseEvent->mapFromGlobal(globalPos), globalPos,
   534 
       
   535 void QSymbianControl::sendMouseEvent(
       
   536         QWidget *receiver,
       
   537         QEvent::Type type,
       
   538         const QPoint &globalPos,
       
   539         Qt::MouseButton button,
       
   540         Qt::KeyboardModifiers modifiers)
       
   541 {
       
   542     Q_ASSERT(receiver);
       
   543     QMouseEvent mEvent(type, receiver->mapFromGlobal(globalPos), globalPos,
   574         button, QApplicationPrivate::mouse_buttons, modifiers);
   544         button, QApplicationPrivate::mouse_buttons, modifiers);
   575     events.append(Event(widgetToReceiveMouseEvent,mEvent));
       
   576     QEventDispatcherS60 *dispatcher;
   545     QEventDispatcherS60 *dispatcher;
   577     // It is theoretically possible for someone to install a different event dispatcher.
   546     // It is theoretically possible for someone to install a different event dispatcher.
   578     if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widgetToReceiveMouseEvent->d_func()->threadData->eventDispatcher)) != 0) {
   547     if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(receiver->d_func()->threadData->eventDispatcher)) != 0) {
   579         if (dispatcher->excludeUserInputEvents()) {
   548         if (dispatcher->excludeUserInputEvents()) {
   580             for (int i=0;i < events.count();++i)
   549             dispatcher->saveInputEvent(this, receiver, new QMouseEvent(mEvent));
   581             {
       
   582                 Event next = events[i];
       
   583                 dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second));
       
   584             }
       
   585             return;
   550             return;
   586         }
   551         }
   587     }
   552     }
   588 
   553 
   589     //send events in the queue
   554     sendMouseEvent(receiver, &mEvent);
   590     for (int i=0;i < events.count();++i)
       
   591     {
       
   592         Event next = events[i];
       
   593         sendMouseEvent(next.first, &(next.second));
       
   594     }
       
   595 }
   555 }
   596 
   556 
   597 bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent)
   557 bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent)
   598 {
   558 {
   599     return qt_sendSpontaneousEvent(widget, mEvent);
   559     return qt_sendSpontaneousEvent(widget, mEvent);
   669                 if (type == EEventKeyUp) {
   629                 if (type == EEventKeyUp) {
   670                     if (keyCode == Qt::Key_Select)
   630                     if (keyCode == Qt::Key_Select)
   671                         fakeEvent.iType = TPointerEvent::EButton1Up;
   631                         fakeEvent.iType = TPointerEvent::EButton1Up;
   672                     S60->virtualMouseAccel = 1;
   632                     S60->virtualMouseAccel = 1;
   673                     S60->virtualMouseLastKey = 0;
   633                     S60->virtualMouseLastKey = 0;
       
   634                     switch (keyCode) {
       
   635                     case Qt::Key_Left:
       
   636                         S60->virtualMousePressedKeys &= ~QS60Data::Left;
       
   637                         break;
       
   638                     case Qt::Key_Right:
       
   639                         S60->virtualMousePressedKeys &= ~QS60Data::Right;
       
   640                         break;
       
   641                     case Qt::Key_Up:
       
   642                         S60->virtualMousePressedKeys &= ~QS60Data::Up;
       
   643                         break;
       
   644                     case Qt::Key_Down:
       
   645                         S60->virtualMousePressedKeys &= ~QS60Data::Down;
       
   646                         break;
       
   647                     case Qt::Key_Select:
       
   648                         S60->virtualMousePressedKeys &= ~QS60Data::Select;
       
   649                         break;
       
   650                     }
   674                 }
   651                 }
   675                 else if (type == EEventKey) {
   652                 else if (type == EEventKey) {
   676                     switch (keyCode) {
   653                     switch (keyCode) {
   677                     case Qt::Key_Left:
   654                     case Qt::Key_Left:
       
   655                         S60->virtualMousePressedKeys |= QS60Data::Left;
   678                         x -= S60->virtualMouseAccel;
   656                         x -= S60->virtualMouseAccel;
   679                         fakeEvent.iType = TPointerEvent::EMove;
   657                         fakeEvent.iType = TPointerEvent::EMove;
   680                         break;
   658                         break;
   681                     case Qt::Key_Right:
   659                     case Qt::Key_Right:
       
   660                         S60->virtualMousePressedKeys |= QS60Data::Right;
   682                         x += S60->virtualMouseAccel;
   661                         x += S60->virtualMouseAccel;
   683                         fakeEvent.iType = TPointerEvent::EMove;
   662                         fakeEvent.iType = TPointerEvent::EMove;
   684                         break;
   663                         break;
   685                     case Qt::Key_Up:
   664                     case Qt::Key_Up:
       
   665                         S60->virtualMousePressedKeys |= QS60Data::Up;
   686                         y -= S60->virtualMouseAccel;
   666                         y -= S60->virtualMouseAccel;
   687                         fakeEvent.iType = TPointerEvent::EMove;
   667                         fakeEvent.iType = TPointerEvent::EMove;
   688                         break;
   668                         break;
   689                     case Qt::Key_Down:
   669                     case Qt::Key_Down:
       
   670                         S60->virtualMousePressedKeys |= QS60Data::Down;
   690                         y += S60->virtualMouseAccel;
   671                         y += S60->virtualMouseAccel;
   691                         fakeEvent.iType = TPointerEvent::EMove;
   672                         fakeEvent.iType = TPointerEvent::EMove;
   692                         break;
   673                         break;
   693                     case Qt::Key_Select:
   674                     case Qt::Key_Select:
   694                         fakeEvent.iType = TPointerEvent::EButton1Down;
   675                         // Platform bug. If you start pressing several keys simultaneously (for
       
   676                         // example for drag'n'drop), Symbian starts producing spurious up and
       
   677                         // down messages for some keys. Therefore, make sure we have a clean slate
       
   678                         // of pressed keys before starting a new button press.
       
   679                         if (S60->virtualMousePressedKeys != 0) {
       
   680                             S60->virtualMousePressedKeys |= QS60Data::Select;
       
   681                             return EKeyWasConsumed;
       
   682                         } else {
       
   683                             S60->virtualMousePressedKeys |= QS60Data::Select;
       
   684                             fakeEvent.iType = TPointerEvent::EButton1Down;
       
   685                         }
   695                         break;
   686                         break;
   696                     }
   687                     }
   697                 }
   688                 }
   698                 //clip to screen size (window server allows a sprite hotspot to be outside the screen)
   689                 //clip to screen size (window server allows a sprite hotspot to be outside the screen)
   699                 if (x < 0)
   690                 if (x < 0)
   720 #endif
   711 #endif
   721 
   712 
   722         Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
   713         Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
   723         QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
   714         QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
   724                 mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
   715                 mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
   725                 false, 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
   716                 (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
   726 //        WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
   717 //        WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
   727 //        if (!wid)
   718 //        if (!wid)
   728 //             Could happen if window isn't shown yet.
   719 //             Could happen if window isn't shown yet.
   729 //            return EKeyWasNotConsumed;
   720 //            return EKeyWasNotConsumed;
   730         QWidget *widget;
   721         QWidget *widget;
   820     QPaintEngine *engine = surface ? surface->paintDevice()->paintEngine() : NULL;
   811     QPaintEngine *engine = surface ? surface->paintDevice()->paintEngine() : NULL;
   821 
   812 
   822     if (!engine)
   813     if (!engine)
   823         return;
   814         return;
   824 
   815 
       
   816     const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents;
       
   817     if (sendNativePaintEvents) {
       
   818         const QRect r = qt_TRect2QRect(controlRect);
       
   819         QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r));
       
   820     }
       
   821 
   825     // Map source rectangle into coordinates of the backing store.
   822     // Map source rectangle into coordinates of the backing store.
   826     const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY);
   823     const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY);
   827     const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase);
   824     const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase);
   828     const TRect backingStoreRect(TPoint(backingStoreBase.x(), backingStoreBase.y()), controlRect.Size());
   825     const TRect backingStoreRect(TPoint(backingStoreBase.x(), backingStoreBase.y()), controlRect.Size());
   829 
   826 
   830     if (engine->type() == QPaintEngine::Raster) {
   827     if (engine->type() == QPaintEngine::Raster) {
   831         QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
   828         QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
   832         CFbsBitmap *bitmap = s60Surface->symbianBitmap();
   829         CFbsBitmap *bitmap = s60Surface->symbianBitmap();
   833         CWindowGc &gc = SystemGc();
   830         CWindowGc &gc = SystemGc();
   834 
   831 
   835         if(!qwidget->d_func()->extraData()->disableBlit) {
   832         switch(qwidget->d_func()->extraData()->nativePaintMode) {
       
   833         case QWExtra::Disable:
       
   834             // Do nothing
       
   835             break;
       
   836 
       
   837         case QWExtra::Blit:
   836             if (qwidget->d_func()->isOpaque)
   838             if (qwidget->d_func()->isOpaque)
   837                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
   839                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
   838             gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
   840             gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
   839 	    }
   841             break;
       
   842 
       
   843         case QWExtra::ZeroFill:
       
   844             if (Window().DisplayMode() == EColor16MA) {
       
   845                 gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
       
   846                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
       
   847                 gc.SetBrushColor(TRgb::Color16MA(0));
       
   848                 gc.Clear(controlRect);
       
   849             } else {
       
   850                 gc.SetBrushColor(TRgb(0x000000));
       
   851                 gc.Clear(controlRect);
       
   852             };
       
   853             break;
       
   854 
       
   855         default:
       
   856             Q_ASSERT(false);
       
   857         }
   840     } else {
   858     } else {
   841         surface->flush(qwidget, QRegion(qt_TRect2QRect(backingStoreRect)), QPoint());
   859         surface->flush(qwidget, QRegion(qt_TRect2QRect(backingStoreRect)), QPoint());
       
   860     }
       
   861 
       
   862     if (sendNativePaintEvents) {
       
   863         const QRect r = qt_TRect2QRect(controlRect);
       
   864         // The draw ops aren't actually sent to WSERV until the graphics
       
   865         // context is deactivated, which happens in the function calling
       
   866         // this one.  We therefore delay the delivery of endNativePaintEvent,
       
   867         // to ensure that drawing has completed by the time the widget
       
   868         // receives the event.  Note that, if the widget needs to ensure
       
   869         // that the draw ops have actually been executed into the output
       
   870         // framebuffer, a call to RWsSession::Flush is required in the
       
   871         // endNativePaintEvent implementation.
       
   872         QMetaObject::invokeMethod(qwidget, "endNativePaintEvent", Qt::QueuedConnection, Q_ARG(QRect, r));
   842     }
   873     }
   843 }
   874 }
   844 
   875 
   845 void QSymbianControl::SizeChanged()
   876 void QSymbianControl::SizeChanged()
   846 {
   877 {
   864                 qwidget->d_func()->syncBackingStore();
   895                 qwidget->d_func()->syncBackingStore();
   865             if (!slowResize && tlwExtra)
   896             if (!slowResize && tlwExtra)
   866                 tlwExtra->inTopLevelResize = false;
   897                 tlwExtra->inTopLevelResize = false;
   867         }
   898         }
   868     }
   899     }
       
   900 
       
   901     // CCoeControl::SetExtent calls SizeChanged, but does not call
       
   902     // PositionChanged, so we call it here to ensure that the widget's
       
   903     // position is updated.
       
   904     PositionChanged();
   869 }
   905 }
   870 
   906 
   871 void QSymbianControl::PositionChanged()
   907 void QSymbianControl::PositionChanged()
   872 {
   908 {
   873     CCoeControl::PositionChanged();
   909     CCoeControl::PositionChanged();
   901     if (QApplicationPrivate::popupWidgets != 0
   937     if (QApplicationPrivate::popupWidgets != 0
   902             || (qwidget->windowType() & Qt::Popup) == Qt::Popup)
   938             || (qwidget->windowType() & Qt::Popup) == Qt::Popup)
   903         return;
   939         return;
   904 
   940 
   905     if (IsFocused() && IsVisible()) {
   941     if (IsFocused() && IsVisible()) {
       
   942         if (m_symbianPopupIsOpen) {
       
   943             QWidget *fw = QApplication::focusWidget();
       
   944             if (fw) {
       
   945                 QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason);
       
   946                 QCoreApplication::sendEvent(fw, &event);
       
   947             }
       
   948             m_symbianPopupIsOpen = false;
       
   949         }
       
   950 
   906         QApplication::setActiveWindow(qwidget->window());
   951         QApplication::setActiveWindow(qwidget->window());
       
   952         qwidget->d_func()->setWindowIcon_sys(true);
       
   953         qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
   907 #ifdef Q_WS_S60
   954 #ifdef Q_WS_S60
   908         // If widget is fullscreen, hide status pane and button container
   955         // If widget is fullscreen, hide status pane and button container
   909         // otherwise show them.
   956         // otherwise show them.
   910         CEikStatusPane* statusPane = S60->statusPane();
   957         CEikStatusPane* statusPane = S60->statusPane();
   911         CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
   958         CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
   912         bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
   959         bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
   913         if (statusPane && (statusPane->IsVisible() == isFullscreen))
   960         if (statusPane && (bool)statusPane->IsVisible() == isFullscreen)
   914             statusPane->MakeVisible(!isFullscreen);
   961             statusPane->MakeVisible(!isFullscreen);
   915         if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen))
   962         if (buttonGroup && (bool)buttonGroup->IsVisible() == isFullscreen)
   916             buttonGroup->MakeVisible(!isFullscreen);
   963             buttonGroup->MakeVisible(!isFullscreen);
   917 #endif
   964 #endif
   918     } else if (QApplication::activeWindow() == qwidget->window()) {
   965     } else if (QApplication::activeWindow() == qwidget->window()) {
       
   966         if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) {
       
   967             QWidget *fw = QApplication::focusWidget();
       
   968             if (fw) {
       
   969                 QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
       
   970                 QCoreApplication::sendEvent(fw, &event);
       
   971             }
       
   972             m_symbianPopupIsOpen = true;
       
   973             return;
       
   974         }
       
   975 
   919         QApplication::setActiveWindow(0);
   976         QApplication::setActiveWindow(0);
   920     }
   977     }
   921     // else { We don't touch the active window unless we were explicitly activated or deactivated }
   978     // else { We don't touch the active window unless we were explicitly activated or deactivated }
   922 }
   979 }
   923 
   980 
   924 void QSymbianControl::HandleResourceChange(int resourceType)
   981 void QSymbianControl::HandleResourceChange(int resourceType)
   925 {
   982 {
   926     switch (resourceType) {
   983     switch (resourceType) {
   927     case KInternalStatusPaneChange:
   984     case KInternalStatusPaneChange:
   928         qwidget->d_func()->setWindowIcon_sys(true);
   985         if (qwidget->isFullScreen()) {
       
   986             SetExtentToWholeScreen();
       
   987         } else if (qwidget->isMaximized()) {
       
   988             TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
       
   989             SetExtent(r.iTl, r.Size());
       
   990         }
       
   991         if (IsFocused() && IsVisible()) {
       
   992             qwidget->d_func()->setWindowIcon_sys(true);
       
   993             qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
       
   994         }
   929         break;
   995         break;
   930     case KUidValueCoeFontChangeEvent:
   996     case KUidValueCoeFontChangeEvent:
   931         // font change event
   997         // font change event
   932         break;
   998         break;
   933 #ifdef Q_WS_S60
   999 #ifdef Q_WS_S60
  1044         CApaCommandLine* commandLine = 0;
  1110         CApaCommandLine* commandLine = 0;
  1045         TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine);
  1111         TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine);
  1046         // After this construction, CEikonEnv will be available from CEikonEnv::Static().
  1112         // After this construction, CEikonEnv will be available from CEikonEnv::Static().
  1047         // (much like our qApp).
  1113         // (much like our qApp).
  1048         CEikonEnv* coe = new CEikonEnv;
  1114         CEikonEnv* coe = new CEikonEnv;
  1049         QT_TRAP_THROWING(coe->ConstructAppFromCommandLineL(factory,*commandLine));
  1115         //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there.
       
  1116         if(err == KErrNone)
       
  1117             TRAP(err, coe->ConstructAppFromCommandLineL(factory,*commandLine));
  1050         delete commandLine;
  1118         delete commandLine;
       
  1119         if(err != KErrNone) {
       
  1120             qWarning() << "qt_init: Eikon application construct failed ("
       
  1121                        << err
       
  1122                        << "), maybe missing resource file on S60 3.1?";
       
  1123             delete coe;
       
  1124             qt_symbian_throwIfError(err);
       
  1125         }
  1051 
  1126 
  1052         S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler);
  1127         S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler);
  1053 
  1128 
  1054         S60->qtOwnsS60Environment = true;
  1129         S60->qtOwnsS60Environment = true;
  1055     } else {
  1130     } else {
  1078     TSecureId securId = me.SecureId();
  1153     TSecureId securId = me.SecureId();
  1079     S60->uid = securId.operator TUid();
  1154     S60->uid = securId.operator TUid();
  1080 
  1155 
  1081     // enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app,
  1156     // enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app,
  1082     // and for dimming behind modal windows
  1157     // and for dimming behind modal windows
  1083 	S60->windowGroup().EnableFocusChangeEvents();
  1158     S60->windowGroup().EnableFocusChangeEvents();
  1084 
  1159 
  1085 	//Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this)
  1160     //Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this)
  1086     const TInt KMachineUidSamsungI8510 = 0x2000C51E;
  1161     const TInt KMachineUidSamsungI8510 = 0x2000C51E;
  1087     // HAL::Get(HALData::EPen, TInt& result) may set 'result' to 1 on some 3.1 systems (e.g. N95).
  1162     // HAL::Get(HALData::EPen, TInt& result) may set 'result' to 1 on some 3.1 systems (e.g. N95).
  1088     // But we know that S60 systems below 5.0 did not support touch.
  1163     // But we know that S60 systems below 5.0 did not support touch.
  1089     static const bool touchIsUnsupportedOnSystem =
  1164     static const bool touchIsUnsupportedOnSystem =
  1090         QSysInfo::s60Version() == QSysInfo::SV_S60_3_1
  1165         QSysInfo::s60Version() == QSysInfo::SV_S60_3_1
  1190 /*****************************************************************************
  1265 /*****************************************************************************
  1191   qt_cleanup() - cleans up when the application is finished
  1266   qt_cleanup() - cleans up when the application is finished
  1192  *****************************************************************************/
  1267  *****************************************************************************/
  1193 void qt_cleanup()
  1268 void qt_cleanup()
  1194 {
  1269 {
       
  1270     if(qt_S60Beep) {
       
  1271         delete qt_S60Beep;
       
  1272         qt_S60Beep = 0;
       
  1273     }
  1195     QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
  1274     QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
  1196 // S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
  1275 // S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
  1197 
  1276 
  1198     // It's important that this happens here, before the event dispatcher gets
  1277     // It's important that this happens here, before the event dispatcher gets
  1199     // deleted, because the input context needs the event loop one last time before
  1278     // deleted, because the input context needs the event loop one last time before
  1238 }
  1317 }
  1239 
  1318 
  1240 void QApplicationPrivate::enterModal_sys(QWidget *widget)
  1319 void QApplicationPrivate::enterModal_sys(QWidget *widget)
  1241 {
  1320 {
  1242     if (widget) {
  1321     if (widget) {
  1243         widget->effectiveWinId()->DrawableWindow()->FadeBehind(ETrue);
  1322         static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue);
  1244         // Modal partial screen dialogs (like queries) capture pointer events.
  1323         // Modal partial screen dialogs (like queries) capture pointer events.
  1245         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1324         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1246         widget->effectiveWinId()->SetGloballyCapturing(ETrue);
  1325         widget->effectiveWinId()->SetGloballyCapturing(ETrue);
  1247         widget->effectiveWinId()->SetPointerCapture(ETrue);
  1326         widget->effectiveWinId()->SetPointerCapture(ETrue);
  1248     }
  1327     }
  1253 }
  1332 }
  1254 
  1333 
  1255 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
  1334 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
  1256 {
  1335 {
  1257     if (widget) {
  1336     if (widget) {
  1258         widget->effectiveWinId()->DrawableWindow()->FadeBehind(EFalse);
  1337         static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse);
  1259         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1338         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1260         widget->effectiveWinId()->SetGloballyCapturing(EFalse);
  1339         widget->effectiveWinId()->SetGloballyCapturing(EFalse);
  1261         widget->effectiveWinId()->SetPointerCapture(EFalse);
  1340         widget->effectiveWinId()->SetPointerCapture(EFalse);
  1262     }
  1341     }
  1263     if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
  1342     if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
  1431     QApplicationPrivate::cursor_flash_time = msecs;
  1510     QApplicationPrivate::cursor_flash_time = msecs;
  1432 }
  1511 }
  1433 
  1512 
  1434 void QApplication::beep()
  1513 void QApplication::beep()
  1435 {
  1514 {
  1436     TInt frequency=440;
  1515     if (!qt_S60Beep) {
  1437     TTimeIntervalMicroSeconds duration(500000);
  1516         TInt frequency = 880;
  1438     QS60Beep* beep=NULL;
  1517         TTimeIntervalMicroSeconds duration(500000);
  1439     TRAPD(err, beep=QS60Beep::NewL(frequency, duration));
  1518         TRAP_IGNORE(qt_S60Beep=QS60Beep::NewL(frequency, duration));
  1440     if (!err)
  1519     }
  1441         beep->Play();
  1520     if (qt_S60Beep)
  1442     delete beep;
  1521         qt_S60Beep->Play();
  1443     beep=NULL;
       
  1444 }
  1522 }
  1445 
  1523 
  1446 /*!
  1524 /*!
  1447     \warning This function is only available on Symbian.
  1525     \warning This function is only available on Symbian.
  1448     \since 4.6
  1526     \since 4.6
  1561 #endif
  1639 #endif
  1562                 S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
  1640                 S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
  1563         }
  1641         }
  1564 #endif
  1642 #endif
  1565         break;
  1643         break;
  1566 	default:
  1644     default:
  1567         break;
  1645         break;
  1568     }
  1646     }
  1569 
  1647 
  1570     if (!controlInMap)
  1648     if (!controlInMap)
  1571         return -1;
  1649         return -1;