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