Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Inside Qt for Symbian QApplication/zh: Difference between revisions
No edit summary |
No edit summary |
||
Line 3: | Line 3: | ||
== Qt for Symbian之程序启动 == | == Qt for Symbian之程序启动 == | ||
我们都知道Qt中只要构造出QApplication就启动了,可启动细节就很少有人知道了,当然我们编写Qt的程序无需关心这么多,这也是为什么要用Qt的原因,但如果能够了解则可以加深对Qt的认识。今天看了一下Qt for Symbian的源码,整理如下,希望对有兴趣的朋友有帮助: | 我们都知道Qt中只要构造出QApplication就启动了,可启动细节就很少有人知道了,当然我们编写Qt的程序无需关心这么多,这也是为什么要用Qt的原因,但如果能够了解则可以加深对Qt的认识。今天看了一下Qt for Symbian的源码,整理如下,希望对有兴趣的朋友有帮助: | ||
<code>QApplication::QApplication(int &argc, char **argv) | |||
: QCoreApplication('''new QApplicationPrivate(argc, argv, GuiClient) //第一步) //第二步 | |||
{ | |||
Q_D(QApplication); //第三步 | |||
d->construct(); //第四步 | |||
}</code> | |||
第一步构造了QApplicationPrivate的实例,其中GuiClient是一个枚举常量,表示应用程序的类型,这里我们不用关心。说道 QApplicationPrivate,如果你看过Qt的源码,你会发现很多类都配对有相应的Private类,这是Qt在封装底层实现时经常用的一种模式,Handle-Body Design Pattern,也就是说你在xx类中看不到具体的实现,具体的实现都封装在xxPrivate类中,而在xx类的方法只是调用xxPrivate中相应的方法。 | |||
第二步用QApplicationPrivate的实例构造了QCoreApplication,这里调用的是QCoreApplication的QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)构造函数,代码如下: | |||
<code>QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p) | |||
: QObject(p, 0) | |||
{ | |||
init(); | |||
// note: it is the subclasses' job to call | |||
// QCoreApplicationPrivate::eventDispatcher->startingUp(); | |||
}</code> | |||
上面代码中的init初始化了一些资源,其中包括事件分发器。 | |||
第三步定义了d,这里是通过宏Q_D来实现的,其中宏Q_D的定义如下: | |||
<code>#define Q_D(Class) Class##Private''' const d = d_func()<code> | |||
所以这里的d即是调用父类构造函数QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)时创建的QApplicationPrivate实例。 | |||
第四步调用d的construct函数,也就是QApplicationPrivate的实例的construct函数。代码如下所示: | |||
</code>void QApplicationPrivate::construct( | |||
#ifdef Q_WS_X11 | |||
Display *dpy, Qt::HANDLE visual, Qt::HANDLE cmap | |||
#endif | |||
) | |||
{ | |||
initResources(); | |||
qt_is_gui_used = (qt_appType != QApplication::Tty); | |||
process_cmdline(); | |||
// the environment variable has the lowest precedence of runtime graphicssystem switches | |||
if (graphics_system_name.isEmpty()) | |||
graphics_system_name = QString::fromLocal8Bit(qgetenv("QT_GRAPHICSSYSTEM")); | |||
// Must be called before initialize() | |||
//这里调用了qt_init | |||
qt_init(this, qt_appType | |||
#ifdef Q_WS_X11 | |||
, dpy, visual, cmap | |||
#endif | |||
); | |||
initialize(); | |||
eventDispatcher->startingUp(); | |||
#ifndef QT_NO_LIBRARY | #ifdef QT_EVAL | ||
extern void qt_gui_eval_init(uint); | |||
qt_gui_eval_init(application_type); | |||
#endif | |||
#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE) | |||
symbianInit(); | |||
#endif | |||
#ifndef QT_NO_LIBRARY | |||
if(load_testability) { | |||
QLibrary testLib(QLatin1String("qttestability")); | |||
if (testLib.load()) { | |||
typedef void ('''TasInitialize)(void); | |||
TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init"); | |||
if (initFunction) { | |||
initFunction(); | |||
} else { | |||
qCritical("Library qttestability resolve failed!"); | |||
} | |||
} else { | |||
qCritical("Library qttestability load failed!"); | |||
} | |||
} | |||
//make sure the plugin is loaded | |||
if (qt_is_gui_used) | |||
qt_guiPlatformPlugin(); | |||
#endif | |||
}<code> | |||
这里也是初始化了很多资源,其中要要说的是qt_init,因为就是它创建了程序,代码如下: | |||
</code>void qt_init(QApplicationPrivate''' /* priv */, int) | |||
{ | |||
if (!CCoeEnv::Static()) { | |||
// The S60 framework creates a new trap handler which will render any existing traps | |||
// invalid as long as it is active. This means that all code in main() that occurs after | |||
// the QApplication construction needs to be surrounded by a new trap, despite having | |||
// an outer one already. To avoid this, we save the original trap handler here, and set | |||
// it back after the S60 framework is constructed. Then we restore it right before the S60 | |||
// framework destruction. | |||
TTrapHandler '''origTrapHandler = User::TrapHandler(); | |||
// The S60 framework has not been initialized. We need to do it. | |||
//这里就是创建程序的地方 | |||
TApaApplicationFactory factory(S60->s60ApplicationFactory ? | |||
S60->s60ApplicationFactory : newS60Application); | |||
CApaCommandLine''' commandLine = 0; | |||
TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine); | |||
// After this construction, CEikonEnv will be available from CEikonEnv::Static(). | |||
// (much like our qApp). | |||
CEikonEnv* coe = new CEikonEnv; | |||
//not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there. | |||
if(err == KErrNone) | |||
TRAP (err, coe->ConstructAppFromCommandLineL(factory,*commandLine)); //这里通过factory创建了程序 | |||
delete commandLine; | |||
if(err != KErrNone) { | |||
qWarning() << "qt_init: Eikon application construct failed (" | |||
<< err | |||
<< "), maybe missing resource file on S60 3.1?"; | |||
delete coe; | |||
qt_symbian_throwIfError(err); | |||
} | |||
S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler); | S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler); | ||
S60->qtOwnsS60Environment = true; | S60->qtOwnsS60Environment = true; | ||
} else { | |||
S60->qtOwnsS60Environment = false; | |||
} | |||
#ifdef QT_NO_DEBUG | #ifdef QT_NO_DEBUG | ||
if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty()) | |||
#endif | |||
S60->wsSession().SetAutoFlush(ETrue); | |||
#ifdef Q_SYMBIAN_WINDOW_SIZE_CACHE | #ifdef Q_SYMBIAN_WINDOW_SIZE_CACHE | ||
TRAP_IGNORE(S60->wsSession().EnableWindowSizeCacheL()); | |||
#endif | |||
S60->updateScreenSize(); | S60->updateScreenSize(); | ||
TDisplayMode mode = S60->screenDevice()->DisplayMode(); | TDisplayMode mode = S60->screenDevice()->DisplayMode(); | ||
S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode); | |||
//NB: RWsSession::GetColorModeList tells you what window modes are supported, | //NB: RWsSession::GetColorModeList tells you what window modes are supported, | ||
//not what bitmap formats. | |||
if(QSysInfo::symbianVersion() == QSysInfo::SV_9_2) | |||
S60->supportsPremultipliedAlpha = 0; | |||
else | |||
S60->supportsPremultipliedAlpha = 1; | |||
RProcess me; | RProcess me; | ||
TSecureId securId = me.SecureId(); | |||
S60->uid = securId.operator TUid(); | |||
// enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app, | // enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app, | ||
// and for dimming behind modal windows | |||
S60->windowGroup().EnableFocusChangeEvents(); | |||
//Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this) | //Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this) | ||
|| QSysInfo::s60Version() QSysInfo::SV_S60_3_2; | const TInt KMachineUidSamsungI8510 = 0x2000C51E; | ||
// HAL::Get(HALData::EPen, TInt&amp; result) may set 'result' to 1 on some 3.1 systems (e.g. N95). | |||
// But we know that S60 systems below 5.0 did not support touch. | |||
static const bool touchIsUnsupportedOnSystem = | |||
QSysInfo::s60Version() QSysInfo::SV_S60_3_1 | |||
|| QSysInfo::s60Version() QSysInfo::SV_S60_3_2; | |||
TInt machineUID; | |||
TInt mouse; | |||
TInt touch; | |||
TInt err; | |||
err = HAL::Get(HALData::EMouse, mouse); | |||
if (err != KErrNone) | |||
mouse = 0; | |||
err = HAL::Get(HALData::EMachineUid, machineUID); | |||
if (err != KErrNone) | |||
machineUID = 0; | |||
err = HAL::Get(HALData::EPen, touch); | |||
if (err != KErrNone || touchIsUnsupportedOnSystem) | |||
touch = 0; | |||
#ifdef ''WINS'' | |||
if(QSysInfo::symbianVersion() <= QSysInfo::SV_9_4) { | |||
//for symbian SDK emulator, force values to match typical devices. | |||
mouse = 0; | |||
touch = touchIsUnsupportedOnSystem ? 0 : 1; | |||
} | |||
#endif | |||
if (mouse || machineUID == KMachineUidSamsungI8510) { | |||
S60->hasTouchscreen = false; | |||
S60->virtualMouseRequired = false; | |||
} | |||
else if (!touch) { | |||
S60->hasTouchscreen = false; | |||
S60->virtualMouseRequired = true; | |||
} | |||
else { | |||
S60->hasTouchscreen = true; | |||
S60->virtualMouseRequired = false; | |||
} | |||
S60->avkonComponentsSupportTransparency = false; | S60->avkonComponentsSupportTransparency = false; | ||
S60->menuBeingConstructed = false; | |||
#ifdef Q_WS_S60 | #ifdef Q_WS_S60 | ||
TUid KCRUidAvkon = { 0x101F876E }; | |||
TUint32 KAknAvkonTransparencyEnabled = 0x0000000D; | |||
CRepository* repository = 0; | CRepository* repository = 0; | ||
TRAP (err, repository = CRepository::NewL(KCRUidAvkon)); | |||
if(err KErrNone) { | if(err KErrNone) { | ||
TInt value = 0; | TInt value = 0; | ||
err = repository->Get(KAknAvkonTransparencyEnabled, value); | err = repository->Get(KAknAvkonTransparencyEnabled, value); | ||
if(err KErrNone) { | if(err KErrNone) { | ||
S60->avkonComponentsSupportTransparency = (value==1) ? true : false; | |||
} | |||
} | |||
delete repository; | |||
repository = 0; | |||
#endif | |||
#ifdef QT_KEYPAD_NAVIGATION | |||
if (touch) { | |||
QApplicationPrivate::navigationMode = Qt::NavigationModeNone; | |||
} else { | |||
QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; | |||
} | |||
#endif | |||
# | #ifndef QT_NO_CURSOR | ||
//Check if window server pointer cursors are supported or not | |||
#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS | |||
//In generic binary, use the HAL and OS version | |||
//Any other known good phones should be added here. | |||
if (machineUID == KMachineUidSamsungI8510 || (QSysInfo::symbianVersion() != QSysInfo::SV_9_4 | |||
&& QSysInfo::symbianVersion() != QSysInfo::SV_9_3 && QSysInfo::symbianVersion() | |||
!= QSysInfo::SV_9_2)) { | |||
S60->brokenPointerCursors = false; | |||
qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup()); | |||
} | |||
else | |||
S60->brokenPointerCursors = true; | |||
#endif | |||
if (S60->mouseInteractionEnabled) { | |||
#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS | |||
if (S60->brokenPointerCursors) { | |||
qt_symbian_set_pointer_sprite(Qt::ArrowCursor); | |||
qt_symbian_show_pointer_sprite(); | |||
} | |||
else | |||
#endif | |||
S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); | |||
} | |||
#endif | |||
QFont systemFont; | |||
systemFont.setFamily(systemFont.defaultFamily()); | |||
QApplicationPrivate::setSystemFont(systemFont); | |||
#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS | |||
QObject::connect(qApp, SIGNAL (aboutToQuit()), qApp, SLOT (_q_aboutToQuit())); | |||
#endif | |||
# | /* | ||
### Commented out for now as parameter handling not needed in SOS (yet). Code below will break testlib with -o flag | |||
int argc = priv->argc; | |||
char **argv = priv->argv; | |||
/ | // Get command line params | ||
int j = argc ? 1 : 0; | |||
for (int i=1; i<argc; i+'') { | |||
if (argv[i] && *argv[i] != '-') { | |||
argv[j''+] = argv[i]; | |||
continue; | |||
} | |||
#if defined(QT_DEBUG) | |||
if (qstrcmp(argv[i], "-nograb") == 0) | |||
appNoGrab = !appNoGrab; | |||
else | |||
#endif // QT_DEBUG | |||
; | |||
} | |||
*/ | |||
// Register WId with the metatype system. This is to enable | |||
// QWidgetPrivate::create_sys to used delayed slot invocation in order | |||
// to destroy WId objects during reparenting. | |||
qRegisterMetaType<WId>("WId"); | |||
}<code> | |||
代码很多,哈哈。上面代码中标有注释“这里就是创建程序的地方” 的部分: | |||
</code>TApaApplicationFactory factory(S60->s60ApplicationFactory ? | |||
S60->s60ApplicationFactory : newS60Application);<code> | |||
这里将newS60Application赋值给S60->s60ApplicationFactory,而newS60Application是什么呢,我们看看它的定义: | |||
</code>CApaApplication '''newS60Application() | |||
{ | |||
return new QS60MainApplication; | |||
}<code> | |||
由此可知newS60Application就是一个函数指针,它创建了一个QS60MainApplication实例,这里QS60MainApplication类封装了CAknApplication的实现。 | |||
另外上面代码中s60是一个全局数据,里面放了很多东西,主要是方便直接查询,其类结构如下: | |||
</code>class QS60Data | |||
{ | |||
public: | |||
QS60Data(); | |||
QThreadStorage<QS60ThreadLocalData'''> tls; | |||
TUid uid; | |||
int screenDepth; | |||
QPoint lastCursorPos; | |||
QPoint lastPointerEventPos; | |||
QPointer<QWidget> lastPointerEventTarget; | |||
QPointer<QWidget> mousePressTarget; | |||
int screenWidthInPixels; | |||
int screenHeightInPixels; | |||
int screenWidthInTwips; | |||
int screenHeightInTwips; | |||
int defaultDpiX; | |||
int defaultDpiY; | |||
WId curWin; | |||
enum PressedKeys { | |||
Select = 0x1, | |||
Right = 0x2, | |||
Down = 0x4, | |||
Left = 0x8, | |||
Up = 0x10, | |||
LeftUp = 0x20, | |||
RightUp = 0x40, | |||
RightDown = 0x80, | |||
LeftDown = 0x100 | |||
}; | |||
int virtualMousePressedKeys; // of the above type, but avoids casting problems | |||
int virtualMouseAccelDX; | |||
int virtualMouseAccelDY; | |||
QElapsedTimer virtualMouseAccelTimeout; | |||
int virtualMouseMaxAccel; | |||
#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS | |||
int brokenPointerCursors : 1; | |||
#endif | |||
int hasTouchscreen : 1; | |||
int mouseInteractionEnabled : 1; | |||
int virtualMouseRequired : 1; | |||
int qtOwnsS60Environment : 1; | |||
int supportsPremultipliedAlpha : 1; | |||
int avkonComponentsSupportTransparency : 1; | |||
int menuBeingConstructed : 1; | |||
QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type | |||
enum ScanCodeState { | enum ScanCodeState { | ||
Unpressed, | |||
KeyDown, | |||
KeyDownAndKey | |||
}; | |||
QHash<TInt, ScanCodeState> scanCodeStates; | |||
static inline void updateScreenSize(); | static inline void updateScreenSize(); | ||
inline RWsSession&amp; wsSession(); | |||
static inline RWindowGroup&amp; windowGroup(); | |||
inline CWsScreenDevice* screenDevice(); | |||
static inline CCoeAppUi* appUi(); | |||
static inline CEikMenuBar* menuBar(); | |||
#ifdef Q_WS_S60 | |||
static inline CEikStatusPane* statusPane(); | |||
static inline CCoeControl* statusPaneSubPane(TInt aPaneId); | |||
static inline CAknTitlePane* titlePane(); | |||
static inline CAknContextPane* contextPane(); | |||
static inline CEikButtonGroupContainer* buttonGroupContainer(); | |||
static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible); | |||
#endif | |||
static void controlVisibilityChanged(CCoeControl *control, bool visible); | |||
#ifdef Q_OS_SYMBIAN | #ifdef Q_OS_SYMBIAN | ||
TTrapHandler *s60InstalledTrapHandler; | |||
#endif | |||
};<code> |
Revision as of 11:43, 25 February 2015
作者: "habert":http://developer.qt.nokia.com/member/3776
Qt for Symbian之程序启动
我们都知道Qt中只要构造出QApplication就启动了,可启动细节就很少有人知道了,当然我们编写Qt的程序无需关心这么多,这也是为什么要用Qt的原因,但如果能够了解则可以加深对Qt的认识。今天看了一下Qt for Symbian的源码,整理如下,希望对有兴趣的朋友有帮助:
QApplication::QApplication(int &argc, char **argv)
: QCoreApplication('''new QApplicationPrivate(argc, argv, GuiClient) //第一步) //第二步
{
Q_D(QApplication); //第三步
d->construct(); //第四步
}
第一步构造了QApplicationPrivate的实例,其中GuiClient是一个枚举常量,表示应用程序的类型,这里我们不用关心。说道 QApplicationPrivate,如果你看过Qt的源码,你会发现很多类都配对有相应的Private类,这是Qt在封装底层实现时经常用的一种模式,Handle-Body Design Pattern,也就是说你在xx类中看不到具体的实现,具体的实现都封装在xxPrivate类中,而在xx类的方法只是调用xxPrivate中相应的方法。
第二步用QApplicationPrivate的实例构造了QCoreApplication,这里调用的是QCoreApplication的QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)构造函数,代码如下:
QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
: QObject(p, 0)
{
init();
// note: it is the subclasses' job to call
// QCoreApplicationPrivate::eventDispatcher->startingUp();
}
上面代码中的init初始化了一些资源,其中包括事件分发器。
第三步定义了d,这里是通过宏Q_D来实现的,其中宏Q_D的定义如下:
#define Q_D(Class) Class##Private''' const d = d_func()<code>
所以这里的d即是调用父类构造函数QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)时创建的QApplicationPrivate实例。
第四步调用d的construct函数,也就是QApplicationPrivate的实例的construct函数。代码如下所示:
void QApplicationPrivate::construct(
- ifdef Q_WS_X11
Display *dpy, Qt::HANDLE visual, Qt::HANDLE cmap
- endif
)
{
initResources();
qt_is_gui_used = (qt_appType != QApplication::Tty);
process_cmdline(); // the environment variable has the lowest precedence of runtime graphicssystem switches if (graphics_system_name.isEmpty()) graphics_system_name = QString::fromLocal8Bit(qgetenv("QT_GRAPHICSSYSTEM")); // Must be called before initialize() //这里调用了qt_init qt_init(this, qt_appType
- ifdef Q_WS_X11
, dpy, visual, cmap
- endif
); initialize(); eventDispatcher->startingUp();
- ifdef QT_EVAL
extern void qt_gui_eval_init(uint); qt_gui_eval_init(application_type);
- endif
- if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
symbianInit();
- endif
- ifndef QT_NO_LIBRARY
if(load_testability) { QLibrary testLib(QLatin1String("qttestability")); if (testLib.load()) { typedef void (TasInitialize)(void); TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init"); if (initFunction) { initFunction(); } else { qCritical("Library qttestability resolve failed!"); } } else { qCritical("Library qttestability load failed!"); } }
//make sure the plugin is loaded if (qt_is_gui_used) qt_guiPlatformPlugin();
- endif
}
这里也是初始化了很多资源,其中要要说的是qt_init,因为就是它创建了程序,代码如下:
void qt_init(QApplicationPrivate /* priv */, int)
{
if (!CCoeEnv::Static()) { // The S60 framework creates a new trap handler which will render any existing traps // invalid as long as it is active. This means that all code in main() that occurs after // the QApplication construction needs to be surrounded by a new trap, despite having // an outer one already. To avoid this, we save the original trap handler here, and set // it back after the S60 framework is constructed. Then we restore it right before the S60 // framework destruction. TTrapHandler origTrapHandler = User::TrapHandler();
// The S60 framework has not been initialized. We need to do it. //这里就是创建程序的地方 TApaApplicationFactory factory(S60->s60ApplicationFactory ? S60->s60ApplicationFactory : newS60Application); CApaCommandLine commandLine = 0; TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine); // After this construction, CEikonEnv will be available from CEikonEnv::Static(). // (much like our qApp). CEikonEnv* coe = new CEikonEnv; //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there. if(err == KErrNone) TRAP (err, coe->ConstructAppFromCommandLineL(factory,*commandLine)); //这里通过factory创建了程序 delete commandLine; if(err != KErrNone) { qWarning() << "qt_init: Eikon application construct failed (" << err << "), maybe missing resource file on S60 3.1?"; delete coe; qt_symbian_throwIfError(err); }
S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler);
S60->qtOwnsS60Environment = true;
} else { S60->qtOwnsS60Environment = false; }
- ifdef QT_NO_DEBUG
if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty())
- endif
S60->wsSession().SetAutoFlush(ETrue);
- ifdef Q_SYMBIAN_WINDOW_SIZE_CACHE
TRAP_IGNORE(S60->wsSession().EnableWindowSizeCacheL());
- endif
S60->updateScreenSize();
TDisplayMode mode = S60->screenDevice()->DisplayMode();
S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode);
//NB: RWsSession::GetColorModeList tells you what window modes are supported,
//not what bitmap formats. if(QSysInfo::symbianVersion() == QSysInfo::SV_9_2) S60->supportsPremultipliedAlpha = 0; else S60->supportsPremultipliedAlpha = 1;
RProcess me;
TSecureId securId = me.SecureId(); S60->uid = securId.operator TUid();
// enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app,
// and for dimming behind modal windows S60->windowGroup().EnableFocusChangeEvents();
//Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this)
const TInt KMachineUidSamsungI8510 = 0x2000C51E; // HAL::Get(HALData::EPen, TInt& result) may set 'result' to 1 on some 3.1 systems (e.g. N95). // But we know that S60 systems below 5.0 did not support touch. static const bool touchIsUnsupportedOnSystem = QSysInfo::s60Version() QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() QSysInfo::SV_S60_3_2; TInt machineUID; TInt mouse; TInt touch; TInt err; err = HAL::Get(HALData::EMouse, mouse); if (err != KErrNone) mouse = 0; err = HAL::Get(HALData::EMachineUid, machineUID); if (err != KErrNone) machineUID = 0; err = HAL::Get(HALData::EPen, touch); if (err != KErrNone || touchIsUnsupportedOnSystem) touch = 0;
- ifdef WINS
if(QSysInfo::symbianVersion() <= QSysInfo::SV_9_4) { //for symbian SDK emulator, force values to match typical devices. mouse = 0; touch = touchIsUnsupportedOnSystem ? 0 : 1; }
- endif
if (mouse || machineUID == KMachineUidSamsungI8510) { S60->hasTouchscreen = false; S60->virtualMouseRequired = false; } else if (!touch) { S60->hasTouchscreen = false; S60->virtualMouseRequired = true; } else { S60->hasTouchscreen = true; S60->virtualMouseRequired = false; }
S60->avkonComponentsSupportTransparency = false;
S60->menuBeingConstructed = false;
- ifdef Q_WS_S60
TUid KCRUidAvkon = { 0x101F876E }; TUint32 KAknAvkonTransparencyEnabled = 0x0000000D;
CRepository* repository = 0;
TRAP (err, repository = CRepository::NewL(KCRUidAvkon));
if(err KErrNone) {
TInt value = 0; err = repository->Get(KAknAvkonTransparencyEnabled, value); if(err KErrNone) { S60->avkonComponentsSupportTransparency = (value==1) ? true : false; } } delete repository; repository = 0;
- endif
- ifdef QT_KEYPAD_NAVIGATION
if (touch) { QApplicationPrivate::navigationMode = Qt::NavigationModeNone; } else { QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; }
- endif
- ifndef QT_NO_CURSOR
//Check if window server pointer cursors are supported or not
- ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
//In generic binary, use the HAL and OS version //Any other known good phones should be added here. if (machineUID == KMachineUidSamsungI8510 || (QSysInfo::symbianVersion() != QSysInfo::SV_9_4 && QSysInfo::symbianVersion() != QSysInfo::SV_9_3 && QSysInfo::symbianVersion() != QSysInfo::SV_9_2)) { S60->brokenPointerCursors = false; qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup()); } else S60->brokenPointerCursors = true;
- endif
if (S60->mouseInteractionEnabled) {
- ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
if (S60->brokenPointerCursors) { qt_symbian_set_pointer_sprite(Qt::ArrowCursor); qt_symbian_show_pointer_sprite(); } else
- endif
S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); }
- endif
QFont systemFont;
systemFont.setFamily(systemFont.defaultFamily()); QApplicationPrivate::setSystemFont(systemFont);
- ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
QObject::connect(qApp, SIGNAL (aboutToQuit()), qApp, SLOT (_q_aboutToQuit()));
- endif
/*
### Commented out for now as parameter handling not needed in SOS (yet). Code below will break testlib with -o flag int argc = priv->argc; char **argv = priv->argv;
// Get command line params
int j = argc ? 1 : 0; for (int i=1; i<argc; i+) { if (argv[i] && *argv[i] != '-') { argv[j+] = argv[i]; continue; }
- if defined(QT_DEBUG)
if (qstrcmp(argv[i], "-nograb") == 0) appNoGrab = !appNoGrab; else
- endif // QT_DEBUG
; }
- /
// Register WId with the metatype system. This is to enable // QWidgetPrivate::create_sys to used delayed slot invocation in order // to destroy WId objects during reparenting. qRegisterMetaType<WId>("WId");
}
代码很多,哈哈。上面代码中标有注释“这里就是创建程序的地方” 的部分:
TApaApplicationFactory factory(S60->s60ApplicationFactory ? S60->s60ApplicationFactory : newS60Application);
这里将newS60Application赋值给S60->s60ApplicationFactory,而newS60Application是什么呢,我们看看它的定义:
CApaApplication newS60Application()
{
return new QS60MainApplication;
}
由此可知newS60Application就是一个函数指针,它创建了一个QS60MainApplication实例,这里QS60MainApplication类封装了CAknApplication的实现。
另外上面代码中s60是一个全局数据,里面放了很多东西,主要是方便直接查询,其类结构如下:
class QS60Data
{ public:
QS60Data(); QThreadStorage<QS60ThreadLocalData> tls; TUid uid; int screenDepth; QPoint lastCursorPos; QPoint lastPointerEventPos; QPointer<QWidget> lastPointerEventTarget; QPointer<QWidget> mousePressTarget; int screenWidthInPixels; int screenHeightInPixels; int screenWidthInTwips; int screenHeightInTwips; int defaultDpiX; int defaultDpiY; WId curWin; enum PressedKeys { Select = 0x1, Right = 0x2, Down = 0x4, Left = 0x8, Up = 0x10, LeftUp = 0x20, RightUp = 0x40, RightDown = 0x80, LeftDown = 0x100 }; int virtualMousePressedKeys; // of the above type, but avoids casting problems int virtualMouseAccelDX; int virtualMouseAccelDY; QElapsedTimer virtualMouseAccelTimeout; int virtualMouseMaxAccel;
- ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
int brokenPointerCursors : 1;
- endif
int hasTouchscreen : 1; int mouseInteractionEnabled : 1; int virtualMouseRequired : 1; int qtOwnsS60Environment : 1; int supportsPremultipliedAlpha : 1; int avkonComponentsSupportTransparency : 1; int menuBeingConstructed : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type
enum ScanCodeState {
Unpressed, KeyDown, KeyDownAndKey }; QHash<TInt, ScanCodeState> scanCodeStates;
static inline void updateScreenSize();
inline RWsSession& wsSession(); static inline RWindowGroup& windowGroup(); inline CWsScreenDevice* screenDevice(); static inline CCoeAppUi* appUi(); static inline CEikMenuBar* menuBar();
- ifdef Q_WS_S60
static inline CEikStatusPane* statusPane(); static inline CCoeControl* statusPaneSubPane(TInt aPaneId); static inline CAknTitlePane* titlePane(); static inline CAknContextPane* contextPane(); static inline CEikButtonGroupContainer* buttonGroupContainer(); static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible);
- endif
static void controlVisibilityChanged(CCoeControl *control, bool visible);
- ifdef Q_OS_SYMBIAN
TTrapHandler *s60InstalledTrapHandler;
- endif
};