source: trunk/src/gui/kernel/qapplication_s60.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

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