src/gui/kernel/qapplication_s60.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    85 #include "private/qstylesheetstyle_p.h"
    85 #include "private/qstylesheetstyle_p.h"
    86 
    86 
    87 #include <hal.h>
    87 #include <hal.h>
    88 #include <hal_data.h>
    88 #include <hal_data.h>
    89 
    89 
       
    90 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
    91 #include <graphics/wstfxconst.h>
       
    92 #endif
       
    93 
    90 QT_BEGIN_NAMESPACE
    94 QT_BEGIN_NAMESPACE
    91 
    95 
    92 // Goom Events through Window Server
    96 // Goom Events through Window Server
    93 static const int KGoomMemoryLowEvent = 0x10282DBF;
    97 static const int KGoomMemoryLowEvent = 0x10282DBF;
    94 static const int KGoomMemoryGoodEvent = 0x20026790;
    98 static const int KGoomMemoryGoodEvent = 0x20026790;
   108 QSymbianControl *QSymbianControl::lastFocusedControl = 0;
   112 QSymbianControl *QSymbianControl::lastFocusedControl = 0;
   109 
   113 
   110 QS60Data* qGlobalS60Data()
   114 QS60Data* qGlobalS60Data()
   111 {
   115 {
   112     return qt_s60Data();
   116     return qt_s60Data();
       
   117 }
       
   118 
       
   119 #ifdef Q_WS_S60
       
   120 void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible)
       
   121 {
       
   122     bool buttonGroupVisibilityChanged = false;
       
   123     if (CEikButtonGroupContainer *const b = buttonGroupContainer()) {
       
   124         buttonGroupVisibilityChanged = (b->IsVisible() != buttonGroupVisible);
       
   125         b->MakeVisible(buttonGroupVisible);
       
   126     }
       
   127     bool statusPaneVisibilityChanged = false;
       
   128     if (CEikStatusPane *const s = statusPane()) {
       
   129         statusPaneVisibilityChanged = (s->IsVisible() != statusPaneVisible);
       
   130         s->MakeVisible(statusPaneVisible);
       
   131     }
       
   132     if (buttonGroupVisibilityChanged  || statusPaneVisibilityChanged) {
       
   133         const QSize size = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()).size();
       
   134         const QSize oldSize; // note that QDesktopWidget::resizeEvent ignores the QResizeEvent contents
       
   135         QResizeEvent event(size, oldSize);
       
   136         QApplication::instance()->sendEvent(QApplication::desktop(), &event);
       
   137     }
       
   138     if (buttonGroupVisibilityChanged  && !statusPaneVisibilityChanged && QApplication::activeWindow())
       
   139         // Ensure that control rectangle is updated
       
   140         static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange();
       
   141 }
       
   142 #endif
       
   143 
       
   144 void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible)
       
   145 {
       
   146     if (QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control)) {
       
   147         QWidget *const widget = QWidgetPrivate::mapper->value(control);
       
   148         QWidget *const window = widget->window();
       
   149         if (QTLWExtra *topData = qt_widget_private(window)->maybeTopData()) {
       
   150             QWidgetBackingStoreTracker &backingStore = topData->backingStore;
       
   151             if (visible) {
       
   152                 if (backingStore.data()) {
       
   153                     backingStore.registerWidget(widget);
       
   154                 } else {
       
   155 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
   156                     S60->wsSession().SendEffectCommand(ETfxCmdRestoreLayer);
       
   157 #endif
       
   158                     backingStore.create(window);
       
   159                     backingStore.registerWidget(widget);
       
   160                     qt_widget_private(widget)->invalidateBuffer(widget->rect());
       
   161                     widget->repaint();
       
   162                 }
       
   163             } else {
       
   164 #ifdef  SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
   165                 S60->wsSession().SendEffectCommand(ETfxCmdDeallocateLayer);
       
   166 #endif
       
   167                 backingStore.unregisterWidget(widget);
       
   168                 // In order to ensure that any resources used by the window surface
       
   169                 // are immediately freed, we flush the WSERV command buffer.
       
   170                 S60->wsSession().Flush();
       
   171             }
       
   172         }
       
   173     }
   113 }
   174 }
   114 
   175 
   115 bool qt_nograb()                                // application no-grab option
   176 bool qt_nograb()                                // application no-grab option
   116 {
   177 {
   117 #if defined(QT_DEBUG)
   178 #if defined(QT_DEBUG)
   205     Q_UNUSED(aError);
   266     Q_UNUSED(aError);
   206     iState = EBeepPrepared;
   267     iState = EBeepPrepared;
   207 }
   268 }
   208 
   269 
   209 
   270 
   210 QHash<TInt, TUint> QApplicationPrivate::scanCodeCache;
       
   211 
       
   212 static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers)
   271 static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers)
   213 {
   272 {
   214     Qt::KeyboardModifiers result = Qt::NoModifier;
   273     Qt::KeyboardModifiers result = Qt::NoModifier;
   215 
   274 
   216     if (s60Modifiers & EModifierKeypad)
   275     if (s60Modifiers & EModifierKeypad)
   353 
   412 
   354 void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop)
   413 void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop)
   355 {
   414 {
   356     if (!desktop)
   415     if (!desktop)
   357     {
   416     {
   358         if (isWindowOwning or !qwidget->parentWidget())
   417         if (isWindowOwning || !qwidget->parentWidget())
   359             CreateWindowL(S60->windowGroup());
   418             CreateWindowL(S60->windowGroup());
   360         else
   419         else
   361             /**
   420             /**
   362              * TODO: in order to avoid creating windows for all ancestors of
   421              * TODO: in order to avoid creating windows for all ancestors of
   363              * this widget up to the root window, the parameter passed to
   422              * this widget up to the root window, the parameter passed to
   376         m_longTapDetector = QLongTapTimer::NewL(this);
   435         m_longTapDetector = QLongTapTimer::NewL(this);
   377         m_doubleClickTimer.invalidate();
   436         m_doubleClickTimer.invalidate();
   378 
   437 
   379         DrawableWindow()->SetPointerGrab(ETrue);
   438         DrawableWindow()->SetPointerGrab(ETrue);
   380     }
   439     }
       
   440 
       
   441 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
   442     if (OwnsWindow()) {
       
   443         TTfxWindowPurpose windowPurpose(ETfxPurposeNone);
       
   444         switch (qwidget->windowType()) {
       
   445         case Qt::Dialog:
       
   446             windowPurpose = ETfxPurposeDialogWindow;
       
   447             break;
       
   448         case Qt::Popup:
       
   449             windowPurpose = ETfxPurposePopupWindow;
       
   450             break;
       
   451         case Qt::Tool:
       
   452             windowPurpose = ETfxPurposeToolWindow;
       
   453             break;
       
   454         case Qt::ToolTip:
       
   455             windowPurpose = ETfxPurposeToolTipWindow;
       
   456             break;
       
   457         case Qt::SplashScreen:
       
   458             windowPurpose = ETfxPurposeSplashScreenWindow;
       
   459             break;
       
   460         default:
       
   461             windowPurpose = (isWindowOwning || !qwidget->parentWidget())
       
   462                             ? ETfxPurposeWindow : ETfxPurposeChildWindow;
       
   463             break;
       
   464         }
       
   465         Window().SetPurpose(windowPurpose);
       
   466     }
       
   467 #endif
   381 }
   468 }
   382 
   469 
   383 QSymbianControl::~QSymbianControl()
   470 QSymbianControl::~QSymbianControl()
   384 {
   471 {
       
   472     // Ensure backing store is deleted before the top-level
       
   473     // window is destroyed
       
   474     qt_widget_private(qwidget)->topData()->backingStore.destroy();
       
   475 
   385     if (S60->curWin == this)
   476     if (S60->curWin == this)
   386         S60->curWin = 0;
   477         S60->curWin = 0;
   387     if (!QApplicationPrivate::is_app_closing) {
   478     if (!QApplicationPrivate::is_app_closing) {
   388         QT_TRY {
   479         QT_TRY {
   389             setFocusSafely(false);
   480             setFocusSafely(false);
   619     return r;
   710     return r;
   620 }
   711 }
   621 
   712 
   622 TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type)
   713 TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type)
   623 {
   714 {
   624     switch (type) {
   715     /*
   625     //case EEventKeyDown: // <-- Intentionally left out. See below.
   716       S60 has a confusing way of delivering key events. There are three types of
   626     case EEventKeyUp:
   717       events: EEventKey, EEventKeyDown and EEventKeyUp. When a key is pressed,
   627     case EEventKey:
   718       EEventKeyDown is first generated, followed by EEventKey. Then, when the key is
   628     {
   719       released, EEventKeyUp is generated.
       
   720       However, it is possible that only the EEventKey is generated alone, typically
       
   721       in relation to virtual keyboards. In that case we need to take care to
       
   722       generate both press and release events in Qt, since applications expect that.
       
   723       We do this by having three states for each used scan code, depending on the
       
   724       events received. See the switch below for what happens in each state
       
   725       transition.
       
   726     */
       
   727 
       
   728     if (type != EEventKeyDown)
       
   729         if (handleVirtualMouse(keyEvent, type) == EKeyWasConsumed)
       
   730             return EKeyWasConsumed;
       
   731 
       
   732     TKeyResponse ret = EKeyWasNotConsumed;
       
   733 #define GET_RETURN(x) (ret = ((x) == EKeyWasConsumed) ? EKeyWasConsumed : ret)
       
   734 
       
   735     // This top level switch corresponds to the states, and the inner switches
       
   736     // correspond to the transitions.
       
   737     QS60Data::ScanCodeState &scanCodeState = S60->scanCodeStates[keyEvent.iScanCode];
       
   738     switch (scanCodeState) {
       
   739     case QS60Data::Unpressed:
       
   740         switch (type) {
       
   741         case EEventKeyDown:
       
   742             scanCodeState = QS60Data::KeyDown;
       
   743             break;
       
   744         case EEventKey:
       
   745             GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress));
       
   746             GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease));
       
   747             break;
       
   748         case EEventKeyUp:
       
   749             // No action.
       
   750             break;
       
   751         }
       
   752         break;
       
   753     case QS60Data::KeyDown:
       
   754         switch (type) {
       
   755         case EEventKeyDown:
       
   756             // This should never happen, just stay in this state to be safe.
       
   757             break;
       
   758         case EEventKey:
       
   759             GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress));
       
   760             scanCodeState = QS60Data::KeyDownAndKey;
       
   761             break;
       
   762         case EEventKeyUp:
       
   763             scanCodeState = QS60Data::Unpressed;
       
   764             break;
       
   765         }
       
   766         break;
       
   767     case QS60Data::KeyDownAndKey:
       
   768         switch (type) {
       
   769         case EEventKeyDown:
       
   770             // This should never happen, just stay in this state to be safe.
       
   771             break;
       
   772         case EEventKey:
       
   773             GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease));
       
   774             GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress));
       
   775             break;
       
   776         case EEventKeyUp:
       
   777             GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease));
       
   778             scanCodeState = QS60Data::Unpressed;
       
   779             break;
       
   780         }
       
   781         break;
       
   782     }
       
   783     return ret;
       
   784 
       
   785 #undef GET_RETURN
       
   786 }
       
   787 
       
   788 TKeyResponse QSymbianControl::sendSymbianKeyEvent(const TKeyEvent &keyEvent, QEvent::Type type)
       
   789 {
       
   790     // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp
       
   791     // events, we need to cache the keysyms from the EKeyEvent events. This is what
       
   792     // resolveS60ScanCode does.
       
   793     TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode,
       
   794             keyEvent.iCode);
       
   795     int keyCode;
       
   796     if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used
       
   797         keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode);
       
   798     } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
       
   799         // Normal characters keys.
       
   800         keyCode = s60Keysym;
       
   801     } else {
       
   802         // Special S60 keys.
       
   803         keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym);
       
   804     }
       
   805 
       
   806     Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
       
   807     QKeyEventEx qKeyEvent(type, keyCode, mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
       
   808             (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
       
   809     QWidget *widget;
       
   810     widget = QWidget::keyboardGrabber();
       
   811     if (!widget) {
       
   812         if (QApplicationPrivate::popupWidgets != 0) {
       
   813             widget = QApplication::activePopupWidget()->focusWidget();
       
   814             if (!widget) {
       
   815                 widget = QApplication::activePopupWidget();
       
   816             }
       
   817         } else {
       
   818             widget = QApplicationPrivate::focus_widget;
       
   819             if (!widget) {
       
   820                 widget = qwidget;
       
   821             }
       
   822         }
       
   823     }
       
   824 
       
   825     QEventDispatcherS60 *dispatcher;
       
   826     // It is theoretically possible for someone to install a different event dispatcher.
       
   827     if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) {
       
   828         if (dispatcher->excludeUserInputEvents()) {
       
   829             dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent));
       
   830             return EKeyWasConsumed;
       
   831         }
       
   832     }
       
   833     return sendKeyEvent(widget, &qKeyEvent);
       
   834 }
       
   835 
       
   836 TKeyResponse QSymbianControl::handleVirtualMouse(const TKeyEvent& keyEvent,TEventCode type)
       
   837 {
   629 #ifndef QT_NO_CURSOR
   838 #ifndef QT_NO_CURSOR
   630         if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) {
   839     if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) {
   631             //translate keys to pointer
   840         //translate keys to pointer
   632             if ((keyEvent.iScanCode >= EStdKeyLeftArrow && keyEvent.iScanCode <= EStdKeyDownArrow) ||
   841         if ((keyEvent.iScanCode >= EStdKeyLeftArrow && keyEvent.iScanCode <= EStdKeyDownArrow) ||
   633                 (keyEvent.iScanCode >= EStdKeyDevice10 && keyEvent.iScanCode <= EStdKeyDevice13) ||
   842                 (keyEvent.iScanCode >= EStdKeyDevice10 && keyEvent.iScanCode <= EStdKeyDevice13) ||
   634                 keyEvent.iScanCode == EStdKeyDevice3) {
   843                 keyEvent.iScanCode == EStdKeyDevice3) {
   635                 QPoint pos = QCursor::pos();
   844             QPoint pos = QCursor::pos();
   636                 TPointerEvent fakeEvent;
   845             TPointerEvent fakeEvent;
   637                 fakeEvent.iType = (TPointerEvent::TType)(-1);
   846             fakeEvent.iType = (TPointerEvent::TType)(-1);
   638                 fakeEvent.iModifiers = keyEvent.iModifiers;
   847             fakeEvent.iModifiers = keyEvent.iModifiers;
   639                 TInt x = pos.x();
   848             TInt x = pos.x();
   640                 TInt y = pos.y();
   849             TInt y = pos.y();
   641                 if (type == EEventKeyUp) {
   850             if (type == EEventKeyUp) {
   642                     S60->virtualMouseAccelTimeout.start();
   851                 S60->virtualMouseAccelTimeout.start();
   643                     switch (keyEvent.iScanCode) {
   852                 switch (keyEvent.iScanCode) {
   644                     case EStdKeyLeftArrow:
   853                 case EStdKeyLeftArrow:
   645                         S60->virtualMousePressedKeys &= ~QS60Data::Left;
   854                     S60->virtualMousePressedKeys &= ~QS60Data::Left;
   646                         break;
   855                     break;
   647                     case EStdKeyRightArrow:
   856                 case EStdKeyRightArrow:
   648                         S60->virtualMousePressedKeys &= ~QS60Data::Right;
   857                     S60->virtualMousePressedKeys &= ~QS60Data::Right;
   649                         break;
   858                     break;
   650                     case EStdKeyUpArrow:
   859                 case EStdKeyUpArrow:
   651                         S60->virtualMousePressedKeys &= ~QS60Data::Up;
   860                     S60->virtualMousePressedKeys &= ~QS60Data::Up;
   652                         break;
   861                     break;
   653                     case EStdKeyDownArrow:
   862                 case EStdKeyDownArrow:
   654                         S60->virtualMousePressedKeys &= ~QS60Data::Down;
   863                     S60->virtualMousePressedKeys &= ~QS60Data::Down;
   655                         break;
   864                     break;
   656                     // diagonal keys (named aliases don't exist in 3.1 SDK)
   865                 // diagonal keys (named aliases don't exist in 3.1 SDK)
   657                     case EStdKeyDevice10:
   866                 case EStdKeyDevice10:
   658                         S60->virtualMousePressedKeys &= ~QS60Data::LeftUp;
   867                     S60->virtualMousePressedKeys &= ~QS60Data::LeftUp;
   659                         break;
   868                     break;
   660                     case EStdKeyDevice11:
   869                 case EStdKeyDevice11:
   661                         S60->virtualMousePressedKeys &= ~QS60Data::RightUp;
   870                     S60->virtualMousePressedKeys &= ~QS60Data::RightUp;
   662                         break;
   871                     break;
   663                     case EStdKeyDevice12:
   872                 case EStdKeyDevice12:
   664                         S60->virtualMousePressedKeys &= ~QS60Data::RightDown;
   873                     S60->virtualMousePressedKeys &= ~QS60Data::RightDown;
   665                         break;
   874                     break;
   666                     case EStdKeyDevice13:
   875                 case EStdKeyDevice13:
   667                         S60->virtualMousePressedKeys &= ~QS60Data::LeftDown;
   876                     S60->virtualMousePressedKeys &= ~QS60Data::LeftDown;
   668                         break;
   877                     break;
   669                     case EStdKeyDevice3: //select
   878                 case EStdKeyDevice3: //select
   670                         if (S60->virtualMousePressedKeys & QS60Data::Select)
   879                     if (S60->virtualMousePressedKeys & QS60Data::Select)
   671                             fakeEvent.iType = TPointerEvent::EButton1Up;
   880                         fakeEvent.iType = TPointerEvent::EButton1Up;
   672                         S60->virtualMousePressedKeys &= ~QS60Data::Select;
   881                     S60->virtualMousePressedKeys &= ~QS60Data::Select;
   673                         break;
   882                     break;
   674                     }
       
   675                 }
       
   676                 else if (type == EEventKey) {
       
   677                     int dx = 0;
       
   678                     int dy = 0;
       
   679                     if (keyEvent.iScanCode != EStdKeyDevice3) {
       
   680                         m_doubleClickTimer.invalidate();
       
   681                         //reset mouse accelleration after a short time with no moves
       
   682                         const int maxTimeBetweenKeyEventsMs = 500;
       
   683                         if (S60->virtualMouseAccelTimeout.isValid() &&
       
   684                             S60->virtualMouseAccelTimeout.hasExpired(maxTimeBetweenKeyEventsMs)) {
       
   685                             S60->virtualMouseAccelDX = 0;
       
   686                             S60->virtualMouseAccelDY = 0;
       
   687                         }
       
   688                         S60->virtualMouseAccelTimeout.invalidate();
       
   689                     }
       
   690                     switch (keyEvent.iScanCode) {
       
   691                     case EStdKeyLeftArrow:
       
   692                         S60->virtualMousePressedKeys |= QS60Data::Left;
       
   693                         dx = -1;
       
   694                         fakeEvent.iType = TPointerEvent::EMove;
       
   695                         break;
       
   696                     case EStdKeyRightArrow:
       
   697                         S60->virtualMousePressedKeys |= QS60Data::Right;
       
   698                         dx = 1;
       
   699                         fakeEvent.iType = TPointerEvent::EMove;
       
   700                         break;
       
   701                     case EStdKeyUpArrow:
       
   702                         S60->virtualMousePressedKeys |= QS60Data::Up;
       
   703                         dy = -1;
       
   704                         fakeEvent.iType = TPointerEvent::EMove;
       
   705                         break;
       
   706                     case EStdKeyDownArrow:
       
   707                         S60->virtualMousePressedKeys |= QS60Data::Down;
       
   708                         dy = 1;
       
   709                         fakeEvent.iType = TPointerEvent::EMove;
       
   710                         break;
       
   711                     case EStdKeyDevice10:
       
   712                         S60->virtualMousePressedKeys |= QS60Data::LeftUp;
       
   713                         dx = -1;
       
   714                         dy = -1;
       
   715                         fakeEvent.iType = TPointerEvent::EMove;
       
   716                         break;
       
   717                     case EStdKeyDevice11:
       
   718                         S60->virtualMousePressedKeys |= QS60Data::RightUp;
       
   719                         dx = 1;
       
   720                         dy = -1;
       
   721                         fakeEvent.iType = TPointerEvent::EMove;
       
   722                         break;
       
   723                     case EStdKeyDevice12:
       
   724                         S60->virtualMousePressedKeys |= QS60Data::RightDown;
       
   725                         dx = 1;
       
   726                         dy = 1;
       
   727                         fakeEvent.iType = TPointerEvent::EMove;
       
   728                         break;
       
   729                     case EStdKeyDevice13:
       
   730                         S60->virtualMousePressedKeys |= QS60Data::LeftDown;
       
   731                         dx = -1;
       
   732                         dy = 1;
       
   733                         fakeEvent.iType = TPointerEvent::EMove;
       
   734                         break;
       
   735                     case EStdKeyDevice3:
       
   736                         // Platform bug. If you start pressing several keys simultaneously (for
       
   737                         // example for drag'n'drop), Symbian starts producing spurious up and
       
   738                         // down messages for some keys. Therefore, make sure we have a clean slate
       
   739                         // of pressed keys before starting a new button press.
       
   740                         if (S60->virtualMousePressedKeys & QS60Data::Select) {
       
   741                             return EKeyWasConsumed;
       
   742                         } else {
       
   743                             S60->virtualMousePressedKeys |= QS60Data::Select;
       
   744                             fakeEvent.iType = TPointerEvent::EButton1Down;
       
   745                             if (m_doubleClickTimer.isValid()
       
   746                                 && !m_doubleClickTimer.hasExpired(QApplication::doubleClickInterval())) {
       
   747                                 fakeEvent.iModifiers |= EModifierDoubleClick;
       
   748                                 m_doubleClickTimer.invalidate();
       
   749                             } else {
       
   750                                 m_doubleClickTimer.start();
       
   751                             }
       
   752                         }
       
   753                         break;
       
   754                     }
       
   755                     if (dx) {
       
   756                         int cdx = S60->virtualMouseAccelDX;
       
   757                         //reset accel on change of sign, else double accel
       
   758                         if (dx * cdx <= 0)
       
   759                             cdx = dx;
       
   760                         else
       
   761                             cdx *= 4;
       
   762                         //cap accelleration
       
   763                         if (dx * cdx > S60->virtualMouseMaxAccel)
       
   764                             cdx = dx * S60->virtualMouseMaxAccel;
       
   765                         //move mouse position
       
   766                         x += cdx;
       
   767                         S60->virtualMouseAccelDX = cdx;
       
   768                     }
       
   769 
       
   770                     if (dy) {
       
   771                         int cdy = S60->virtualMouseAccelDY;
       
   772                         if (dy * cdy <= 0)
       
   773                             cdy = dy;
       
   774                         else
       
   775                             cdy *= 4;
       
   776                         if (dy * cdy > S60->virtualMouseMaxAccel)
       
   777                             cdy = dy * S60->virtualMouseMaxAccel;
       
   778                         y += cdy;
       
   779                         S60->virtualMouseAccelDY = cdy;
       
   780                     }
       
   781                 }
       
   782                 //clip to screen size (window server allows a sprite hotspot to be outside the screen)
       
   783                 if (x < 0)
       
   784                     x = 0;
       
   785                 else if (x >= S60->screenWidthInPixels)
       
   786                     x = S60->screenWidthInPixels - 1;
       
   787                 if (y < 0)
       
   788                     y = 0;
       
   789                 else if (y >= S60->screenHeightInPixels)
       
   790                     y = S60->screenHeightInPixels - 1;
       
   791                 TPoint epos(x, y);
       
   792                 TPoint cpos = epos - PositionRelativeToScreen();
       
   793                 fakeEvent.iPosition = cpos;
       
   794                 fakeEvent.iParentPosition = epos;
       
   795                 if(fakeEvent.iType != -1)
       
   796                     HandlePointerEvent(fakeEvent);
       
   797                 return EKeyWasConsumed;
       
   798             }
       
   799         }
       
   800 #endif
       
   801         // S60 has a confusing way of delivering key events. There are three types of
       
   802         // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the
       
   803         // two first events are generated. When releasing the key, the last one is
       
   804         // generated.
       
   805         // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events,
       
   806         // we need to do some special tricks to map it to the Qt way. First, we completely
       
   807         // discard EKeyEventDown events, since they are redundant. Second, since
       
   808         // EKeyEventUp does not give us a keysym, we need to cache the keysyms from
       
   809         // the EKeyEvent events. This is what resolveS60ScanCode does.
       
   810 
       
   811 
       
   812         // ### hackish way to send Qt application to background when pressing right softkey
       
   813         /*
       
   814         if( keyEvent.iScanCode == EStdKeyDevice1 ) {
       
   815             S60->window_group->SetOrdinalPosition(-1);
       
   816             qApp->setActiveWindow(0);
       
   817             return EKeyWasNotConsumed;
       
   818         }
       
   819         */
       
   820 
       
   821         TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode,
       
   822                 keyEvent.iCode);
       
   823         int keyCode;
       
   824         if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used
       
   825             keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode);
       
   826         } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
       
   827             // Normal characters keys.
       
   828             keyCode = s60Keysym;
       
   829         } else {
       
   830             // Special S60 keys.
       
   831             keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym);
       
   832         }
       
   833 
       
   834         Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
       
   835         QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
       
   836                 mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
       
   837                 (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
       
   838 //        WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
       
   839 //        if (!wid)
       
   840 //             Could happen if window isn't shown yet.
       
   841 //            return EKeyWasNotConsumed;
       
   842         QWidget *widget;
       
   843         widget = QWidget::keyboardGrabber();
       
   844         if (!widget) {
       
   845             if (QApplicationPrivate::popupWidgets != 0) {
       
   846                 widget = QApplication::activePopupWidget()->focusWidget();
       
   847                 if (!widget) {
       
   848                     widget = QApplication::activePopupWidget();
       
   849                 }
       
   850             } else {
       
   851                 widget = QApplicationPrivate::focus_widget;
       
   852                 if (!widget) {
       
   853                     widget = qwidget;
       
   854                 }
   883                 }
   855             }
   884             }
   856         }
   885             else if (type == EEventKey) {
   857 
   886                 int dx = 0;
   858         QEventDispatcherS60 *dispatcher;
   887                 int dy = 0;
   859         // It is theoretically possible for someone to install a different event dispatcher.
   888                 if (keyEvent.iScanCode != EStdKeyDevice3) {
   860         if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) {
   889                     m_doubleClickTimer.invalidate();
   861             if (dispatcher->excludeUserInputEvents()) {
   890                     //reset mouse accelleration after a short time with no moves
   862                 dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent));
   891                     const int maxTimeBetweenKeyEventsMs = 500;
   863                 return EKeyWasConsumed;
   892                     if (S60->virtualMouseAccelTimeout.isValid() &&
       
   893                             S60->virtualMouseAccelTimeout.hasExpired(maxTimeBetweenKeyEventsMs)) {
       
   894                         S60->virtualMouseAccelDX = 0;
       
   895                         S60->virtualMouseAccelDY = 0;
       
   896                     }
       
   897                     S60->virtualMouseAccelTimeout.invalidate();
       
   898                 }
       
   899                 switch (keyEvent.iScanCode) {
       
   900                 case EStdKeyLeftArrow:
       
   901                     S60->virtualMousePressedKeys |= QS60Data::Left;
       
   902                     dx = -1;
       
   903                     fakeEvent.iType = TPointerEvent::EMove;
       
   904                     break;
       
   905                 case EStdKeyRightArrow:
       
   906                     S60->virtualMousePressedKeys |= QS60Data::Right;
       
   907                     dx = 1;
       
   908                     fakeEvent.iType = TPointerEvent::EMove;
       
   909                     break;
       
   910                 case EStdKeyUpArrow:
       
   911                     S60->virtualMousePressedKeys |= QS60Data::Up;
       
   912                     dy = -1;
       
   913                     fakeEvent.iType = TPointerEvent::EMove;
       
   914                     break;
       
   915                 case EStdKeyDownArrow:
       
   916                     S60->virtualMousePressedKeys |= QS60Data::Down;
       
   917                     dy = 1;
       
   918                     fakeEvent.iType = TPointerEvent::EMove;
       
   919                     break;
       
   920                 case EStdKeyDevice10:
       
   921                     S60->virtualMousePressedKeys |= QS60Data::LeftUp;
       
   922                     dx = -1;
       
   923                     dy = -1;
       
   924                     fakeEvent.iType = TPointerEvent::EMove;
       
   925                     break;
       
   926                 case EStdKeyDevice11:
       
   927                     S60->virtualMousePressedKeys |= QS60Data::RightUp;
       
   928                     dx = 1;
       
   929                     dy = -1;
       
   930                     fakeEvent.iType = TPointerEvent::EMove;
       
   931                     break;
       
   932                 case EStdKeyDevice12:
       
   933                     S60->virtualMousePressedKeys |= QS60Data::RightDown;
       
   934                     dx = 1;
       
   935                     dy = 1;
       
   936                     fakeEvent.iType = TPointerEvent::EMove;
       
   937                     break;
       
   938                 case EStdKeyDevice13:
       
   939                     S60->virtualMousePressedKeys |= QS60Data::LeftDown;
       
   940                     dx = -1;
       
   941                     dy = 1;
       
   942                     fakeEvent.iType = TPointerEvent::EMove;
       
   943                     break;
       
   944                 case EStdKeyDevice3:
       
   945                     // Platform bug. If you start pressing several keys simultaneously (for
       
   946                     // example for drag'n'drop), Symbian starts producing spurious up and
       
   947                     // down messages for some keys. Therefore, make sure we have a clean slate
       
   948                     // of pressed keys before starting a new button press.
       
   949                     if (S60->virtualMousePressedKeys & QS60Data::Select) {
       
   950                         return EKeyWasConsumed;
       
   951                     } else {
       
   952                         S60->virtualMousePressedKeys |= QS60Data::Select;
       
   953                         fakeEvent.iType = TPointerEvent::EButton1Down;
       
   954                         if (m_doubleClickTimer.isValid()
       
   955                                 && !m_doubleClickTimer.hasExpired(QApplication::doubleClickInterval())) {
       
   956                             fakeEvent.iModifiers |= EModifierDoubleClick;
       
   957                             m_doubleClickTimer.invalidate();
       
   958                         } else {
       
   959                             m_doubleClickTimer.start();
       
   960                         }
       
   961                     }
       
   962                     break;
       
   963                 }
       
   964                 if (dx) {
       
   965                     int cdx = S60->virtualMouseAccelDX;
       
   966                     //reset accel on change of sign, else double accel
       
   967                     if (dx * cdx <= 0)
       
   968                         cdx = dx;
       
   969                     else
       
   970                         cdx *= 4;
       
   971                     //cap accelleration
       
   972                     if (dx * cdx > S60->virtualMouseMaxAccel)
       
   973                         cdx = dx * S60->virtualMouseMaxAccel;
       
   974                     //move mouse position
       
   975                     x += cdx;
       
   976                     S60->virtualMouseAccelDX = cdx;
       
   977                 }
       
   978 
       
   979                 if (dy) {
       
   980                     int cdy = S60->virtualMouseAccelDY;
       
   981                     if (dy * cdy <= 0)
       
   982                         cdy = dy;
       
   983                     else
       
   984                         cdy *= 4;
       
   985                     if (dy * cdy > S60->virtualMouseMaxAccel)
       
   986                         cdy = dy * S60->virtualMouseMaxAccel;
       
   987                     y += cdy;
       
   988                     S60->virtualMouseAccelDY = cdy;
       
   989                 }
   864             }
   990             }
   865         }
   991             //clip to screen size (window server allows a sprite hotspot to be outside the screen)
   866         return sendKeyEvent(widget, &qKeyEvent);
   992             if (x < 0)
   867     }
   993                 x = 0;
   868     }
   994             else if (x >= S60->screenWidthInPixels)
       
   995                 x = S60->screenWidthInPixels - 1;
       
   996             if (y < 0)
       
   997                 y = 0;
       
   998             else if (y >= S60->screenHeightInPixels)
       
   999                 y = S60->screenHeightInPixels - 1;
       
  1000             TPoint epos(x, y);
       
  1001             TPoint cpos = epos - PositionRelativeToScreen();
       
  1002             fakeEvent.iPosition = cpos;
       
  1003             fakeEvent.iParentPosition = epos;
       
  1004             if(fakeEvent.iType != -1)
       
  1005                 HandlePointerEvent(fakeEvent);
       
  1006             return EKeyWasConsumed;
       
  1007         }
       
  1008     }
       
  1009 #endif
       
  1010 
   869     return EKeyWasNotConsumed;
  1011     return EKeyWasNotConsumed;
   870 }
  1012 }
   871 
  1013 
   872 void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent)
  1014 void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent)
   873 {
  1015 {
   961         QS60WindowSurface *s60Surface;
  1103         QS60WindowSurface *s60Surface;
   962 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
  1104 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
   963         if (QApplicationPrivate::runtime_graphics_system) {
  1105         if (QApplicationPrivate::runtime_graphics_system) {
   964             QRuntimeWindowSurface *rtSurface =
  1106             QRuntimeWindowSurface *rtSurface =
   965                     static_cast<QRuntimeWindowSurface*>(qwidget->windowSurface());
  1107                     static_cast<QRuntimeWindowSurface*>(qwidget->windowSurface());
   966             s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface);
  1108             s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface.data());
   967         } else
  1109         } else
   968 #endif
  1110 #endif
   969             s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
  1111             s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
   970 
  1112 
   971         CFbsBitmap *bitmap = s60Surface->symbianBitmap();
  1113         CFbsBitmap *bitmap = s60Surface->symbianBitmap();
   972         CWindowGc &gc = SystemGc();
  1114         CWindowGc &gc = SystemGc();
   973 
  1115 
   974         switch(qwidget->d_func()->extraData()->nativePaintMode) {
  1116         QWExtra::NativePaintMode nativePaintMode = qwidget->d_func()->extraData()->nativePaintMode;
       
  1117         if(qwidget->d_func()->paintOnScreen())
       
  1118             nativePaintMode = QWExtra::Disable;
       
  1119 
       
  1120         switch(nativePaintMode) {
   975         case QWExtra::Disable:
  1121         case QWExtra::Disable:
   976             // Do nothing
  1122             // Do nothing
   977             break;
  1123             break;
   978 
       
   979         case QWExtra::Blit:
  1124         case QWExtra::Blit:
   980             if (qwidget->d_func()->isOpaque)
  1125             if (qwidget->d_func()->isOpaque)
   981                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
  1126                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
   982             gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
  1127             gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
   983             break;
  1128             break;
   984 
       
   985         case QWExtra::ZeroFill:
  1129         case QWExtra::ZeroFill:
   986             if (Window().DisplayMode() == EColor16MA) {
  1130             if (Window().DisplayMode() == EColor16MA
       
  1131                 || Window().DisplayMode() == Q_SYMBIAN_ECOLOR16MAP) {
   987                 gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
  1132                 gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
   988                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
  1133                 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
   989                 gc.SetBrushColor(TRgb::Color16MA(0));
  1134                 gc.SetBrushColor(TRgb::Color16MA(0));
   990                 gc.Clear(controlRect);
  1135                 gc.Clear(controlRect);
   991             } else {
  1136             } else {
   992                 gc.SetBrushColor(TRgb(0x000000));
  1137                 gc.SetBrushColor(TRgb(0x000000));
   993                 gc.Clear(controlRect);
  1138                 gc.Clear(controlRect);
   994             };
  1139             };
   995             break;
  1140             break;
   996 
       
   997         default:
  1141         default:
   998             Q_ASSERT(false);
  1142             Q_ASSERT(false);
   999         }
  1143         }
  1000     }
  1144     }
  1001 
  1145 
  1094         QApplication::setActiveWindow(qwidget->window());
  1238         QApplication::setActiveWindow(qwidget->window());
  1095         qwidget->d_func()->setWindowIcon_sys(true);
  1239         qwidget->d_func()->setWindowIcon_sys(true);
  1096         qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
  1240         qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
  1097 #ifdef Q_WS_S60
  1241 #ifdef Q_WS_S60
  1098         // If widget is fullscreen/minimized, hide status pane and button container otherwise show them.
  1242         // If widget is fullscreen/minimized, hide status pane and button container otherwise show them.
  1099         CEikStatusPane *statusPane = S60->statusPane();
  1243         const bool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
  1100         CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer();
  1244         const bool statusPaneVisibility = visible;
  1101         TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
  1245         const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
  1102         if (statusPane)
  1246         const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
  1103             statusPane->MakeVisible(visible);
  1247         const bool buttonGroupVisibility = (visible || (isFullscreen && cbaVisibilityHint));
  1104         if (buttonGroup) {
  1248         S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility);
  1105             // Visibility
       
  1106             const TBool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
       
  1107             const TBool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
       
  1108             buttonGroup->MakeVisible(visible || (isFullscreen && cbaVisibilityHint));
       
  1109         }
       
  1110 #endif
  1249 #endif
  1111     } else if (QApplication::activeWindow() == qwidget->window()) {
  1250     } else if (QApplication::activeWindow() == qwidget->window()) {
  1112         if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) {
  1251         bool focusedControlFound = false;
  1113             QWidget *fw = QApplication::focusWidget();
  1252         WId winId = 0;
  1114             if (fw) {
  1253         for (QWidget *w = qwidget->parentWidget(); w && (winId = w->internalWinId()); w = w->parentWidget()) {
  1115                 QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
  1254             if (winId->IsFocused() && winId->IsVisible()) {
  1116                 QCoreApplication::sendEvent(fw, &event);
  1255                 focusedControlFound = true;
       
  1256                 break;
       
  1257             } else if (w->isWindow())
       
  1258                 break;
       
  1259         }
       
  1260         if (!focusedControlFound) {
       
  1261             if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) {
       
  1262                 QWidget *fw = QApplication::focusWidget();
       
  1263                 if (fw) {
       
  1264                     QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
       
  1265                     QCoreApplication::sendEvent(fw, &event);
       
  1266                 }
       
  1267                 m_symbianPopupIsOpen = true;
       
  1268                 return;
  1117             }
  1269             }
  1118             m_symbianPopupIsOpen = true;
  1270 
  1119             return;
  1271             QApplication::setActiveWindow(0);
  1120         }
  1272         }
  1121 
       
  1122         QApplication::setActiveWindow(0);
       
  1123     }
  1273     }
  1124     // else { We don't touch the active window unless we were explicitly activated or deactivated }
  1274     // else { We don't touch the active window unless we were explicitly activated or deactivated }
  1125 }
  1275 }
  1126 
  1276 
  1127 void QSymbianControl::handleClientAreaChange()
  1277 void QSymbianControl::handleClientAreaChange()
  1209             lastFocusedControl = 0;
  1359             lastFocusedControl = 0;
  1210         this->SetFocus(false);
  1360         this->SetFocus(false);
  1211     }
  1361     }
  1212 }
  1362 }
  1213 
  1363 
       
  1364 bool QSymbianControl::isControlActive()
       
  1365 {
       
  1366     return IsActivated() ? true : false;
       
  1367 }
       
  1368 
  1214 /*!
  1369 /*!
  1215     \typedef QApplication::QS60MainApplicationFactory
  1370     \typedef QApplication::QS60MainApplicationFactory
  1216     \since 4.6
  1371     \since 4.6
  1217 
  1372 
  1218     This is a typedef for a pointer to a function with the following
  1373     This is a typedef for a pointer to a function with the following
  1259         // an outer one already. To avoid this, we save the original trap handler here, and set
  1414         // an outer one already. To avoid this, we save the original trap handler here, and set
  1260         // it back after the S60 framework is constructed. Then we restore it right before the S60
  1415         // it back after the S60 framework is constructed. Then we restore it right before the S60
  1261         // framework destruction.
  1416         // framework destruction.
  1262         TTrapHandler *origTrapHandler = User::TrapHandler();
  1417         TTrapHandler *origTrapHandler = User::TrapHandler();
  1263 
  1418 
  1264         // The S60 framework has not been initalized. We need to do it.
  1419         // The S60 framework has not been initialized. We need to do it.
  1265         TApaApplicationFactory factory(S60->s60ApplicationFactory ?
  1420         TApaApplicationFactory factory(S60->s60ApplicationFactory ?
  1266                 S60->s60ApplicationFactory : newS60Application);
  1421                 S60->s60ApplicationFactory : newS60Application);
  1267         CApaCommandLine* commandLine = 0;
  1422         CApaCommandLine* commandLine = 0;
  1268         TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine);
  1423         TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine);
  1269         // After this construction, CEikonEnv will be available from CEikonEnv::Static().
  1424         // After this construction, CEikonEnv will be available from CEikonEnv::Static().
  1373         err = repository->Get(KAknAvkonTransparencyEnabled, value);
  1528         err = repository->Get(KAknAvkonTransparencyEnabled, value);
  1374         if(err == KErrNone) {
  1529         if(err == KErrNone) {
  1375             S60->avkonComponentsSupportTransparency = (value==1) ? true : false;
  1530             S60->avkonComponentsSupportTransparency = (value==1) ? true : false;
  1376         }
  1531         }
  1377     }
  1532     }
       
  1533     delete repository;
       
  1534     repository = 0;
  1378 #endif
  1535 #endif
  1379 
  1536 
  1380 #ifdef QT_KEYPAD_NAVIGATION
  1537 #ifdef QT_KEYPAD_NAVIGATION
  1381     if (touch) {
  1538     if (touch) {
  1382         QApplicationPrivate::navigationMode = Qt::NavigationModeNone;
  1539         QApplicationPrivate::navigationMode = Qt::NavigationModeNone;
  1414 
  1571 
  1415     QFont systemFont;
  1572     QFont systemFont;
  1416     systemFont.setFamily(systemFont.defaultFamily());
  1573     systemFont.setFamily(systemFont.defaultFamily());
  1417     QApplicationPrivate::setSystemFont(systemFont);
  1574     QApplicationPrivate::setSystemFont(systemFont);
  1418 
  1575 
       
  1576 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
  1577     QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit()));
       
  1578 #endif
       
  1579 
  1419 /*
  1580 /*
  1420  ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag
  1581  ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag
  1421     int argc = priv->argc;
  1582     int argc = priv->argc;
  1422     char **argv = priv->argv;
  1583     char **argv = priv->argv;
  1423 
  1584 
  1437             ;
  1598             ;
  1438     }
  1599     }
  1439 */
  1600 */
  1440 
  1601 
  1441     // Register WId with the metatype system.  This is to enable
  1602     // Register WId with the metatype system.  This is to enable
  1442     // QWidgetPrivate::create_sys to used delayed slot invokation in order
  1603     // QWidgetPrivate::create_sys to used delayed slot invocation in order
  1443     // to destroy WId objects during reparenting.
  1604     // to destroy WId objects during reparenting.
  1444     qRegisterMetaType<WId>("WId");
  1605     qRegisterMetaType<WId>("WId");
  1445 }
  1606 }
  1446 
  1607 
  1447 extern void qt_cleanup_symbianFontDatabaseExtras(); // qfontdatabase_s60.cpp
  1608 extern void qt_cleanup_symbianFontDatabaseExtras(); // qfontdatabase_s60.cpp
  1503     return app_do_modal;
  1664     return app_do_modal;
  1504 }
  1665 }
  1505 
  1666 
  1506 void QApplicationPrivate::enterModal_sys(QWidget *widget)
  1667 void QApplicationPrivate::enterModal_sys(QWidget *widget)
  1507 {
  1668 {
       
  1669 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
  1670     S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeEnter);
       
  1671 #endif
  1508     if (widget) {
  1672     if (widget) {
  1509         static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue);
  1673         static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue);
  1510         // Modal partial screen dialogs (like queries) capture pointer events.
  1674         // Modal partial screen dialogs (like queries) capture pointer events.
  1511         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1675         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1512         widget->effectiveWinId()->SetGloballyCapturing(ETrue);
  1676         widget->effectiveWinId()->SetGloballyCapturing(ETrue);
  1518     app_do_modal = true;
  1682     app_do_modal = true;
  1519 }
  1683 }
  1520 
  1684 
  1521 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
  1685 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
  1522 {
  1686 {
       
  1687 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
  1688     S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeExit);
       
  1689 #endif
  1523     if (widget) {
  1690     if (widget) {
  1524         static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse);
  1691         static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse);
  1525         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1692         // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
  1526         widget->effectiveWinId()->SetGloballyCapturing(EFalse);
  1693         widget->effectiveWinId()->SetGloballyCapturing(EFalse);
  1527         widget->effectiveWinId()->SetPointerCapture(EFalse);
  1694         widget->effectiveWinId()->SetPointerCapture(EFalse);
  1808     case EEventWindowVisibilityChanged:
  1975     case EEventWindowVisibilityChanged:
  1809         if (controlInMap) {
  1976         if (controlInMap) {
  1810             if (callSymbianEventFilters(symbianEvent))
  1977             if (callSymbianEventFilters(symbianEvent))
  1811                 return 1;
  1978                 return 1;
  1812             const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged();
  1979             const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged();
  1813             QWidget *w = QWidgetPrivate::mapper->value(control);
  1980             if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible)
  1814             QWidget *const window = w->window();
  1981                 S60->controlVisibilityChanged(control, false);
  1815             if (!window->d_func()->maybeTopData())
  1982             else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
  1816                 break;
  1983                 S60->controlVisibilityChanged(control, true);
  1817             QRefCountedWidgetBackingStore &backingStore = window->d_func()->maybeTopData()->backingStore;
       
  1818             if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) {
       
  1819                 backingStore.widgetHidden(w);
       
  1820                 // In order to ensure that any resources used by the window surface
       
  1821                 // are immediately freed, we flush the WSERV command buffer.
       
  1822                 S60->wsSession().Flush();
       
  1823             } else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) {
       
  1824                 if (backingStore.data()) {
       
  1825                     backingStore.widgetShown(w);
       
  1826                 } else {
       
  1827                     // Create backing store with an initial reference count of 1
       
  1828                     backingStore.create(window);
       
  1829                     backingStore.widgetShown(w);
       
  1830                     w->d_func()->invalidateBuffer(w->rect());
       
  1831                     w->repaint();
       
  1832                 }
       
  1833             }
       
  1834             return 1;
  1984             return 1;
  1835         }
  1985         }
  1836         break;
  1986         break;
  1837     case EEventFocusGained:
  1987     case EEventFocusGained:
  1838         if (callSymbianEventFilters(symbianEvent))
  1988         if (callSymbianEventFilters(symbianEvent))
  1882             }
  2032             }
  1883 
  2033 
  1884             if (switchToSwRendering) {
  2034             if (switchToSwRendering) {
  1885                 QRuntimeGraphicsSystem *gs =
  2035                 QRuntimeGraphicsSystem *gs =
  1886                    static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
  2036                    static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
  1887 
       
  1888                 uint memoryUsage = gs->memoryUsage();
       
  1889                 uint memoryForFullscreen = ( S60->screenDepth / 8 )
       
  1890                                            * S60->screenWidthInPixels
       
  1891                                            * S60->screenHeightInPixels;
       
  1892 
       
  1893                 S60->memoryLimitForHwRendering = memoryUsage - memoryForFullscreen;
       
  1894                 gs->setGraphicsSystem(QLatin1String("raster"));
  2037                 gs->setGraphicsSystem(QLatin1String("raster"));
  1895             }
  2038             }
  1896         }
  2039         }
  1897 #endif
  2040 #endif
  1898         break;
  2041         break;
  1904             return 1;
  2047             return 1;
  1905 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
  2048 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
  1906         if(QApplicationPrivate::runtime_graphics_system) {
  2049         if(QApplicationPrivate::runtime_graphics_system) {
  1907             QRuntimeGraphicsSystem *gs =
  2050             QRuntimeGraphicsSystem *gs =
  1908                    static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
  2051                    static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
  1909             gs->setGraphicsSystem(QLatin1String("openvg"), S60->memoryLimitForHwRendering);
  2052             gs->setGraphicsSystem(QLatin1String("openvg"));
  1910             S60->memoryLimitForHwRendering = 0;
       
  1911         }
  2053         }
  1912 #endif
  2054 #endif
  1913         break;
  2055         break;
  1914     default:
  2056     default:
  1915         break;
  2057         break;
  2074     // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
  2216     // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
  2075 }
  2217 }
  2076 
  2218 
  2077 TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym)
  2219 TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym)
  2078 {
  2220 {
       
  2221     if (!scanCode)
       
  2222         return keysym;
       
  2223 
       
  2224     QApplicationPrivate *d = QApplicationPrivate::instance();
       
  2225 
  2079     if (keysym) {
  2226     if (keysym) {
  2080         // If keysym is specified, cache it.
  2227         // If keysym is specified, cache it.
  2081         scanCodeCache.insert(scanCode, keysym);
  2228         d->scanCodeCache.insert(scanCode, keysym);
  2082         return keysym;
  2229         return keysym;
  2083     } else {
  2230     } else {
  2084         // If not, retrieve the cached version.
  2231         // If not, retrieve the cached version.
  2085         return scanCodeCache[scanCode];
  2232         return d->scanCodeCache[scanCode];
  2086     }
  2233     }
  2087 }
  2234 }
  2088 
  2235 
  2089 void QApplicationPrivate::initializeMultitouch_sys()
  2236 void QApplicationPrivate::initializeMultitouch_sys()
  2090 {
  2237 {
  2200     }
  2347     }
  2201 }
  2348 }
  2202 
  2349 
  2203 #endif // QT_NO_CURSOR
  2350 #endif // QT_NO_CURSOR
  2204 
  2351 
       
  2352 void QApplicationPrivate::_q_aboutToQuit()
       
  2353 {
       
  2354 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
       
  2355     // Send the shutdown tfx command
       
  2356     S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown);
       
  2357 #endif
       
  2358 }
       
  2359 
  2205 QS60ThreadLocalData::QS60ThreadLocalData()
  2360 QS60ThreadLocalData::QS60ThreadLocalData()
  2206 {
  2361 {
  2207     CCoeEnv *env = CCoeEnv::Static();
  2362     CCoeEnv *env = CCoeEnv::Static();
  2208     if (env) {
  2363     if (env) {
  2209         //if this is the UI thread, share objects owned by CONE
  2364         //if this is the UI thread, share objects owned by CONE