Cleaned up position tracking in the Symbian input methods.
[qt:kde-qt.git] / src / gui / kernel / qt_s60_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 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 module 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 #ifndef QT_S60_P_H
43 #define QT_S60_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "QtGui/qwindowdefs.h"
57 #include "private/qcore_symbian_p.h"
58 #include "qhash.h"
59 #include "qpoint.h"
60 #include "QtGui/qfont.h"
61 #include "QtGui/qimage.h"
62 #include "QtGui/qevent.h"
63 #include "qpointer.h"
64 #include "qapplication.h"
65 #include "qelapsedtimer.h"
66 #include "QtCore/qthreadstorage.h"
67 #include <w32std.h>
68 #include <coecntrl.h>
69 #include <eikenv.h>
70 #include <eikappui.h>
71
72 #ifdef Q_WS_S60
73 #include <AknUtils.h>               // AknLayoutUtils
74 #include <avkon.hrh>                // EEikStatusPaneUidTitle
75 #include <akntitle.h>               // CAknTitlePane
76 #include <akncontext.h>             // CAknContextPane
77 #include <eikspane.h>               // CEikStatusPane
78 #include <AknPopupFader.h>          // MAknFadedComponent and TAknPopupFader
79 #endif
80
81 QT_BEGIN_NAMESPACE
82
83 // Application internal HandleResourceChangeL events,
84 // system events seems to start with 0x10
85 const TInt KInternalStatusPaneChange = 0x50000000;
86
87 //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2
88 #define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13)
89
90 class Q_AUTOTEST_EXPORT QS60ThreadLocalData
91 {
92 public:
93     QS60ThreadLocalData();
94     ~QS60ThreadLocalData();
95     bool usingCONEinstances;
96     RWsSession wsSession;
97     CWsScreenDevice *screenDevice;
98 };
99
100 class QS60Data
101 {
102 public:
103     QS60Data();
104     QThreadStorage<QS60ThreadLocalData *> tls;
105     TUid uid;
106     int screenDepth;
107     QPoint lastCursorPos;
108     QPoint lastPointerEventPos;
109     QPointer<QWidget> lastPointerEventTarget;
110     QPointer<QWidget> mousePressTarget;
111     int screenWidthInPixels;
112     int screenHeightInPixels;
113     int screenWidthInTwips;
114     int screenHeightInTwips;
115     int defaultDpiX;
116     int defaultDpiY;
117     WId curWin;
118     enum PressedKeys {
119         Select = 0x1,
120         Right = 0x2,
121         Down = 0x4,
122         Left = 0x8,
123         Up = 0x10,
124         LeftUp = 0x20,
125         RightUp = 0x40,
126         RightDown = 0x80,
127         LeftDown = 0x100
128     };
129     int virtualMousePressedKeys; // of the above type, but avoids casting problems
130     int virtualMouseAccelDX;
131     int virtualMouseAccelDY;
132     QElapsedTimer virtualMouseAccelTimeout;
133     int virtualMouseMaxAccel;
134 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
135     int brokenPointerCursors : 1;
136 #endif
137     int hasTouchscreen : 1;
138     int mouseInteractionEnabled : 1;
139     int virtualMouseRequired : 1;
140     int qtOwnsS60Environment : 1;
141     int supportsPremultipliedAlpha : 1;
142     int avkonComponentsSupportTransparency : 1;
143     int menuBeingConstructed : 1;
144     QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type
145
146     enum ScanCodeState {
147         Unpressed,
148         KeyDown,
149         KeyDownAndKey
150     };
151     QHash<TInt, ScanCodeState> scanCodeStates;
152
153     static inline void updateScreenSize();
154     inline RWsSession& wsSession();
155     static inline RWindowGroup& windowGroup();
156     inline CWsScreenDevice* screenDevice();
157     static inline CCoeAppUi* appUi();
158     static inline CEikMenuBar* menuBar();
159 #ifdef Q_WS_S60
160     static inline CEikStatusPane* statusPane();
161     static inline CCoeControl* statusPaneSubPane(TInt aPaneId);
162     static inline CAknTitlePane* titlePane();
163     static inline CAknContextPane* contextPane();
164     static inline CEikButtonGroupContainer* buttonGroupContainer();
165     static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible);
166 #endif
167     static void controlVisibilityChanged(CCoeControl *control, bool visible);
168
169 #ifdef Q_OS_SYMBIAN
170     TTrapHandler *s60InstalledTrapHandler;
171 #endif
172 };
173
174 Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data();
175 #define S60 qGlobalS60Data()
176
177 class QAbstractLongTapObserver
178 {
179 public:
180     virtual void HandleLongTapEventL( const TPoint& aPenEventLocation,
181                                       const TPoint& aPenEventScreenLocation ) = 0;
182 };
183 class QLongTapTimer;
184
185
186 class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver
187 #ifdef Q_WS_S60
188 , public MAknFadedComponent, public MEikStatusPaneObserver
189 #endif
190 {
191 public:
192     DECLARE_TYPE_ID(0x51740000) // Fun fact: the two first values are "Qt" in ASCII.
193
194 public:
195     QSymbianControl(QWidget *w);
196     void ConstructL(bool isWindowOwning = false, bool desktop = false);
197     ~QSymbianControl();
198     void HandleResourceChange(int resourceType);
199     void HandlePointerEventL(const TPointerEvent& aPointerEvent);
200     TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
201 #if !defined(QT_NO_IM) && defined(Q_WS_S60)
202     TCoeInputCapabilities InputCapabilities() const;
203 #endif
204     TTypeUid::Ptr MopSupplyObject(TTypeUid id);
205
206     inline QWidget* widget() const { return qwidget; }
207     void setWidget(QWidget *w);
208     void sendInputEvent(QWidget *widget, QInputEvent *inputEvent);
209     void setIgnoreFocusChanged(bool enabled) { m_ignoreFocusChanged = enabled; }
210     void CancelLongTapTimer();
211
212     void setFocusSafely(bool focus);
213
214 #ifdef Q_WS_S60
215     void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); }
216     void HandleStatusPaneSizeChange();
217
218 protected: // from MAknFadedComponent
219     TInt CountFadedComponents() {return 1;}
220     CCoeControl* FadedComponent(TInt /*aIndex*/) {return this;}
221 #else
222     // #warning No fallback implementation for QSymbianControl::FadeBehindPopup
223     void FadeBehindPopup(bool /*fade*/){ }
224 #endif
225
226 protected:
227     void Draw(const TRect& aRect) const;
228     void SizeChanged();
229     void PositionChanged();
230     void FocusChanged(TDrawNow aDrawNow);
231
232 private:
233     void HandlePointerEvent(const TPointerEvent& aPointerEvent);
234     TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType);
235     TKeyResponse sendSymbianKeyEvent(const TKeyEvent &keyEvent, QEvent::Type type);
236     TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent);
237     TKeyResponse handleVirtualMouse(const TKeyEvent& keyEvent,TEventCode type);
238     bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent);
239     void sendMouseEvent(
240             QWidget *receiver,
241             QEvent::Type type,
242             const QPoint &globalPos,
243             Qt::MouseButton button,
244             Qt::KeyboardModifiers modifiers);
245     void processTouchEvent(int pointerNumber, TPointerEvent::TType type, QPointF screenPos, qreal pressure);
246     void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation );
247 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
248     void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event);
249 #endif
250
251 public:
252     void handleClientAreaChange();
253
254 private:
255     static QSymbianControl *lastFocusedControl;
256
257 private:
258     QWidget *qwidget;
259     QLongTapTimer* m_longTapDetector;
260     QElapsedTimer m_doubleClickTimer;
261     bool m_ignoreFocusChanged : 1;
262     bool m_symbianPopupIsOpen : 1;
263
264 #ifdef Q_WS_S60
265     // Fader object used to fade everything except this menu and the CBA.
266     TAknPopupFader popupFader;
267 #endif
268 };
269
270 inline QS60Data::QS60Data()
271 : uid(TUid::Null()),
272   screenDepth(0),
273   screenWidthInPixels(0),
274   screenHeightInPixels(0),
275   screenWidthInTwips(0),
276   screenHeightInTwips(0),
277   defaultDpiX(0),
278   defaultDpiY(0),
279   curWin(0),
280   virtualMousePressedKeys(0),
281   virtualMouseAccelDX(0),
282   virtualMouseAccelDY(0),
283   virtualMouseMaxAccel(0),
284 #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
285   brokenPointerCursors(0),
286 #endif
287   hasTouchscreen(0),
288   mouseInteractionEnabled(0),
289   virtualMouseRequired(0),
290   qtOwnsS60Environment(0),
291   supportsPremultipliedAlpha(0),
292   avkonComponentsSupportTransparency(0),
293   menuBeingConstructed(0),
294   s60ApplicationFactory(0)
295 #ifdef Q_OS_SYMBIAN
296   ,s60InstalledTrapHandler(0)
297 #endif
298 {
299 }
300
301 inline void QS60Data::updateScreenSize()
302 {
303     TPixelsTwipsAndRotation params;
304     int mode = S60->screenDevice()->CurrentScreenMode();
305     S60->screenDevice()->GetScreenModeSizeAndRotation(mode, params);
306     S60->screenWidthInPixels = params.iPixelSize.iWidth;
307     S60->screenHeightInPixels = params.iPixelSize.iHeight;
308     S60->screenWidthInTwips = params.iTwipsSize.iWidth;
309     S60->screenHeightInTwips = params.iTwipsSize.iHeight;
310
311     S60->virtualMouseMaxAccel = qMax(S60->screenHeightInPixels, S60->screenWidthInPixels) / 10;
312
313     TReal inches = S60->screenHeightInTwips / (TReal)KTwipsPerInch;
314     S60->defaultDpiY = S60->screenHeightInPixels / inches;
315     inches = S60->screenWidthInTwips / (TReal)KTwipsPerInch;
316     S60->defaultDpiX = S60->screenWidthInPixels / inches;
317 }
318
319 inline RWsSession& QS60Data::wsSession()
320 {
321     if(!tls.hasLocalData()) {
322         tls.setLocalData(new QS60ThreadLocalData);
323     }
324     return tls.localData()->wsSession;
325 }
326
327 inline RWindowGroup& QS60Data::windowGroup()
328 {
329     return CCoeEnv::Static()->RootWin();
330 }
331
332 inline CWsScreenDevice* QS60Data::screenDevice()
333 {
334     if(!tls.hasLocalData()) {
335         tls.setLocalData(new QS60ThreadLocalData);
336     }
337     return tls.localData()->screenDevice;
338 }
339
340 inline CCoeAppUi* QS60Data::appUi()
341 {
342     return CCoeEnv::Static()-> AppUi();
343 }
344
345 inline CEikMenuBar* QS60Data::menuBar()
346 {
347     return CEikonEnv::Static()->AppUiFactory()->MenuBar();
348 }
349
350 #ifdef Q_WS_S60
351 inline CEikStatusPane* QS60Data::statusPane()
352 {
353     return CEikonEnv::Static()->AppUiFactory()->StatusPane();
354 }
355
356 // Returns the application's status pane control, if not present returns NULL.
357 inline CCoeControl* QS60Data::statusPaneSubPane( TInt aPaneId )
358 {
359     const TUid paneUid = { aPaneId };
360     CEikStatusPane* statusPane = S60->statusPane();
361     if (statusPane && statusPane->PaneCapabilities(paneUid).IsPresent()) {
362         CCoeControl* control = NULL;
363         // ControlL shouldn't leave because the pane is present
364         TRAPD(err, control = statusPane->ControlL(paneUid));
365         return err != KErrNone ? NULL : control;
366     }
367     return NULL;
368 }
369
370 // Returns the application's title pane, if not present returns NULL.
371 inline CAknTitlePane* QS60Data::titlePane()
372 {
373     return static_cast<CAknTitlePane*>(S60->statusPaneSubPane(EEikStatusPaneUidTitle));
374 }
375
376 // Returns the application's title pane, if not present returns NULL.
377 inline CAknContextPane* QS60Data::contextPane()
378 {
379     return static_cast<CAknContextPane*>(S60->statusPaneSubPane(EEikStatusPaneUidContext));
380 }
381
382 inline CEikButtonGroupContainer* QS60Data::buttonGroupContainer()
383 {
384     return CEikonEnv::Static()->AppUiFactory()->Cba();
385 }
386 #endif // Q_WS_S60
387
388 static inline QFont qt_TFontSpec2QFontL(const TFontSpec &fontSpec)
389 {
390     return QFont(
391         qt_TDesC2QString(fontSpec.iTypeface.iName),
392         fontSpec.iHeight / KTwipsPerPoint,
393         fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightNormal ? QFont::Normal : QFont::Bold,
394         fontSpec.iFontStyle.Posture() == EPostureItalic
395     );
396 }
397
398 static inline QImage::Format qt_TDisplayMode2Format(TDisplayMode mode)
399 {
400     QImage::Format format;
401     switch(mode) {
402     case EGray2:
403         format = QImage::Format_MonoLSB;
404         break;
405     case EColor256:
406     case EGray256:
407         format = QImage::Format_Indexed8;
408         break;
409     case EColor4K:
410         format = QImage::Format_RGB444;
411         break;
412     case EColor64K:
413         format = QImage::Format_RGB16;
414         break;
415     case EColor16M:
416         format = QImage::Format_RGB888;
417         break;
418     case EColor16MU:
419         format = QImage::Format_RGB32;
420         break;
421     case EColor16MA:
422         format = QImage::Format_ARGB32;
423         break;
424     case Q_SYMBIAN_ECOLOR16MAP:
425         format = QImage::Format_ARGB32_Premultiplied;
426         break;
427     default:
428         format = QImage::Format_Invalid;
429         break;
430     }
431     return format;
432 }
433
434 #ifndef QT_NO_CURSOR
435 void qt_symbian_setWindowCursor(const QCursor &cursor, const CCoeControl* wid);
436 void qt_symbian_setWindowGroupCursor(const QCursor &cursor, RWindowTreeNode &node);
437 void qt_symbian_setGlobalCursor(const QCursor &cursor);
438 void qt_symbian_set_cursor_visible(bool visible);
439 bool qt_symbian_is_cursor_visible();
440 #endif
441
442 QT_END_NAMESPACE
443
444 #endif // QT_S60_P_H