1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
36 ** If you have questions regarding the use of this file, please contact
37 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qapplication_p.h"
43 #include "qsessionmanager.h"
45 #include "qsymbianevent.h"
46 #include "qeventdispatcher_s60_p.h"
48 #include "qdesktopwidget.h"
49 #include "private/qbackingstore_p.h"
51 #include "private/qevent_p.h"
55 #include "qcombobox.h"
56 #include "private/qkeymapper_p.h"
57 #include "private/qfont_p.h"
58 #ifndef QT_NO_STYLE_S60
59 #include "private/qs60style_p.h"
61 #include "private/qwindowsurface_s60_p.h"
62 #include "qpaintengine.h"
63 #include "private/qmenubar_p.h"
64 #include "private/qsoftkeymanager_p.h"
65 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
66 #include "private/qgraphicssystem_runtime_p.h"
69 #include "apgwgnam.h" // For CApaWindowGroupName
70 #include <mdaaudiotoneplayer.h> // For CMdaAudioToneUtility
72 #if defined(Q_OS_SYMBIAN)
73 # include <private/qs60mainapplication_p.h>
74 # include <centralrepository.h>
75 # include "qs60mainappui.h"
76 # include "qinputcontext.h"
80 # if !defined(QT_NO_IM)
81 # include <private/qcoefepinputcontext_p.h>
85 #include "private/qstylesheetstyle_p.h"
90 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
91 #include <graphics/wstfxconst.h>
96 // Goom Events through Window Server
97 static const int KGoomMemoryLowEvent = 0x10282DBF;
98 static const int KGoomMemoryGoodEvent = 0x20026790;
100 #if defined(QT_DEBUG)
101 static bool appNoGrab = false; // Grabbing enabled
103 static bool app_do_modal = false; // modal mode
104 Q_GLOBAL_STATIC(QS60Data, qt_s60Data);
106 extern bool qt_sendSpontaneousEvent(QObject*,QEvent*);
107 extern QWidgetList *qt_modal_stack; // stack of modal widgets
108 extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
110 QWidget *qt_button_down = 0; // widget got last button-down
112 QSymbianControl *QSymbianControl::lastFocusedControl = 0;
114 QS60Data* qGlobalS60Data()
120 void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible)
122 bool buttonGroupVisibilityChanged = false;
123 if (CEikButtonGroupContainer *const b = buttonGroupContainer()) {
124 buttonGroupVisibilityChanged = (b->IsVisible() != buttonGroupVisible);
125 b->MakeVisible(buttonGroupVisible);
127 bool statusPaneVisibilityChanged = false;
128 if (CEikStatusPane *const s = statusPane()) {
129 statusPaneVisibilityChanged = (s->IsVisible() != statusPaneVisible);
130 s->MakeVisible(statusPaneVisible);
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);
138 if (buttonGroupVisibilityChanged && !statusPaneVisibilityChanged && QApplication::activeWindow())
139 // Ensure that control rectangle is updated
140 static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange();
144 void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible)
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;
152 if (backingStore.data()) {
153 backingStore.registerWidget(widget);
155 backingStore.create(window);
156 backingStore.registerWidget(widget);
157 qt_widget_private(widget)->invalidateBuffer(widget->rect());
161 backingStore.unregisterWidget(widget);
162 // In order to ensure that any resources used by the window surface
163 // are immediately freed, we flush the WSERV command buffer.
164 S60->wsSession().Flush();
170 bool qt_nograb() // application no-grab option
172 #if defined(QT_DEBUG)
179 // Modified from http://www3.symbian.com/faq.nsf/0/0F1464EE96E737E780256D5E00503DD1?OpenDocument
180 class QS60Beep : public CBase, public MMdaAudioToneObserver
183 static QS60Beep* NewL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration);
187 void ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration);
188 void MatoPrepareComplete(TInt aError);
189 void MatoPlayComplete(TInt aError);
198 CMdaAudioToneUtility* iToneUtil;
201 TTimeIntervalMicroSeconds iDuration;
204 static QS60Beep* qt_S60Beep = 0;
206 QS60Beep::~QS60Beep()
211 iToneUtil->CancelPlay();
213 case EBeepNotPrepared:
214 iToneUtil->CancelPrepare();
221 QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
223 QS60Beep* self = new (ELeave) QS60Beep();
224 CleanupStack::PushL(self);
225 self->ConstructL(aFrequency, aDuration);
230 void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
232 iToneUtil = CMdaAudioToneUtility::NewL(*this);
233 iState = EBeepNotPrepared;
234 iFrequency = aFrequency;
235 iDuration = aDuration;
236 iToneUtil->PrepareToPlayTone(iFrequency, iDuration);
239 void QS60Beep::Play()
241 if (iState == EBeepPlaying) {
242 iToneUtil->CancelPlay();
243 iState = EBeepPrepared;
247 iState = EBeepPlaying;
250 void QS60Beep::MatoPrepareComplete(TInt aError)
252 if (aError == KErrNone) {
253 iState = EBeepPrepared;
258 void QS60Beep::MatoPlayComplete(TInt aError)
261 iState = EBeepPrepared;
265 static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers)
267 Qt::KeyboardModifiers result = Qt::NoModifier;
269 if (s60Modifiers & EModifierKeypad)
270 result |= Qt::KeypadModifier;
271 if (s60Modifiers & EModifierShift || s60Modifiers & EModifierLeftShift
272 || s60Modifiers & EModifierRightShift)
273 result |= Qt::ShiftModifier;
274 if (s60Modifiers & EModifierCtrl || s60Modifiers & EModifierLeftCtrl
275 || s60Modifiers & EModifierRightCtrl)
276 result |= Qt::ControlModifier;
277 if (s60Modifiers & EModifierAlt || s60Modifiers & EModifierLeftAlt
278 || s60Modifiers & EModifierRightAlt)
279 result |= Qt::AltModifier;
284 static void mapS60MouseEventTypeToQt(QEvent::Type *type, Qt::MouseButton *button, const TPointerEvent *pEvent)
286 switch (pEvent->iType) {
287 case TPointerEvent::EButton1Down:
288 *type = QEvent::MouseButtonPress;
289 *button = Qt::LeftButton;
291 case TPointerEvent::EButton1Up:
292 *type = QEvent::MouseButtonRelease;
293 *button = Qt::LeftButton;
295 case TPointerEvent::EButton2Down:
296 *type = QEvent::MouseButtonPress;
297 *button = Qt::MidButton;
299 case TPointerEvent::EButton2Up:
300 *type = QEvent::MouseButtonRelease;
301 *button = Qt::MidButton;
303 case TPointerEvent::EButton3Down:
304 *type = QEvent::MouseButtonPress;
305 *button = Qt::RightButton;
307 case TPointerEvent::EButton3Up:
308 *type = QEvent::MouseButtonRelease;
309 *button = Qt::RightButton;
311 case TPointerEvent::EDrag:
312 *type = QEvent::MouseMove;
313 *button = Qt::NoButton;
315 case TPointerEvent::EMove:
316 // Qt makes no distinction between move and drag
317 *type = QEvent::MouseMove;
318 *button = Qt::NoButton;
321 *type = QEvent::None;
322 *button = Qt::NoButton;
325 if (pEvent->iModifiers & EModifierDoubleClick){
326 *type = QEvent::MouseButtonDblClick;
329 if (*type == QEvent::MouseButtonPress || *type == QEvent::MouseButtonDblClick)
330 QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | (*button);
331 else if (*type == QEvent::MouseButtonRelease)
332 QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~(*button));
334 QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & Qt::MouseButtonMask;
337 //### Can be replaced with CAknLongTapDetector if animation is required.
338 //NOTE: if CAknLongTapDetector is used make sure it gets variated out of 3.1 and 3.2,.
339 //also MLongTapObserver needs to be changed to MAknLongTapDetectorCallBack if CAknLongTapDetector is used.
340 class QLongTapTimer : public CTimer
343 static QLongTapTimer* NewL(QAbstractLongTapObserver *observer);
344 QLongTapTimer(QAbstractLongTapObserver *observer);
347 void PointerEventL(const TPointerEvent &event);
351 QAbstractLongTapObserver *m_observer;
352 TPointerEvent m_event;
353 QPoint m_pressedCoordinates;
357 QLongTapTimer* QLongTapTimer::NewL(QAbstractLongTapObserver *observer)
359 QLongTapTimer* self = new QLongTapTimer(observer);
363 void QLongTapTimer::ConstructL()
365 CTimer::ConstructL();
368 QLongTapTimer::QLongTapTimer(QAbstractLongTapObserver *observer):CTimer(CActive::EPriorityHigh)
370 m_observer = observer;
371 m_dragDistance = qApp->startDragDistance();
372 CActiveScheduler::Add(this);
375 void QLongTapTimer::PointerEventL(const TPointerEvent& event)
377 if ( event.iType == TPointerEvent::EDrag || event.iType == TPointerEvent::EButtonRepeat)
379 QPoint diff(QPoint(event.iPosition.iX,event.iPosition.iY) - m_pressedCoordinates);
380 if (diff.manhattanLength() < m_dragDistance)
385 if (event.iType == TPointerEvent::EButton1Down)
387 m_pressedCoordinates = QPoint(event.iPosition.iX,event.iPosition.iY);
388 // must be same as KLongTapDelay in aknlongtapdetector.h
392 void QLongTapTimer::RunL()
395 m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition);
398 QSymbianControl::QSymbianControl(QWidget *w)
401 , m_longTapDetector(0)
402 , m_ignoreFocusChanged(0)
403 , m_symbianPopupIsOpen(0)
407 void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop)
411 if (isWindowOwning || !qwidget->parentWidget())
412 CreateWindowL(S60->windowGroup());
415 * TODO: in order to avoid creating windows for all ancestors of
416 * this widget up to the root window, the parameter passed to
417 * CreateWindowL should be
418 * qwidget->parentWidget()->effectiveWinId(). However, if we do
419 * this, then we need to take care of re-parenting when a window
420 * is created for a widget between this one and the root window.
422 CreateWindowL(qwidget->parentWidget()->winId());
424 // Necessary in order to be able to track the activation status of
425 // the control's window
426 qwidget->d_func()->createExtra();
429 m_longTapDetector = QLongTapTimer::NewL(this);
430 m_doubleClickTimer.invalidate();
432 DrawableWindow()->SetPointerGrab(ETrue);
435 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
437 TTfxWindowPurpose windowPurpose(ETfxPurposeNone);
438 switch (qwidget->windowType()) {
440 windowPurpose = ETfxPurposeDialogWindow;
443 windowPurpose = ETfxPurposePopupWindow;
446 windowPurpose = ETfxPurposeToolWindow;
449 windowPurpose = ETfxPurposeToolTipWindow;
451 case Qt::SplashScreen:
452 windowPurpose = ETfxPurposeSplashScreenWindow;
455 windowPurpose = (isWindowOwning || !qwidget->parentWidget())
456 ? ETfxPurposeWindow : ETfxPurposeChildWindow;
459 Window().SetPurpose(windowPurpose);
464 QSymbianControl::~QSymbianControl()
466 // Ensure backing store is deleted before the top-level
467 // window is destroyed
468 qt_widget_private(qwidget)->topData()->backingStore.destroy();
470 if (S60->curWin == this)
472 if (!QApplicationPrivate::is_app_closing) {
474 setFocusSafely(false);
475 } QT_CATCH(const std::exception&) {
476 // ignore exceptions, nothing can be done
479 S60->appUi()->RemoveFromStack(this);
480 delete m_longTapDetector;
483 void QSymbianControl::setWidget(QWidget *w)
487 void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation )
489 QWidget *alienWidget;
490 QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY);
491 QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY);
492 alienWidget = qwidget->childAt(widgetPos);
494 alienWidget = qwidget;
496 #if !defined(QT_NO_CONTEXTMENU)
497 QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, Qt::NoModifier);
498 qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent);
502 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
503 void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event)
505 QApplicationPrivate *d = QApplicationPrivate::instance();
506 QPointF screenPos = qwidget->mapToGlobal(QPoint(event->iPosition.iX, event->iPosition.iY));
508 if(d->pressureSupported
509 && event->Pressure() > 0) //workaround for misconfigured HAL
510 pressure = event->Pressure() / qreal(d->maxTouchPressure);
512 pressure = qreal(1.0);
513 processTouchEvent(event->PointerNumber(), event->iType, screenPos, pressure);
517 void QSymbianControl::processTouchEvent(int pointerNumber, TPointerEvent::TType type, QPointF screenPos, qreal pressure)
519 QRect screenGeometry = qApp->desktop()->screenGeometry(qwidget);
521 QApplicationPrivate *d = QApplicationPrivate::instance();
523 QList<QTouchEvent::TouchPoint> points = d->appAllTouchPoints;
524 while (points.count() <= pointerNumber)
525 points.append(QTouchEvent::TouchPoint(points.count()));
527 Qt::TouchPointStates allStates = 0;
528 for (int i = 0; i < points.count(); ++i) {
529 QTouchEvent::TouchPoint &touchPoint = points[i];
531 if (touchPoint.id() == pointerNumber) {
532 Qt::TouchPointStates state;
534 case TPointerEvent::EButton1Down:
535 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
536 case TPointerEvent::EEnterHighPressure:
538 state = Qt::TouchPointPressed;
540 case TPointerEvent::EButton1Up:
541 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
542 case TPointerEvent::EExitCloseProximity:
544 state = Qt::TouchPointReleased;
546 case TPointerEvent::EDrag:
547 state = Qt::TouchPointMoved;
550 // how likely is this to happen?
551 state = Qt::TouchPointStationary;
554 if (pointerNumber == 0)
555 state |= Qt::TouchPointPrimary;
556 touchPoint.setState(state);
558 touchPoint.setScreenPos(screenPos);
559 touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(),
560 screenPos.y() / screenGeometry.height()));
562 touchPoint.setPressure(pressure);
563 } else if (touchPoint.state() != Qt::TouchPointReleased) {
564 // all other active touch points should be marked as stationary
565 touchPoint.setState(Qt::TouchPointStationary);
568 allStates |= touchPoint.state();
571 if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) {
572 // all touch points released
573 d->appAllTouchPoints.clear();
575 d->appAllTouchPoints = points;
578 QApplicationPrivate::translateRawTouchEvent(qwidget,
579 QTouchEvent::TouchScreen,
583 void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent)
585 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
586 if (pEvent.IsAdvancedPointerEvent()) {
587 const TAdvancedPointerEvent *advancedPointerEvent = pEvent.AdvancedPointerEvent();
588 translateAdvancedPointerEvent(advancedPointerEvent);
589 if (advancedPointerEvent->PointerNumber() != 0) {
590 // only send mouse events for the first touch point
596 m_longTapDetector->PointerEventL(pEvent);
597 QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent));
600 void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
602 QMouseEvent::Type type;
603 Qt::MouseButton button;
604 mapS60MouseEventTypeToQt(&type, &button, &pEvent);
605 Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers);
607 QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
608 TPoint controlScreenPos = PositionRelativeToScreen();
609 QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
610 S60->lastCursorPos = globalPos;
611 S60->lastPointerEventPos = widgetPos;
613 QWidget *mouseGrabber = QWidget::mouseGrabber();
615 QWidget *popupWidget = qApp->activePopupWidget();
616 QWidget *popupReceiver = 0;
618 QWidget *popupChild = popupWidget->childAt(popupWidget->mapFromGlobal(globalPos));
619 popupReceiver = popupChild ? popupChild : popupWidget;
624 sendMouseEvent(popupReceiver, type, globalPos, button, modifiers);
626 sendMouseEvent(mouseGrabber, type, globalPos, button, modifiers);
628 // No Enter/Leave events in grabbing mode.
632 QWidget *widgetUnderPointer = qwidget->childAt(widgetPos);
633 if (!widgetUnderPointer)
634 widgetUnderPointer = qwidget;
636 QApplicationPrivate::dispatchEnterLeave(widgetUnderPointer, S60->lastPointerEventTarget);
637 S60->lastPointerEventTarget = widgetUnderPointer;
640 if (!popupReceiver && S60->mousePressTarget && type != QEvent::MouseButtonPress) {
641 receiver = S60->mousePressTarget;
642 if (type == QEvent::MouseButtonRelease)
643 S60->mousePressTarget = 0;
645 receiver = popupReceiver ? popupReceiver : widgetUnderPointer;
646 if (type == QEvent::MouseButtonPress)
647 S60->mousePressTarget = receiver;
650 #if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS)
651 if (S60->brokenPointerCursors)
652 qt_symbian_move_cursor_sprite();
655 //Generate single touch event for S60 5.0 (has touchscreen, does not have advanced pointers)
656 #ifndef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
657 if (S60->hasTouchscreen) {
658 processTouchEvent(0, pEvent.iType, QPointF(globalPos), 1.0);
662 sendMouseEvent(receiver, type, globalPos, button, modifiers);
666 void QSymbianControl::HandleStatusPaneSizeChange()
668 QS60MainAppUi *s60AppUi = static_cast<QS60MainAppUi *>(S60->appUi());
669 s60AppUi->HandleStatusPaneSizeChange();
673 void QSymbianControl::sendMouseEvent(
676 const QPoint &globalPos,
677 Qt::MouseButton button,
678 Qt::KeyboardModifiers modifiers)
681 QMouseEvent mEvent(type, receiver->mapFromGlobal(globalPos), globalPos,
682 button, QApplicationPrivate::mouse_buttons, modifiers);
683 QEventDispatcherS60 *dispatcher;
684 // It is theoretically possible for someone to install a different event dispatcher.
685 if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(receiver->d_func()->threadData->eventDispatcher)) != 0) {
686 if (dispatcher->excludeUserInputEvents()) {
687 dispatcher->saveInputEvent(this, receiver, new QMouseEvent(mEvent));
692 sendMouseEvent(receiver, &mEvent);
695 bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent)
697 return qt_sendSpontaneousEvent(widget, mEvent);
700 TKeyResponse QSymbianControl::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCode type)
702 TKeyResponse r = EKeyWasNotConsumed;
703 QT_TRYCATCH_LEAVING(r = OfferKeyEvent(keyEvent, type));
707 TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type)
710 S60 has a confusing way of delivering key events. There are three types of
711 events: EEventKey, EEventKeyDown and EEventKeyUp. When a key is pressed,
712 EEventKeyDown is first generated, followed by EEventKey. Then, when the key is
713 released, EEventKeyUp is generated.
714 However, it is possible that only the EEventKey is generated alone, typically
715 in relation to virtual keyboards. In that case we need to take care to
716 generate both press and release events in Qt, since applications expect that.
717 We do this by having three states for each used scan code, depending on the
718 events received. See the switch below for what happens in each state
722 if (type != EEventKeyDown)
723 if (handleVirtualMouse(keyEvent, type) == EKeyWasConsumed)
724 return EKeyWasConsumed;
726 TKeyResponse ret = EKeyWasNotConsumed;
727 #define GET_RETURN(x) (ret = ((x) == EKeyWasConsumed) ? EKeyWasConsumed : ret)
729 // This top level switch corresponds to the states, and the inner switches
730 // correspond to the transitions.
731 QS60Data::ScanCodeState &scanCodeState = S60->scanCodeStates[keyEvent.iScanCode];
732 switch (scanCodeState) {
733 case QS60Data::Unpressed:
736 scanCodeState = QS60Data::KeyDown;
739 GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress));
740 GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease));
747 case QS60Data::KeyDown:
750 // This should never happen, just stay in this state to be safe.
753 GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress));
754 scanCodeState = QS60Data::KeyDownAndKey;
757 scanCodeState = QS60Data::Unpressed;
761 case QS60Data::KeyDownAndKey:
764 // This should never happen, just stay in this state to be safe.
767 GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease));
768 GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress));
771 GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease));
772 scanCodeState = QS60Data::Unpressed;
782 TKeyResponse QSymbianControl::sendSymbianKeyEvent(const TKeyEvent &keyEvent, QEvent::Type type)
784 // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp
785 // events, we need to cache the keysyms from the EKeyEvent events. This is what
786 // resolveS60ScanCode does.
787 TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode,
790 if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used
791 keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode);
792 } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
793 // Normal characters keys.
797 keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym);
800 Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
801 QKeyEventEx qKeyEvent(type, keyCode, mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
802 (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
804 widget = QWidget::keyboardGrabber();
806 if (QApplicationPrivate::popupWidgets != 0) {
807 widget = QApplication::activePopupWidget()->focusWidget();
809 widget = QApplication::activePopupWidget();
812 widget = QApplicationPrivate::focus_widget;
819 QEventDispatcherS60 *dispatcher;
820 // It is theoretically possible for someone to install a different event dispatcher.
821 if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) {
822 if (dispatcher->excludeUserInputEvents()) {
823 dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent));
824 return EKeyWasConsumed;
827 return sendKeyEvent(widget, &qKeyEvent);
830 TKeyResponse QSymbianControl::handleVirtualMouse(const TKeyEvent& keyEvent,TEventCode type)
833 if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) {
834 //translate keys to pointer
835 if ((keyEvent.iScanCode >= EStdKeyLeftArrow && keyEvent.iScanCode <= EStdKeyDownArrow) ||
836 (keyEvent.iScanCode >= EStdKeyDevice10 && keyEvent.iScanCode <= EStdKeyDevice13) ||
837 keyEvent.iScanCode == EStdKeyDevice3) {
838 QPoint pos = QCursor::pos();
839 TPointerEvent fakeEvent;
840 fakeEvent.iType = (TPointerEvent::TType)(-1);
841 fakeEvent.iModifiers = keyEvent.iModifiers;
844 if (type == EEventKeyUp) {
845 S60->virtualMouseAccelTimeout.start();
846 switch (keyEvent.iScanCode) {
847 case EStdKeyLeftArrow:
848 S60->virtualMousePressedKeys &= ~QS60Data::Left;
850 case EStdKeyRightArrow:
851 S60->virtualMousePressedKeys &= ~QS60Data::Right;
854 S60->virtualMousePressedKeys &= ~QS60Data::Up;
856 case EStdKeyDownArrow:
857 S60->virtualMousePressedKeys &= ~QS60Data::Down;
859 // diagonal keys (named aliases don't exist in 3.1 SDK)
860 case EStdKeyDevice10:
861 S60->virtualMousePressedKeys &= ~QS60Data::LeftUp;
863 case EStdKeyDevice11:
864 S60->virtualMousePressedKeys &= ~QS60Data::RightUp;
866 case EStdKeyDevice12:
867 S60->virtualMousePressedKeys &= ~QS60Data::RightDown;
869 case EStdKeyDevice13:
870 S60->virtualMousePressedKeys &= ~QS60Data::LeftDown;
872 case EStdKeyDevice3: //select
873 if (S60->virtualMousePressedKeys & QS60Data::Select)
874 fakeEvent.iType = TPointerEvent::EButton1Up;
875 S60->virtualMousePressedKeys &= ~QS60Data::Select;
879 else if (type == EEventKey) {
882 if (keyEvent.iScanCode != EStdKeyDevice3) {
883 m_doubleClickTimer.invalidate();
884 //reset mouse accelleration after a short time with no moves
885 const int maxTimeBetweenKeyEventsMs = 500;
886 if (S60->virtualMouseAccelTimeout.isValid() &&
887 S60->virtualMouseAccelTimeout.hasExpired(maxTimeBetweenKeyEventsMs)) {
888 S60->virtualMouseAccelDX = 0;
889 S60->virtualMouseAccelDY = 0;
891 S60->virtualMouseAccelTimeout.invalidate();
893 switch (keyEvent.iScanCode) {
894 case EStdKeyLeftArrow:
895 S60->virtualMousePressedKeys |= QS60Data::Left;
897 fakeEvent.iType = TPointerEvent::EMove;
899 case EStdKeyRightArrow:
900 S60->virtualMousePressedKeys |= QS60Data::Right;
902 fakeEvent.iType = TPointerEvent::EMove;
905 S60->virtualMousePressedKeys |= QS60Data::Up;
907 fakeEvent.iType = TPointerEvent::EMove;
909 case EStdKeyDownArrow:
910 S60->virtualMousePressedKeys |= QS60Data::Down;
912 fakeEvent.iType = TPointerEvent::EMove;
914 case EStdKeyDevice10:
915 S60->virtualMousePressedKeys |= QS60Data::LeftUp;
918 fakeEvent.iType = TPointerEvent::EMove;
920 case EStdKeyDevice11:
921 S60->virtualMousePressedKeys |= QS60Data::RightUp;
924 fakeEvent.iType = TPointerEvent::EMove;
926 case EStdKeyDevice12:
927 S60->virtualMousePressedKeys |= QS60Data::RightDown;
930 fakeEvent.iType = TPointerEvent::EMove;
932 case EStdKeyDevice13:
933 S60->virtualMousePressedKeys |= QS60Data::LeftDown;
936 fakeEvent.iType = TPointerEvent::EMove;
939 // Platform bug. If you start pressing several keys simultaneously (for
940 // example for drag'n'drop), Symbian starts producing spurious up and
941 // down messages for some keys. Therefore, make sure we have a clean slate
942 // of pressed keys before starting a new button press.
943 if (S60->virtualMousePressedKeys & QS60Data::Select) {
944 return EKeyWasConsumed;
946 S60->virtualMousePressedKeys |= QS60Data::Select;
947 fakeEvent.iType = TPointerEvent::EButton1Down;
948 if (m_doubleClickTimer.isValid()
949 && !m_doubleClickTimer.hasExpired(QApplication::doubleClickInterval())) {
950 fakeEvent.iModifiers |= EModifierDoubleClick;
951 m_doubleClickTimer.invalidate();
953 m_doubleClickTimer.start();
959 int cdx = S60->virtualMouseAccelDX;
960 //reset accel on change of sign, else double accel
966 if (dx * cdx > S60->virtualMouseMaxAccel)
967 cdx = dx * S60->virtualMouseMaxAccel;
968 //move mouse position
970 S60->virtualMouseAccelDX = cdx;
974 int cdy = S60->virtualMouseAccelDY;
979 if (dy * cdy > S60->virtualMouseMaxAccel)
980 cdy = dy * S60->virtualMouseMaxAccel;
982 S60->virtualMouseAccelDY = cdy;
985 //clip to screen size (window server allows a sprite hotspot to be outside the screen)
988 else if (x >= S60->screenWidthInPixels)
989 x = S60->screenWidthInPixels - 1;
992 else if (y >= S60->screenHeightInPixels)
993 y = S60->screenHeightInPixels - 1;
995 TPoint cpos = epos - PositionRelativeToScreen();
996 fakeEvent.iPosition = cpos;
997 fakeEvent.iParentPosition = epos;
998 if(fakeEvent.iType != -1)
999 HandlePointerEvent(fakeEvent);
1000 return EKeyWasConsumed;
1005 return EKeyWasNotConsumed;
1008 void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent)
1010 switch (inputEvent->type()) {
1011 case QEvent::KeyPress:
1012 case QEvent::KeyRelease:
1013 sendKeyEvent(widget, static_cast<QKeyEvent *>(inputEvent));
1015 case QEvent::MouseButtonDblClick:
1016 case QEvent::MouseButtonPress:
1017 case QEvent::MouseButtonRelease:
1018 case QEvent::MouseMove:
1019 sendMouseEvent(widget, static_cast<QMouseEvent *>(inputEvent));
1022 // Shouldn't get here.
1023 Q_ASSERT_X(0 == 1, "QSymbianControl::sendInputEvent()", "inputEvent->type() is unknown");
1028 TKeyResponse QSymbianControl::sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent)
1030 #if !defined(QT_NO_IM) && defined(Q_WS_S60)
1031 if (widget && widget->isEnabled() && widget->testAttribute(Qt::WA_InputMethodEnabled)) {
1032 QInputContext *qic = widget->inputContext();
1033 if (qic && qic->filterEvent(keyEvent))
1034 return EKeyWasConsumed;
1036 #endif // !defined(QT_NO_IM) && defined(Q_OS_SYMBIAN)
1038 if (widget && qt_sendSpontaneousEvent(widget, keyEvent))
1039 if (keyEvent->isAccepted())
1040 return EKeyWasConsumed;
1042 return EKeyWasNotConsumed;
1045 #if !defined(QT_NO_IM) && defined(Q_WS_S60)
1046 TCoeInputCapabilities QSymbianControl::InputCapabilities() const
1050 if (qwidget->hasFocus())
1053 w = qwidget->focusWidget();
1055 QCoeFepInputContext *ic;
1056 if (w && w->isEnabled() && w->testAttribute(Qt::WA_InputMethodEnabled)
1057 && (ic = qobject_cast<QCoeFepInputContext *>(w->inputContext()))) {
1058 return ic->inputCapabilities();
1060 return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0);
1065 void QSymbianControl::Draw(const TRect& controlRect) const
1067 // Set flag to avoid calling DrawNow in window surface
1068 QWidget *window = qwidget->window();
1070 QTLWExtra *topExtra = window->d_func()->maybeTopData();
1072 if (!topExtra->inExpose) {
1073 topExtra->inExpose = true;
1074 if (!qwidget->isWindow()) {
1075 // If we get here, then it means we have a native child window
1076 // Since no content should ever be painted to these windows, we
1077 // erase them with a transparent brush when they get an expose.
1078 CWindowGc &gc = SystemGc();
1079 gc.SetBrushColor(TRgb(0, 0, 0, 0));
1080 gc.Clear(controlRect);
1082 QRect exposeRect = qt_TRect2QRect(controlRect);
1083 qwidget->d_func()->syncBackingStore(exposeRect);
1084 topExtra->inExpose = false;
1087 QWindowSurface *surface = qwidget->windowSurface();
1088 QPaintEngine *engine = surface ? surface->paintDevice()->paintEngine() : NULL;
1093 const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents;
1094 if (sendNativePaintEvents) {
1095 const QRect r = qt_TRect2QRect(controlRect);
1096 QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r));
1099 // Map source rectangle into coordinates of the backing store.
1100 const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY);
1101 const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase);
1102 const TRect backingStoreRect(TPoint(backingStoreBase.x(), backingStoreBase.y()), controlRect.Size());
1104 if (engine->type() == QPaintEngine::Raster) {
1105 QS60WindowSurface *s60Surface;
1106 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
1107 if (QApplicationPrivate::runtime_graphics_system) {
1108 QRuntimeWindowSurface *rtSurface =
1109 static_cast<QRuntimeWindowSurface*>(qwidget->windowSurface());
1110 s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface.data());
1113 s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
1115 CFbsBitmap *bitmap = s60Surface->symbianBitmap();
1116 CWindowGc &gc = SystemGc();
1118 QWExtra::NativePaintMode nativePaintMode = qwidget->d_func()->extraData()->nativePaintMode;
1119 if(qwidget->d_func()->paintOnScreen())
1120 nativePaintMode = QWExtra::Disable;
1122 switch(nativePaintMode) {
1123 case QWExtra::Disable:
1127 if (qwidget->d_func()->isOpaque)
1128 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
1129 gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
1131 case QWExtra::ZeroFill:
1132 if (Window().DisplayMode() == EColor16MA
1133 || Window().DisplayMode() == Q_SYMBIAN_ECOLOR16MAP) {
1134 gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
1135 gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
1136 gc.SetBrushColor(TRgb::Color16MA(0));
1137 gc.Clear(controlRect);
1139 gc.SetBrushColor(TRgb(0x000000));
1140 gc.Clear(controlRect);
1148 if (sendNativePaintEvents) {
1149 const QRect r = qt_TRect2QRect(controlRect);
1150 // The draw ops aren't actually sent to WSERV until the graphics
1151 // context is deactivated, which happens in the function calling
1152 // this one. We therefore delay the delivery of endNativePaintEvent,
1153 // to ensure that drawing has completed by the time the widget
1154 // receives the event. Note that, if the widget needs to ensure
1155 // that the draw ops have actually been executed into the output
1156 // framebuffer, a call to RWsSession::Flush is required in the
1157 // endNativePaintEvent implementation.
1158 QMetaObject::invokeMethod(qwidget, "endNativePaintEvent", Qt::QueuedConnection, Q_ARG(QRect, r));
1162 void QSymbianControl::SizeChanged()
1164 CCoeControl::SizeChanged();
1166 QSize oldSize = qwidget->size();
1167 QSize newSize(Size().iWidth, Size().iHeight);
1169 if (oldSize != newSize) {
1170 QRect cr = qwidget->geometry();
1171 cr.setSize(newSize);
1172 qwidget->data->crect = cr;
1173 if (qwidget->isVisible()) {
1174 QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData();
1175 bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
1176 if (!slowResize && tlwExtra)
1177 tlwExtra->inTopLevelResize = true;
1178 QResizeEvent e(newSize, oldSize);
1179 qt_sendSpontaneousEvent(qwidget, &e);
1180 if (!qwidget->testAttribute(Qt::WA_StaticContents))
1181 qwidget->d_func()->syncBackingStore();
1182 if (!slowResize && tlwExtra)
1183 tlwExtra->inTopLevelResize = false;
1185 if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) {
1186 QResizeEvent *e = new QResizeEvent(newSize, oldSize);
1187 QApplication::postEvent(qwidget, e);
1192 // CCoeControl::SetExtent calls SizeChanged, but does not call
1193 // PositionChanged, so we call it here to ensure that the widget's
1194 // position is updated.
1198 void QSymbianControl::PositionChanged()
1200 CCoeControl::PositionChanged();
1202 QPoint oldPos = qwidget->geometry().topLeft();
1203 QPoint newPos(Position().iX, Position().iY);
1205 if (oldPos != newPos) {
1206 QRect cr = qwidget->geometry();
1207 cr.moveTopLeft(newPos);
1208 qwidget->data->crect = cr;
1209 QTLWExtra *top = qwidget->d_func()->maybeTopData();
1210 if (top && (qwidget->windowState() & (~Qt::WindowActive)) == Qt::WindowNoState)
1211 top->normalGeometry.moveTopLeft(newPos);
1212 if (qwidget->isVisible()) {
1213 QMoveEvent e(newPos, oldPos);
1214 qt_sendSpontaneousEvent(qwidget, &e);
1216 QMoveEvent * e = new QMoveEvent(newPos, oldPos);
1217 QApplication::postEvent(qwidget, e);
1222 void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
1224 if (m_ignoreFocusChanged || (qwidget->windowType() & Qt::WindowType_Mask) == Qt::Desktop)
1227 // Popups never get focused, but still receive the FocusChanged when they are hidden.
1228 if (QApplicationPrivate::popupWidgets != 0
1229 || (qwidget->windowType() & Qt::Popup) == Qt::Popup)
1232 if (IsFocused() && IsVisible()) {
1233 if (m_symbianPopupIsOpen) {
1234 QWidget *fw = QApplication::focusWidget();
1236 QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason);
1237 QCoreApplication::sendEvent(fw, &event);
1239 m_symbianPopupIsOpen = false;
1242 QApplication::setActiveWindow(qwidget->window());
1243 qwidget->d_func()->setWindowIcon_sys(true);
1244 qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
1246 if (qwidget->isWindow()) {
1247 QWidget *const window = qwidget->window();
1248 QWidget *parentWindow = window->parentWidget();
1250 while (parentWindow->parentWidget())
1251 parentWindow = parentWindow->parentWidget();
1253 parentWindow = window;
1256 const bool parentDecorationsVisible = !(parentWindow->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
1257 const bool parentIsFullscreen = parentWindow->windowState() & Qt::WindowFullScreen;
1258 const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint;
1259 bool buttonGroupVisibility = (parentDecorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint));
1261 // For non-toplevel normal and maximized windows, show cba if window has softkey
1262 // actions even if topmost parent is not showing cba. Do the same for fullscreen
1263 // windows that request it.
1264 if (!buttonGroupVisibility
1265 && window->parentWidget()
1266 && !(window->windowState() & Qt::WindowMinimized)
1267 && ((window->windowFlags() & Qt::WindowSoftkeysVisibleHint) || !(window->windowState() & Qt::WindowFullScreen))) {
1268 for (int i = 0; i < window->actions().size(); ++i) {
1269 if (window->actions().at(i)->softKeyRole() != QAction::NoSoftKey) {
1270 buttonGroupVisibility = true;
1275 S60->setStatusPaneAndButtonGroupVisibility(parentDecorationsVisible, buttonGroupVisibility);
1278 } else if (QApplication::activeWindow() == qwidget->window()) {
1279 bool focusedControlFound = false;
1281 for (QWidget *w = qwidget->parentWidget(); w && (winId = w->internalWinId()); w = w->parentWidget()) {
1282 if (winId->IsFocused() && winId->IsVisible()) {
1283 focusedControlFound = true;
1285 } else if (w->isWindow())
1288 if (!focusedControlFound) {
1289 if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) {
1290 QWidget *fw = QApplication::focusWidget();
1292 QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
1293 QCoreApplication::sendEvent(fw, &event);
1295 m_symbianPopupIsOpen = true;
1299 QApplication::setActiveWindow(0);
1302 // else { We don't touch the active window unless we were explicitly activated or deactivated }
1305 void QSymbianControl::handleClientAreaChange()
1307 const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
1308 if (qwidget->isFullScreen() && !cbaVisibilityHint) {
1309 SetExtentToWholeScreen();
1310 } else if (qwidget->isMaximized() || (qwidget->isFullScreen() && cbaVisibilityHint)) {
1311 TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
1312 SetExtent(r.iTl, r.Size());
1313 } else if (!qwidget->isMinimized()) { // Normal geometry
1314 if (!qwidget->testAttribute(Qt::WA_Resized)) {
1315 qwidget->adjustSize();
1316 qwidget->setAttribute(Qt::WA_Resized, false); //not a user resize
1318 if (!qwidget->testAttribute(Qt::WA_Moved) && qwidget->windowType() != Qt::Dialog) {
1319 TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
1321 qwidget->setAttribute(Qt::WA_Moved, false); // not really an explicit position
1326 void QSymbianControl::HandleResourceChange(int resourceType)
1328 switch (resourceType) {
1329 case KInternalStatusPaneChange:
1330 handleClientAreaChange();
1331 if (IsFocused() && IsVisible()) {
1332 qwidget->d_func()->setWindowIcon_sys(true);
1333 qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
1336 case KUidValueCoeFontChangeEvent:
1337 // font change event
1340 case KEikDynamicLayoutVariantSwitch:
1342 handleClientAreaChange();
1343 // Send resize event to trigger desktopwidget workAreaResized signal
1344 QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size());
1345 QApplication::sendEvent(qt_desktopWidget, &e);
1353 CCoeControl::HandleResourceChange(resourceType);
1356 void QSymbianControl::CancelLongTapTimer()
1358 m_longTapDetector->Cancel();
1361 TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id)
1363 if (id.iUid == ETypeId)
1364 return id.MakePtr(this);
1366 return CCoeControl::MopSupplyObject(id);
1369 void QSymbianControl::setFocusSafely(bool focus)
1371 // The stack hack in here is very unfortunate, but it is the only way to ensure proper
1372 // focus in Symbian. If this is not executed, the control which happens to be on
1373 // the top of the stack may randomly be assigned focus by Symbian, for example
1374 // when creating new windows (specifically in CCoeAppUi::HandleStackChanged()).
1376 // Close any popups.
1377 CEikonEnv::Static()->EikAppUi()->StopDisplayingMenuBar();
1380 S60->appUi()->RemoveFromStack(this);
1381 // Symbian doesn't automatically remove focus from the last focused control, so we need to
1382 // remember it and clear focus ourselves.
1383 if (lastFocusedControl && lastFocusedControl != this)
1384 lastFocusedControl->SetFocus(false);
1385 QT_TRAP_THROWING(S60->appUi()->AddToStackL(this,
1386 ECoeStackPriorityDefault + 1, ECoeStackFlagStandard)); // Note the + 1
1387 lastFocusedControl = this;
1388 this->SetFocus(true);
1390 S60->appUi()->RemoveFromStack(this);
1391 QT_TRAP_THROWING(S60->appUi()->AddToStackL(this,
1392 ECoeStackPriorityDefault, ECoeStackFlagStandard));
1393 if(this == lastFocusedControl)
1394 lastFocusedControl = 0;
1395 this->SetFocus(false);
1399 bool QSymbianControl::isControlActive()
1401 return IsActivated() ? true : false;
1405 \typedef QApplication::QS60MainApplicationFactory
1408 This is a typedef for a pointer to a function with the following
1411 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 47
1413 \sa QApplication::QApplication()
1419 Creates an application using the application factory given in
1420 \a factory, and using \a argc command line arguments in \a argv.
1421 \a factory can be leaving, but the error will be converted to a
1424 This function is only available on S60.
1426 QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv)
1427 : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
1430 S60->s60ApplicationFactory = factory;
1434 QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal)
1435 : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
1438 S60->s60ApplicationFactory = factory;
1440 QApplicationPrivate::app_compile_version = _internal;
1443 void qt_init(QApplicationPrivate * /* priv */, int)
1445 if (!CCoeEnv::Static()) {
1446 // The S60 framework creates a new trap handler which will render any existing traps
1447 // invalid as long as it is active. This means that all code in main() that occurs after
1448 // the QApplication construction needs to be surrounded by a new trap, despite having
1449 // an outer one already. To avoid this, we save the original trap handler here, and set
1450 // it back after the S60 framework is constructed. Then we restore it right before the S60
1451 // framework destruction.
1452 TTrapHandler *origTrapHandler = User::TrapHandler();
1454 // The S60 framework has not been initialized. We need to do it.
1455 TApaApplicationFactory factory(S60->s60ApplicationFactory ?
1456 S60->s60ApplicationFactory : newS60Application);
1457 CApaCommandLine* commandLine = 0;
1458 TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine);
1459 // After this construction, CEikonEnv will be available from CEikonEnv::Static().
1460 // (much like our qApp).
1461 QtEikonEnv* coe = new QtEikonEnv;
1462 //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there.
1464 TRAP(err, coe->ConstructAppFromCommandLineL(factory,*commandLine));
1466 if(err != KErrNone) {
1467 qWarning() << "qt_init: Eikon application construct failed ("
1469 << "), maybe missing resource file on S60 3.1?";
1471 qt_symbian_throwIfError(err);
1474 S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler);
1476 S60->qtOwnsS60Environment = true;
1478 S60->qtOwnsS60Environment = false;
1482 if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty())
1484 S60->wsSession().SetAutoFlush(ETrue);
1486 #ifdef Q_SYMBIAN_WINDOW_SIZE_CACHE
1487 TRAP_IGNORE(S60->wsSession().EnableWindowSizeCacheL());
1490 S60->updateScreenSize();
1493 TDisplayMode mode = S60->screenDevice()->DisplayMode();
1494 S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode);
1496 //NB: RWsSession::GetColorModeList tells you what window modes are supported,
1497 //not what bitmap formats.
1498 if(QSysInfo::symbianVersion() == QSysInfo::SV_9_2)
1499 S60->supportsPremultipliedAlpha = 0;
1501 S60->supportsPremultipliedAlpha = 1;
1504 TSecureId securId = me.SecureId();
1505 S60->uid = securId.operator TUid();
1507 // enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app,
1508 // and for dimming behind modal windows
1509 S60->windowGroup().EnableFocusChangeEvents();
1511 //Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this)
1512 const TInt KMachineUidSamsungI8510 = 0x2000C51E;
1513 // HAL::Get(HALData::EPen, TInt& result) may set 'result' to 1 on some 3.1 systems (e.g. N95).
1514 // But we know that S60 systems below 5.0 did not support touch.
1515 static const bool touchIsUnsupportedOnSystem =
1516 QSysInfo::s60Version() == QSysInfo::SV_S60_3_1
1517 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2;
1522 err = HAL::Get(HALData::EMouse, mouse);
1523 if (err != KErrNone)
1525 err = HAL::Get(HALData::EMachineUid, machineUID);
1526 if (err != KErrNone)
1528 err = HAL::Get(HALData::EPen, touch);
1529 if (err != KErrNone || touchIsUnsupportedOnSystem)
1532 if(QSysInfo::symbianVersion() <= QSysInfo::SV_9_4) {
1533 //for symbian SDK emulator, force values to match typical devices.
1535 touch = touchIsUnsupportedOnSystem ? 0 : 1;
1538 if (mouse || machineUID == KMachineUidSamsungI8510) {
1539 S60->hasTouchscreen = false;
1540 S60->virtualMouseRequired = false;
1543 S60->hasTouchscreen = false;
1544 S60->virtualMouseRequired = true;
1547 S60->hasTouchscreen = true;
1548 S60->virtualMouseRequired = false;
1551 S60->avkonComponentsSupportTransparency = false;
1552 S60->menuBeingConstructed = false;
1555 TUid KCRUidAvkon = { 0x101F876E };
1556 TUint32 KAknAvkonTransparencyEnabled = 0x0000000D;
1558 CRepository* repository = 0;
1559 TRAP(err, repository = CRepository::NewL(KCRUidAvkon));
1561 if(err == KErrNone) {
1563 err = repository->Get(KAknAvkonTransparencyEnabled, value);
1564 if(err == KErrNone) {
1565 S60->avkonComponentsSupportTransparency = (value==1) ? true : false;
1572 #ifdef QT_KEYPAD_NAVIGATION
1574 QApplicationPrivate::navigationMode = Qt::NavigationModeNone;
1576 QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional;
1580 #ifndef QT_NO_CURSOR
1581 //Check if window server pointer cursors are supported or not
1582 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
1583 //In generic binary, use the HAL and OS version
1584 //Any other known good phones should be added here.
1585 if (machineUID == KMachineUidSamsungI8510 || (QSysInfo::symbianVersion() != QSysInfo::SV_9_4
1586 && QSysInfo::symbianVersion() != QSysInfo::SV_9_3 && QSysInfo::symbianVersion()
1587 != QSysInfo::SV_9_2)) {
1588 S60->brokenPointerCursors = false;
1589 qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup());
1592 S60->brokenPointerCursors = true;
1595 if (S60->mouseInteractionEnabled) {
1596 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
1597 if (S60->brokenPointerCursors) {
1598 qt_symbian_set_pointer_sprite(Qt::ArrowCursor);
1599 qt_symbian_show_pointer_sprite();
1603 S60->wsSession().SetPointerCursorMode(EPointerCursorNormal);
1608 systemFont.setFamily(systemFont.defaultFamily());
1609 QApplicationPrivate::setSystemFont(systemFont);
1611 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
1612 QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit()));
1616 ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag
1617 int argc = priv->argc;
1618 char **argv = priv->argv;
1620 // Get command line params
1621 int j = argc ? 1 : 0;
1622 for (int i=1; i<argc; i++) {
1623 if (argv[i] && *argv[i] != '-') {
1624 argv[j++] = argv[i];
1628 #if defined(QT_DEBUG)
1629 if (qstrcmp(argv[i], "-nograb") == 0)
1630 appNoGrab = !appNoGrab;
1637 // Register WId with the metatype system. This is to enable
1638 // QWidgetPrivate::create_sys to used delayed slot invocation in order
1639 // to destroy WId objects during reparenting.
1640 qRegisterMetaType<WId>("WId");
1643 extern void qt_cleanup_symbianFontDatabase(); // qfontdatabase_s60.cpp
1645 /*****************************************************************************
1646 qt_cleanup() - cleans up when the application is finished
1647 *****************************************************************************/
1654 QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
1655 QPixmapCache::clear(); // Has to happen now, since QS60PixmapData has FBS handles
1657 qt_cleanup_symbianFontDatabase();
1658 // S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
1660 // It's important that this happens here, before the event dispatcher gets
1661 // deleted, because the input context needs the event loop one last time before
1663 delete QApplicationPrivate::inputContext;
1664 QApplicationPrivate::inputContext = 0;
1666 //Change mouse pointer back
1667 S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
1671 CEikonEnv::Static()->AppUiFactory()->SwapButtonGroup(0);
1672 delete S60->buttonGroupContainer();
1673 S60->setButtonGroupContainer(0);
1676 if (S60->qtOwnsS60Environment) {
1677 // Restore the S60 framework trap handler. See qt_init().
1678 User::SetTrapHandler(S60->s60InstalledTrapHandler);
1680 CEikonEnv* coe = CEikonEnv::Static();
1681 coe->PrepareToExit();
1682 // The CEikonEnv itself is destroyed in here.
1683 coe->DestroyEnvironment();
1687 void QApplicationPrivate::initializeWidgetPaletteHash()
1689 // TODO: Implement QApplicationPrivate::initializeWidgetPaletteHash()
1690 // Possibly a task fot the S60Style guys
1693 void QApplicationPrivate::createEventDispatcher()
1696 eventDispatcher = new QEventDispatcherS60(q);
1699 QString QApplicationPrivate::appName() const
1701 return QCoreApplicationPrivate::appName();
1704 bool QApplicationPrivate::modalState()
1706 return app_do_modal;
1709 void QApplicationPrivate::enterModal_sys(QWidget *widget)
1711 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
1712 S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeEnter);
1715 static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue);
1716 // Modal partial screen dialogs (like queries) capture pointer events.
1717 // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
1718 widget->effectiveWinId()->SetGloballyCapturing(ETrue);
1719 widget->effectiveWinId()->SetPointerCapture(ETrue);
1721 if (!qt_modal_stack)
1722 qt_modal_stack = new QWidgetList;
1723 qt_modal_stack->insert(0, widget);
1724 app_do_modal = true;
1727 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
1729 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
1730 S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeExit);
1733 static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse);
1734 // ### FixMe: Add specialized behaviour for fullscreen modal dialogs
1735 widget->effectiveWinId()->SetGloballyCapturing(EFalse);
1736 widget->effectiveWinId()->SetPointerCapture(EFalse);
1738 if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
1739 if (qt_modal_stack->isEmpty()) {
1740 delete qt_modal_stack;
1744 app_do_modal = qt_modal_stack != 0;
1747 void QApplicationPrivate::openPopup(QWidget *popup)
1749 if (popup && qobject_cast<QComboBox *>(popup->parentWidget()))
1750 static_cast<QSymbianControl *>(popup->effectiveWinId())->FadeBehindPopup(ETrue);
1752 if (!QApplicationPrivate::popupWidgets)
1753 QApplicationPrivate::popupWidgets = new QWidgetList;
1754 QApplicationPrivate::popupWidgets->append(popup);
1756 // Cancel focus widget pointer capture and long tap timer
1757 if (QApplication::focusWidget()) {
1758 static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer();
1759 QApplication::focusWidget()->effectiveWinId()->SetPointerCapture(false);
1763 // Cancel pointer capture and long tap timer for earlier popup
1764 int popupCount = QApplicationPrivate::popupWidgets->count();
1765 if (popupCount > 1) {
1766 QWidget* prevPopup = QApplicationPrivate::popupWidgets->at(popupCount-2);
1767 static_cast<QSymbianControl*>(prevPopup->effectiveWinId())->CancelLongTapTimer();
1768 prevPopup->effectiveWinId()->SetPointerCapture(false);
1771 // Enable pointer capture for this (topmost) popup
1772 Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
1773 WId id = popup->effectiveWinId();
1774 id->SetPointerCapture(true);
1777 // popups are not focus-handled by the window system (the first
1778 // popup grabbed the keyboard), so we have to do that manually: A
1779 // new popup gets the focus
1780 QWidget *fw = popup->focusWidget();
1782 fw->setFocus(Qt::PopupFocusReason);
1783 } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
1784 fw = QApplication::focusWidget();
1786 QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
1787 q_func()->sendEvent(fw, &e);
1792 void QApplicationPrivate::closePopup(QWidget *popup)
1794 if (popup && qobject_cast<QComboBox *>(popup->parentWidget()))
1795 static_cast<QSymbianControl *>(popup->effectiveWinId())->FadeBehindPopup(EFalse);
1797 if (!QApplicationPrivate::popupWidgets)
1799 QApplicationPrivate::popupWidgets->removeAll(popup);
1801 // Cancel pointer capture and long tap for this popup
1802 WId id = popup->effectiveWinId();
1803 id->SetPointerCapture(false);
1804 static_cast<QSymbianControl*>(id)->CancelLongTapTimer();
1806 if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
1807 delete QApplicationPrivate::popupWidgets;
1808 QApplicationPrivate::popupWidgets = 0;
1809 if (!qt_nograb()) { // grabbing not disabled
1810 Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
1811 if (QWidgetPrivate::mouseGrabber != 0)
1812 QWidgetPrivate::mouseGrabber->grabMouse();
1814 if (QWidgetPrivate::keyboardGrabber != 0)
1815 QWidgetPrivate::keyboardGrabber->grabKeyboard();
1817 QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
1818 : q_func()->focusWidget();
1820 if(fw->window()->isModal()) // restore pointer capture for modal window
1821 fw->effectiveWinId()->SetPointerCapture(true);
1823 if (fw != q_func()->focusWidget()) {
1824 fw->setFocus(Qt::PopupFocusReason);
1826 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
1827 q_func()->sendEvent(fw, &e);
1833 // popups are not focus-handled by the window system (the
1834 // first popup grabbed the keyboard), so we have to do that
1835 // manually: A popup was closed, so the previous popup gets
1837 QWidget* aw = QApplicationPrivate::popupWidgets->last();
1838 if (QWidget *fw = QApplication::focusWidget()) {
1839 QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
1840 q_func()->sendEvent(fw, &e);
1843 // Enable pointer capture for previous popup
1845 aw->effectiveWinId()->SetPointerCapture(true);
1850 QWidget * QApplication::topLevelAt(QPoint const& point)
1853 int lowestZ = INT_MAX;
1854 QWidgetList list = QApplication::topLevelWidgets();
1855 for (int i = 0; i < list.count(); ++i) {
1856 QWidget *widget = list.at(i);
1857 if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) {
1858 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
1859 if (widget->geometry().adjusted(0,0,1,1).contains(point)) {
1860 // At this point we know there is a Qt widget under the point.
1861 // Now we need to make sure it is the top most in the z-order.
1862 RDrawableWindow *const window = widget->effectiveWinId()->DrawableWindow();
1863 int z = window->OrdinalPosition();
1874 void QApplication::alert(QWidget * /* widget */, int /* duration */)
1876 // TODO: Implement QApplication::alert(QWidget *widget, int duration)
1879 int QApplication::doubleClickInterval()
1881 TTimeIntervalMicroSeconds32 us;
1883 S60->wsSession().GetDoubleClickSettings(us, distance);
1884 return (us.Int() / 1000);
1887 void QApplication::setDoubleClickInterval(int ms)
1889 TTimeIntervalMicroSeconds32 newUs( ms * 1000);
1890 TTimeIntervalMicroSeconds32 us;
1892 S60->wsSession().GetDoubleClickSettings(us, distance);
1894 S60->wsSession().SetDoubleClick(newUs, distance);
1897 int QApplication::keyboardInputInterval()
1899 return QApplicationPrivate::keyboard_input_time;
1902 void QApplication::setKeyboardInputInterval(int ms)
1904 QApplicationPrivate::keyboard_input_time = ms;
1907 int QApplication::cursorFlashTime()
1909 return QApplicationPrivate::cursor_flash_time;
1912 void QApplication::setCursorFlashTime(int msecs)
1914 QApplicationPrivate::cursor_flash_time = msecs;
1917 void QApplication::beep()
1920 TInt frequency = 880;
1921 TTimeIntervalMicroSeconds duration(500000);
1922 TRAP_IGNORE(qt_S60Beep=QS60Beep::NewL(frequency, duration));
1928 static inline bool callSymbianEventFilters(const QSymbianEvent *event)
1931 return qApp->filterEvent(const_cast<QSymbianEvent *>(event), &unused);
1935 \warning This function is only available on Symbian.
1938 This function processes an individual Symbian event
1939 \a event. It returns 1 if the event was handled, 0 if
1940 the \a event was not handled, and -1 if the event was
1941 not handled because the event is not known to Qt.
1944 int QApplication::symbianProcessEvent(const QSymbianEvent *event)
1948 QScopedLoopLevelCounter counter(d->threadData);
1950 if (d->eventDispatcher->filterEvent(const_cast<QSymbianEvent *>(event)))
1953 QWidget *w = qApp ? qApp->focusWidget() : 0;
1955 QInputContext *ic = w->inputContext();
1956 if (ic && ic->symbianFilterEvent(w, event))
1960 if (symbianEventFilter(event))
1963 switch (event->type()) {
1964 case QSymbianEvent::WindowServerEvent:
1965 return d->symbianProcessWsEvent(event);
1966 case QSymbianEvent::CommandEvent:
1967 return d->symbianHandleCommand(event);
1968 case QSymbianEvent::ResourceChangeEvent:
1969 return d->symbianResourceChange(event);
1975 int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent)
1977 // Qt event handling. Handle some events regardless of if the handle is in our
1978 // widget map or not.
1979 const TWsEvent *event = symbianEvent->windowServerEvent();
1980 CCoeControl* control = reinterpret_cast<CCoeControl*>(event->Handle());
1981 const bool controlInMap = QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control);
1982 switch (event->Type()) {
1983 case EEventPointerEnter:
1985 callSymbianEventFilters(symbianEvent);
1986 return 1; // Qt::Enter will be generated in HandlePointerL
1989 case EEventPointerExit:
1991 if (callSymbianEventFilters(symbianEvent))
1994 // mouseEvent outside our window, send leave event to last focused widget
1995 QMouseEvent mEvent(QEvent::Leave, S60->lastPointerEventPos, S60->lastCursorPos,
1996 Qt::NoButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
1997 if (S60->lastPointerEventTarget)
1998 qt_sendSpontaneousEvent(S60->lastPointerEventTarget,&mEvent);
1999 S60->lastPointerEventTarget = 0;
2004 case EEventScreenDeviceChanged:
2005 if (callSymbianEventFilters(symbianEvent))
2008 S60->updateScreenSize();
2009 if (qt_desktopWidget) {
2010 QSize oldSize = qt_desktopWidget->size();
2011 qt_desktopWidget->data->crect.setWidth(S60->screenWidthInPixels);
2012 qt_desktopWidget->data->crect.setHeight(S60->screenHeightInPixels);
2013 QResizeEvent e(qt_desktopWidget->size(), oldSize);
2014 QApplication::sendEvent(qt_desktopWidget, &e);
2016 return 0; // Propagate to CONE
2017 case EEventWindowVisibilityChanged:
2019 if (callSymbianEventFilters(symbianEvent))
2021 const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged();
2022 if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible)
2023 S60->controlVisibilityChanged(control, false);
2024 else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
2025 S60->controlVisibilityChanged(control, true);
2029 case EEventFocusGained:
2030 if (callSymbianEventFilters(symbianEvent))
2032 #ifndef QT_NO_CURSOR
2033 //re-enable mouse interaction
2034 if (S60->mouseInteractionEnabled) {
2035 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
2036 if (S60->brokenPointerCursors)
2037 qt_symbian_show_pointer_sprite();
2040 S60->wsSession().SetPointerCursorMode(EPointerCursorNormal);
2043 #ifdef QT_SOFTKEYS_ENABLED
2044 QSoftKeyManager::updateSoftKeys();
2047 case EEventFocusLost:
2048 if (callSymbianEventFilters(symbianEvent))
2050 #ifndef QT_NO_CURSOR
2051 //disable mouse as may be moving to application that does not support it
2052 if (S60->mouseInteractionEnabled) {
2053 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
2054 if (S60->brokenPointerCursors)
2055 qt_symbian_hide_pointer_sprite();
2058 S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
2062 case KGoomMemoryLowEvent:
2064 qDebug() << "QApplicationPrivate::symbianProcessWsEvent - KGoomMemoryLowEvent";
2066 if (callSymbianEventFilters(symbianEvent))
2068 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
2069 if(QApplicationPrivate::runtime_graphics_system) {
2070 bool switchToSwRendering(false);
2072 foreach (QWidget *w, QApplication::topLevelWidgets()) {
2073 if(w->d_func()->topData()->backingStore) {
2074 switchToSwRendering = true;
2079 if (switchToSwRendering) {
2080 QRuntimeGraphicsSystem *gs =
2081 static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
2082 gs->setGraphicsSystem(QLatin1String("raster"));
2087 case KGoomMemoryGoodEvent:
2089 qDebug() << "QApplicationPrivate::symbianProcessWsEvent - KGoomMemoryGoodEvent";
2091 if (callSymbianEventFilters(symbianEvent))
2093 #ifdef QT_GRAPHICSSYSTEM_RUNTIME
2094 if(QApplicationPrivate::runtime_graphics_system) {
2095 QRuntimeGraphicsSystem *gs =
2096 static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
2097 gs->setGraphicsSystem(QLatin1String("openvg"));
2101 #ifdef Q_SYMBIAN_SUPPORTS_SURFACES
2104 // GOOM is looking for candidates to kill so indicate that we are
2105 // capable of cleaning up by handling this event
2106 TInt32 *data = reinterpret_cast<TInt32 *>(event->EventData());
2107 if (data[0] == EApaSystemEventShutdown && data[1] == KGoomMemoryLowEvent)
2123 \warning This virtual function is only available on Symbian.
2126 If you create an application that inherits QApplication and reimplement
2127 this function, you get direct access to events that the are received
2128 from Symbian. The events are passed in the \a event parameter.
2130 Return true if you want to stop the event from being processed. Return
2131 false for normal event dispatching. The default implementation returns
2132 false, and does nothing with \a event.
2134 bool QApplication::symbianEventFilter(const QSymbianEvent *event)
2141 \warning This function is only available on Symbian.
2144 Handles \a{command}s which are typically handled by
2145 CAknAppUi::HandleCommandL(). Qts Ui integration into Symbian is
2146 partially achieved by deriving from CAknAppUi. Currently, exit,
2147 menu and softkey commands are handled.
2149 \sa s60EventFilter(), s60ProcessEvent()
2151 int QApplicationPrivate::symbianHandleCommand(const QSymbianEvent *symbianEvent)
2156 if (callSymbianEventFilters(symbianEvent))
2159 int command = symbianEvent->command();
2163 case EAknSoftkeyExit: {
2165 QApplication::sendSpontaneousEvent(q, &ev);
2166 if (ev.isAccepted()) {
2179 bool handled = QSoftKeyManager::handleCommand(command);
2183 ret = QMenuBarPrivate::symbianCommands(command);
2192 \warning This function is only available on Symbian.
2195 Handles the resource change specified by \a type.
2197 Currently, KEikDynamicLayoutVariantSwitch and
2198 KAknsMessageSkinChange are handled.
2200 int QApplicationPrivate::symbianResourceChange(const QSymbianEvent *symbianEvent)
2204 int type = symbianEvent->resourceChangeType();
2208 case KEikDynamicLayoutVariantSwitch:
2210 if (callSymbianEventFilters(symbianEvent))
2213 S60->updateScreenSize();
2215 #ifndef QT_NO_STYLE_S60
2216 QS60Style *s60Style = 0;
2218 #ifndef QT_NO_STYLE_STYLESHEET
2219 QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplication::style());
2221 s60Style = qobject_cast<QS60Style*>(proxy->baseStyle());
2224 s60Style = qobject_cast<QS60Style*>(QApplication::style());
2227 s60Style->d_func()->handleDynamicLayoutVariantSwitch();
2234 #ifndef QT_NO_STYLE_S60
2235 case KAknsMessageSkinChange:
2236 if (callSymbianEventFilters(symbianEvent))
2238 if (QS60Style *s60Style = qobject_cast<QS60Style*>(QApplication::style())) {
2239 s60Style->d_func()->handleSkinChange();
2252 #ifndef QT_NO_WHEELEVENT
2253 int QApplication::wheelScrollLines()
2255 return QApplicationPrivate::wheel_scroll_lines;
2258 void QApplication::setWheelScrollLines(int n)
2260 QApplicationPrivate::wheel_scroll_lines = n;
2262 #endif //QT_NO_WHEELEVENT
2264 bool QApplication::isEffectEnabled(Qt::UIEffect /* effect */)
2266 // TODO: Implement QApplication::isEffectEnabled(Qt::UIEffect effect)
2270 void QApplication::setEffectEnabled(Qt::UIEffect /* effect */, bool /* enable */)
2272 // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
2275 TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym)
2280 QApplicationPrivate *d = QApplicationPrivate::instance();
2283 // If keysym is specified, cache it.
2284 d->scanCodeCache.insert(scanCode, keysym);
2287 // If not, retrieve the cached version.
2288 return d->scanCodeCache[scanCode];
2292 void QApplicationPrivate::initializeMultitouch_sys()
2294 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
2295 if (HAL::Get(HALData::EPointer3DPressureSupported, pressureSupported) != KErrNone)
2296 pressureSupported = 0;
2297 if (HAL::Get(HALData::EPointer3DMaxPressure, maxTouchPressure) != KErrNone)
2298 maxTouchPressure = KMaxTInt;
2300 pressureSupported = 0;
2301 maxTouchPressure = KMaxTInt;
2305 void QApplicationPrivate::cleanupMultitouch_sys()
2308 #ifndef QT_NO_SESSIONMANAGER
2309 QSessionManager::QSessionManager(QApplication * /* app */, QString & /* id */, QString& /* key */)
2314 QSessionManager::~QSessionManager()
2319 bool QSessionManager::allowsInteraction()
2324 void QSessionManager::cancel()
2328 #endif //QT_NO_SESSIONMANAGER
2330 #ifdef QT_KEYPAD_NAVIGATION
2332 * Show/Hide the mouse cursor depending on phone type and chosen mode
2334 void QApplicationPrivate::setNavigationMode(Qt::NavigationMode mode)
2336 #ifndef QT_NO_CURSOR
2337 const bool wasCursorOn = (QApplicationPrivate::navigationMode == Qt::NavigationModeCursorAuto
2338 && !S60->hasTouchscreen)
2339 || QApplicationPrivate::navigationMode == Qt::NavigationModeCursorForceVisible;
2340 const bool isCursorOn = (mode == Qt::NavigationModeCursorAuto
2341 && !S60->hasTouchscreen)
2342 || mode == Qt::NavigationModeCursorForceVisible;
2344 if (!wasCursorOn && isCursorOn) {
2345 //Show the cursor, when changing from another mode to cursor mode
2346 qt_symbian_set_cursor_visible(true);
2348 else if (wasCursorOn && !isCursorOn) {
2349 //Hide the cursor, when leaving cursor mode
2350 qt_symbian_set_cursor_visible(false);
2353 QApplicationPrivate::navigationMode = mode;
2357 #ifndef QT_NO_CURSOR
2358 /*****************************************************************************
2359 QApplication cursor stack
2360 *****************************************************************************/
2362 void QApplication::setOverrideCursor(const QCursor &cursor)
2364 qApp->d_func()->cursor_list.prepend(cursor);
2365 qt_symbian_setGlobalCursor(cursor);
2368 void QApplication::restoreOverrideCursor()
2370 if (qApp->d_func()->cursor_list.isEmpty())
2372 qApp->d_func()->cursor_list.removeFirst();
2374 if (!qApp->d_func()->cursor_list.isEmpty()) {
2375 qt_symbian_setGlobalCursor(qApp->d_func()->cursor_list.first());
2378 //determine which widget has focus
2379 QWidget *w = QApplication::widgetAt(QCursor::pos());
2380 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
2381 if (S60->brokenPointerCursors) {
2382 qt_symbian_set_pointer_sprite(w ? w->cursor() : Qt::ArrowCursor);
2387 //because of the internals of window server, we need to force the cursor
2388 //to be set in all child windows too, otherwise when the cursor is over
2389 //the child window it may show a widget cursor or arrow cursor instead,
2390 //depending on construction order.
2391 QListIterator<WId> iter(QWidgetPrivate::mapper->uniqueKeys());
2392 while (iter.hasNext()) {
2393 CCoeControl *ctrl = iter.next();
2394 if(ctrl->OwnsWindow()) {
2395 ctrl->DrawableWindow()->ClearPointerCursor();
2399 qt_symbian_setWindowCursor(w->cursor(), w->effectiveWinId());
2401 qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup());
2406 #endif // QT_NO_CURSOR
2408 void QApplicationPrivate::_q_aboutToQuit()
2410 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
2411 // Send the shutdown tfx command
2412 S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown);
2416 QS60ThreadLocalData::QS60ThreadLocalData()
2418 CCoeEnv *env = CCoeEnv::Static();
2420 //if this is the UI thread, share objects owned by CONE
2421 usingCONEinstances = true;
2422 wsSession = env->WsSession();
2423 screenDevice = env->ScreenDevice();
2426 usingCONEinstances = false;
2427 qt_symbian_throwIfError(wsSession.Connect(qt_s60GetRFs()));
2428 screenDevice = new CWsScreenDevice(wsSession);
2429 screenDevice->Construct();
2433 QS60ThreadLocalData::~QS60ThreadLocalData()
2435 if (!usingCONEinstances) {
2436 delete screenDevice;