From 1744a94ce6a75ead5bb92546f1e0b28dd8a8a05c Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 27 Aug 2010 15:48:36 +1000 Subject: Recognize GL_ARB_shader_objects as indicating shaders Fixes a regression introduced by bf5c25c4. Some OpenGL implementations don't have the GL_ARB_fragment_shader extension listed even though they do support shaders. Task-number: QTBUG-13179 Reviewed-by: Sarah Smith --- src/opengl/qgl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 81e55b3..f3d0d81 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4931,6 +4931,8 @@ QGLExtensions::Extensions QGLExtensions::currentContextExtensions() glExtensions |= FragmentProgram; if (extensions.match("GL_ARB_fragment_shader")) glExtensions |= FragmentShader; + if (extensions.match("GL_ARB_shader_objects")) + glExtensions |= FragmentShader; if (extensions.match("GL_ARB_ES2_compatibility")) glExtensions |= ES2Compatibility; if (extensions.match("GL_ARB_texture_mirrored_repeat")) -- cgit v0.12 From eb1015c7bbf135af3656110a4d112377c1209db8 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 30 Aug 2010 14:57:06 +0200 Subject: Fix Qt applications freezing until mouse/keyboard events occur. While the qt_GetMessageHook() is executing, GetQueueStatus() reports that there are timer messages in the queue, but these are never actually seen by the hook. Calling PeekMessage() will never return these messages (which is what we really want to know), so don't use GetQueueStatus() with QS_TIMER. Task-number: QTBUG-12721 Reviewed-by: denis Reviewed-by: joao --- src/corelib/kernel/qeventdispatcher_win.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 8010a76..f63fa1d 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -65,7 +65,11 @@ extern uint qGlobalPostedEventsCount(); #endif #ifndef QS_RAWINPUT +# ifdef Q_OS_WINCE +# define QS_RAWINPUT 0x0000 +# else # define QS_RAWINPUT 0x0400 +# endif #endif #ifndef WM_TOUCH @@ -78,8 +82,7 @@ extern uint qGlobalPostedEventsCount(); enum { WM_QT_SOCKETNOTIFIER = WM_USER, - WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, - SendPostedEventsTimerId = ~1u + WM_QT_SENDPOSTEDEVENTS = WM_USER + 1 }; #if defined(Q_OS_WINCE) @@ -503,7 +506,9 @@ LRESULT CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) if (q) { QEventDispatcherWin32Private *d = q->d_func(); int localSerialNumber = d->serialNumber; - if (HIWORD(GetQueueStatus(QS_INPUT | QS_RAWINPUT | QS_TIMER)) == 0) { + MSG unused; + if ((HIWORD(GetQueueStatus(QS_INPUT | QS_RAWINPUT)) == 0 + && PeekMessage(&unused, 0, WM_TIMER, WM_TIMER, PM_NOREMOVE) == 0)) { // no more input or timer events in the message queue, we can allow posted events to be // sent now (void) d->wakeUps.fetchAndStoreRelease(0); @@ -799,7 +804,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) pHandles[i] = d->winEventNotifierList.at(i)->handle(); emit aboutToBlock(); - waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); + waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); emit awake(); if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); -- cgit v0.12 From ae574f7341f4f76a1f7de570cc3d56f77781e625 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 31 Aug 2010 11:15:30 +0200 Subject: Fix QtScript Date <--> QDateTime (local time) conversion This has already been fixed in 4.7 (QTBUG-9770), but the change is too big to backport. The general idea is the same: Only operate on UTC dates internally (since that's how JS dates are stored), and let QDateTime take care of converting from/to local dates as necessary. The fix itself shouldn't be merged to 4.7, but the autotests should. Task-number: QTBUG-9770 Reviewed-by: Jedrzej Nowacki --- src/script/utils/qscriptdate.cpp | 11 ++--- tests/auto/qscriptengine/tst_qscriptengine.cpp | 66 ++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/src/script/utils/qscriptdate.cpp b/src/script/utils/qscriptdate.cpp index 5980256..3985adb 100644 --- a/src/script/utils/qscriptdate.cpp +++ b/src/script/utils/qscriptdate.cpp @@ -320,8 +320,9 @@ qsreal FromDateTime(const QDateTime &dt) return qSNaN(); if (!LocalTZA) // ### move LocalTZA = getLocalTZA(); - QDate date = dt.date(); - QTime taim = dt.time(); + QDateTime utc = dt.toUTC(); + QDate date = utc.date(); + QTime taim = utc.time(); int year = date.year(); int month = date.month() - 1; int day = date.day(); @@ -331,8 +332,6 @@ qsreal FromDateTime(const QDateTime &dt) int ms = taim.msec(); double t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms)); - if (dt.timeSpec() == Qt::LocalTime) - t = UTC(t); return TimeClip(t); } @@ -348,8 +347,6 @@ QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec) return QDateTime(); if (!LocalTZA) // ### move LocalTZA = getLocalTZA(); - if (spec == Qt::LocalTime) - t = LocalTime(t); int year = int(YearFromTime(t)); int month = int(MonthFromTime(t) + 1); int day = int(DateFromTime(t)); @@ -357,7 +354,7 @@ QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec) int mins = MinFromTime(t); int secs = SecFromTime(t); int ms = msFromTime(t); - return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec); + return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), Qt::UTC).toTimeSpec(spec); } } // namespace QScript diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index bb01a42..3bb9d17 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -166,6 +166,10 @@ private slots: void qRegExpInport_data(); void qRegExpInport(); + void dateRoundtripJSQtJS(); + void dateRoundtripQtJSQt(); + void dateConversionJSQt(); + void dateConversionQtJS(); }; tst_QScriptEngine::tst_QScriptEngine() @@ -4895,5 +4899,67 @@ void tst_QScriptEngine::qRegExpInport() } } +// QScriptValue::toDateTime() returns a local time, whereas JS dates +// are always stored as UTC. QtScript must respect the current time +// zone, and correctly adjust for daylight saving time that may be in +// effect at a given date (QTBUG-9770). +void tst_QScriptEngine::dateRoundtripJSQtJS() +{ + uint secs = QDateTime(QDate(2009, 1, 1)).toUTC().toTime_t(); + QScriptEngine eng; + for (int i = 0; i < 8000; ++i) { + QScriptValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0)); + QDateTime qtDate = jsDate.toDateTime(); + QScriptValue jsDate2 = eng.newDate(qtDate); + if (jsDate2.toNumber() != jsDate.toNumber()) + QFAIL(qPrintable(jsDate.toString())); + secs += 2*60*60; + } +} + +void tst_QScriptEngine::dateRoundtripQtJSQt() +{ + QDateTime qtDate = QDateTime(QDate(2009, 1, 1)); + QScriptEngine eng; + for (int i = 0; i < 8000; ++i) { + QScriptValue jsDate = eng.newDate(qtDate); + QDateTime qtDate2 = jsDate.toDateTime(); + if (qtDate2 != qtDate) + QFAIL(qPrintable(qtDate.toString())); + qtDate = qtDate.addSecs(2*60*60); + } +} + +void tst_QScriptEngine::dateConversionJSQt() +{ + uint secs = QDateTime(QDate(2009, 1, 1)).toUTC().toTime_t(); + QScriptEngine eng; + for (int i = 0; i < 8000; ++i) { + QScriptValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0)); + QDateTime qtDate = jsDate.toDateTime(); + QString qtUTCDateStr = qtDate.toUTC().toString(Qt::ISODate); + QString jsUTCDateStr = jsDate.property("toISOString").call(jsDate).toString(); + jsUTCDateStr.chop(5); // get rid of milliseconds (".000Z") + if (qtUTCDateStr != jsUTCDateStr) + QFAIL(qPrintable(jsDate.toString())); + secs += 2*60*60; + } +} + +void tst_QScriptEngine::dateConversionQtJS() +{ + QDateTime qtDate = QDateTime(QDate(2009, 1, 1)); + QScriptEngine eng; + for (int i = 0; i < 8000; ++i) { + QScriptValue jsDate = eng.newDate(qtDate); + QString jsUTCDateStr = jsDate.property("toISOString").call(jsDate).toString(); + jsUTCDateStr.chop(5); // get rid of milliseconds (".000Z") + QString qtUTCDateStr = qtDate.toUTC().toString(Qt::ISODate); + if (jsUTCDateStr != qtUTCDateStr) + QFAIL(qPrintable(qtDate.toString())); + qtDate = qtDate.addSecs(2*60*60); + } +} + QTEST_MAIN(tst_QScriptEngine) #include "tst_qscriptengine.moc" -- cgit v0.12 From 19198b08a1d5b6f4e6875d93e2647b38e8f11184 Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Fri, 20 Aug 2010 17:52:36 +0200 Subject: Some small Solaris fixes. Sets the arch properly for solaris-cc-64-stlport on x86_64. This patch also removes three redundant lines in configure and disables qtconcurrent examples when it's not available. Reviewed-by: Thiago --- configure | 5 +---- examples/examples.pro | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/configure b/configure index eaae2d1..f3420c8 100755 --- a/configure +++ b/configure @@ -1388,9 +1388,6 @@ while [ "$#" -gt 0 ]; do solaris-64) PLATFORM=solaris-cc-64 ;; - solaris-64) - PLATFORM=solaris-cc-64 - ;; openunix-cc) PLATFORM=unixware-cc ;; @@ -2687,7 +2684,7 @@ if [ -z "${CFG_HOST_ARCH}" ]; then ;; i86pc) case "$PLATFORM" in - *-64) + *-64*) if [ "$OPT_VERBOSE" = "yes" ]; then echo " 64-bit AMD 80x86 (x86_64)" fi diff --git a/examples/examples.pro b/examples/examples.pro index 7d9aa05..4408a8b 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -13,7 +13,6 @@ SUBDIRS = \ mainwindows \ network \ painting \ - qtconcurrent \ richtext \ sql \ statemachine \ @@ -61,6 +60,7 @@ contains(QT_CONFIG, dbus): SUBDIRS += dbus win32: SUBDIRS += activeqt contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns contains(DEFINES, QT_NO_CURSOR): SUBDIRS -= mainwindows +contains(QT_CONFIG, concurrent): SUBDIRS += qtconcurrent # install sources.files = README *.pro -- cgit v0.12 From 5738dcd705e7edde816940f9c0ab2c364c81ad20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Tue, 31 Aug 2010 10:23:30 +0200 Subject: Ensure that we load system libraries from the correct location. This was a security hole that has been there for a while, but the public awareness have recently rised so the threat is more imminent now. The solution is to fix all places where we dynamically load system libraries. More specifically, we now load all system libraries with an absolute path that points to a library in the system directory (usually c:\windows\system32). We therefore introduce a small class named QSystemLibrary that only loads libraries located in the system path. This shares some of the API with QLibrary (in order to make the patch as small as possible). We don't fix QLibrary due to risk of regressions. In addition, applications can fix the code that calls QLibrary themselves. The problem does not apply to Windows CE, since the search order is documented as not searching in the current directory. However, it touches some CE-specific code - therefore QSystemLibrary is sometimes used on WinCE (however, it will just do a normal LoadLibrary() since its safe anyway). This change does not affect the testability plugin (it is not clearly documented where that plugin is located, and the plugin should never be used in production code anyway) Loading OpenSSL libraries The ssl libraries are handled specially, and searched in this order (we cannot expect them to always be in the system folder): 1. Application path 2. System libraries path 3. Trying all paths inside the PATH environment variable Task-number: QT-3825 Reviewed-by: Thiago Macieira Reviewed-by: Peter Hartmann --- qmake/Makefile.win32 | 5 ++ qmake/qmake.pri | 3 +- src/activeqt/shared/qaxtypes.cpp | 4 +- src/corelib/io/qfsfileengine_win.cpp | 7 +- src/corelib/io/qsettings.cpp | 6 +- src/corelib/kernel/qeventdispatcher_win.cpp | 10 +-- src/corelib/plugin/plugin.pri | 7 +- src/corelib/plugin/qsystemlibrary.cpp | 90 ++++++++++++++++++++++++++ src/corelib/plugin/qsystemlibrary_p.h | 61 +++++++++++++++++ src/gui/accessible/qaccessible_win.cpp | 4 +- src/gui/dialogs/qfiledialog_win.cpp | 12 ++-- src/gui/dialogs/qwizard_win.cpp | 6 +- src/gui/kernel/qapplication_win.cpp | 38 ++++++----- src/gui/kernel/qdesktopwidget_win.cpp | 6 +- src/gui/kernel/qwidget_win.cpp | 6 +- src/gui/styles/qwindowsstyle.cpp | 8 +-- src/gui/styles/qwindowsvistastyle.cpp | 3 +- src/gui/styles/qwindowsxpstyle.cpp | 4 +- src/gui/text/qfontdatabase_win.cpp | 10 +-- src/gui/text/qfontengine_win.cpp | 4 +- src/gui/util/qdesktopservices_win.cpp | 6 +- src/gui/util/qsystemtrayicon_win.cpp | 8 +-- src/network/kernel/qhostinfo_win.cpp | 14 ++-- src/network/kernel/qnetworkinterface_win.cpp | 3 +- src/network/kernel/qnetworkproxy_win.cpp | 15 +++-- src/network/ssl/qsslsocket_openssl_symbols.cpp | 36 ++++++++--- src/qt3support/network/q3dns.cpp | 3 +- src/tools/bootstrap/bootstrap.pro | 3 +- 28 files changed, 282 insertions(+), 100 deletions(-) create mode 100644 src/corelib/plugin/qsystemlibrary.cpp create mode 100644 src/corelib/plugin/qsystemlibrary_p.h diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 48d84b7..c452c5a 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -102,6 +102,7 @@ QTOBJS= \ qtemporaryfile.obj \ qabstractfileengine.obj \ qfsfileengine_win.obj \ + qsystemlibrary.obj \ qfsfileengine_iterator_win.obj \ qfileinfo.obj \ qglobal.obj \ @@ -155,6 +156,7 @@ clean:: -del qtemporaryfile.obj -del qabstractfileengine.obj -del qfsfileengine_win.obj + -del qsystemlibrary.obj -del qfsfileengine_iterator_win.obj -del qfileinfo.obj -del qglobal.obj @@ -313,6 +315,9 @@ qtemporaryfile.obj: $(SOURCE_PATH)\src\corelib\io\qtemporaryfile.cpp qfsfileengine_win.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine_win.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine_win.cpp +qsystemlibrary.obj: $(SOURCE_PATH)\src\corelib\plugin\qsystemlibrary.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\plugin\qsystemlibrary.cpp + qfsfileengine_iterator_win.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator_win.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator_win.cpp diff --git a/qmake/qmake.pri b/qmake/qmake.pri index b82ab4d..8d3a559 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -128,7 +128,8 @@ bootstrap { #Qt code LIBS += -framework ApplicationServices } } else:win32 { - SOURCES += qfsfileengine_win.cpp qfsfileengine_iterator_win.cpp qsettings_win.cpp + SOURCES += qfsfileengine_win.cpp qfsfileengine_iterator_win.cpp qsettings_win.cpp \ + qsystemlibrary.cpp win32-msvc*:LIBS += ole32.lib advapi32.lib win32-g++:LIBS += -lole32 -luuid } diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 0cfc7eb..957733e 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -52,7 +52,7 @@ #include #ifdef QAX_SERVER # include -# include +# include #else # include # include @@ -666,7 +666,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type static bool resolved = false; if (!resolved) { resolved = true; - pGetRecordInfoFromTypeInfo = (PGetRecordInfoFromTypeInfo)QLibrary::resolve(QLatin1String("oleaut32"), + pGetRecordInfoFromTypeInfo = (PGetRecordInfoFromTypeInfo)QSystemLibrary::resolve(QLatin1String("oleaut32"), "GetRecordInfoFromTypeInfo"); } if (!pGetRecordInfoFromTypeInfo) diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 139075f..44db59b 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -43,6 +43,7 @@ #include "qplatformdefs.h" #include "qabstractfileengine.h" #include "private/qfsfileengine_p.h" +#include #include #include "qfile.h" @@ -181,7 +182,7 @@ void QFSFileEnginePrivate::resolveLibs() triedResolve = true; #if !defined(Q_OS_WINCE) - HINSTANCE advapiHnd = LoadLibraryW(L"advapi32"); + HINSTANCE advapiHnd = QSystemLibrary::load(L"advapi32"); if (advapiHnd) { ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); @@ -213,7 +214,7 @@ void QFSFileEnginePrivate::resolveLibs() ptrFreeSid(pWorld); } } - HINSTANCE userenvHnd = LoadLibraryW(L"userenv"); + HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv"); if (userenvHnd) ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); #endif @@ -245,7 +246,7 @@ bool QFSFileEnginePrivate::resolveUNCLibs() #endif triedResolve = true; #if !defined(Q_OS_WINCE) - HINSTANCE hLib = LoadLibraryW(L"Netapi32"); + HINSTANCE hLib = QSystemLibrary::load(L"Netapi32"); if (hLib) { ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); if (ptrNetShareEnum) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 64015ce..c3dece9 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -69,7 +69,7 @@ #ifdef Q_OS_WIN // for homedirpath reading from registry #include "qt_windows.h" -#include "qlibrary.h" +#include #endif // Q_OS_WIN #endif // QT_NO_QOBJECT @@ -1046,9 +1046,9 @@ static QString windowsConfigPath(int type) // We can't use QLibrary if there is QT_NO_QOBJECT is defined // This only happens when bootstrapping qmake. #ifndef Q_OS_WINCE - QLibrary library(QLatin1String("shell32")); + QSystemLibrary library(QLatin1String("shell32")); #else - QLibrary library(QLatin1String("coredll")); + QSystemLibrary library(QLatin1String("coredll")); #endif // Q_OS_WINCE typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index f63fa1d..2da02f9 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -43,7 +43,7 @@ #include "qcoreapplication.h" #include "qhash.h" -#include "qlibrary.h" +#include #include "qpair.h" #include "qset.h" #include "qsocketnotifier.h" @@ -324,11 +324,11 @@ static void resolveTimerAPI() #endif triedResolve = true; #if !defined(Q_OS_WINCE) - qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("winmm"), "timeSetEvent"); - qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("winmm"), "timeKillEvent"); + qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeSetEvent"); + qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeKillEvent"); #else - qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent"); - qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent"); + qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent"); + qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent"); #endif } } diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri index c05ff48..ba86353 100644 --- a/src/corelib/plugin/plugin.pri +++ b/src/corelib/plugin/plugin.pri @@ -7,7 +7,8 @@ HEADERS += \ plugin/qlibrary_p.h \ plugin/qplugin.h \ plugin/quuid.h \ - plugin/qfactoryloader_p.h + plugin/qfactoryloader_p.h \ + plugin/qsystemlibrary_p.h SOURCES += \ plugin/qpluginloader.cpp \ @@ -16,7 +17,9 @@ SOURCES += \ plugin/qlibrary.cpp win32 { - SOURCES += plugin/qlibrary_win.cpp + SOURCES += \ + plugin/qlibrary_win.cpp \ + plugin/qsystemlibrary.cpp } unix { diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp new file mode 100644 index 0000000..7e9fdde --- /dev/null +++ b/src/corelib/plugin/qsystemlibrary.cpp @@ -0,0 +1,90 @@ +#include "qsystemlibrary_p.h" +#include +#include +#include + +/*! + + \internal + \class QSystemLibrary + + The purpose of this class is to load only libraries that are located in + well-known and trusted locations on the filesystem. It does not suffer from + the security problem that QLibrary has, therefore it will never search in + the current directory. + + The search order is the same as the order in DLL Safe search mode Windows, + except that we don't search: + * The current directory + * The 16-bit system directory. (normally c:\windows\system) + * The Windows directory. (normally c:\windows) + + This means that the effective search order is: + 1. Application path. + 2. System libraries path. + 3. Trying all paths inside the PATH environment variable. + + Note, when onlySystemDirectory is true it will skip 1) and 3). + + DLL Safe search mode is documented in the "Dynamic-Link Library Search + Order" document on MSDN. + + Since library loading code is sometimes shared between Windows and WinCE, + this class can also be used on WinCE. However, its implementation just + calls the LoadLibrary() function. This is ok since it is documented as not + loading from the current directory on WinCE. This behaviour is documented + in the documentation for LoadLibrary for Windows CE at MSDN. + (http://msdn.microsoft.com/en-us/library/ms886736.aspx) +*/ +#if !defined(QT_BOOTSTRAPPED) +extern QString qAppFileName(); +#endif + +static QString qSystemDirectory() +{ + QVarLengthArray fullPath; + + UINT retLen = ::GetSystemDirectory(fullPath.data(), MAX_PATH); + if (retLen > MAX_PATH) { + fullPath.resize(retLen); + retLen = ::GetSystemDirectory(fullPath.data(), retLen); + } + // in some rare cases retLen might be 0 + return QString::fromWCharArray(fullPath.constData(), int(retLen)); +} + +HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory/*= true*/) +{ +#if defined(Q_OS_WINCE) + return ::LoadLibrary(lpFileName); +#else + QStringList searchOrder; + +#if !defined(QT_BOOTSTRAPPED) + if (!onlySystemDirectory) + searchOrder << QFileInfo(qAppFileName()).path(); +#endif + searchOrder << qSystemDirectory(); + + if (!onlySystemDirectory) { + const QString PATH(QLatin1String(qgetenv("PATH").constData())); + searchOrder << PATH.split(QLatin1Char(';'), QString::SkipEmptyParts); + } + QString fileName = QString::fromWCharArray(libraryName); + fileName.append(QLatin1String(".dll")); + + // Start looking in the order specified + for (int i = 0; i < searchOrder.count(); ++i) { + QString fullPathAttempt = searchOrder.at(i); + if (!fullPathAttempt.endsWith(QLatin1Char('\\'))) { + fullPathAttempt.append(QLatin1Char('\\')); + } + fullPathAttempt.append(fileName); + HINSTANCE inst = ::LoadLibrary((const wchar_t *)fullPathAttempt.utf16()); + if (inst != 0) + return inst; + } + return 0; +#endif +} + diff --git a/src/corelib/plugin/qsystemlibrary_p.h b/src/corelib/plugin/qsystemlibrary_p.h new file mode 100644 index 0000000..60c59e2 --- /dev/null +++ b/src/corelib/plugin/qsystemlibrary_p.h @@ -0,0 +1,61 @@ +#ifndef QSYSTEMLIBRARY_P_H +#define QSYSTEMLIBRARY_P_H + +#include +#ifdef Q_OS_WIN +#include +#include + +class QSystemLibrary +{ +public: + explicit QSystemLibrary(const QString &libraryName) + { + m_libraryName = libraryName; + m_handle = 0; + m_didLoad = false; + } + + explicit QSystemLibrary(const wchar_t *libraryName) + { + m_libraryName = QString::fromWCharArray(libraryName); + m_handle = 0; + m_didLoad = false; + } + + bool load(bool onlySystemDirectory = true) + { + m_handle = load((const wchar_t *)m_libraryName.utf16(), onlySystemDirectory); + m_didLoad = true; + return (m_handle != 0); + } + + bool isLoaded() + { + return (m_handle != 0); + } + + void *resolve(const char *symbol) + { + if (!m_didLoad) + load(); + if (!m_handle) + return 0; + return (void*)GetProcAddress(m_handle, symbol); + } + + static void *resolve(const QString &libraryName, const char *symbol) + { + return QSystemLibrary(libraryName).resolve(symbol); + } + + static Q_CORE_EXPORT HINSTANCE load(const wchar_t *lpFileName, bool onlySystemDirectory = true); +private: + HINSTANCE m_handle; + QString m_libraryName; + bool m_didLoad; +}; + +#endif //Q_OS_WIN + +#endif //QSYSTEMLIBRARY_P_H diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp index fc8575f..132d01f 100644 --- a/src/gui/accessible/qaccessible_win.cpp +++ b/src/gui/accessible/qaccessible_win.cpp @@ -42,7 +42,7 @@ #ifndef QT_NO_ACCESSIBILITY #include "qapplication.h" -#include "qlibrary.h" +#include #include "qmessagebox.h" // ### dependency #include "qt_windows.h" #include "qwidget.h" @@ -243,7 +243,7 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason) static bool resolvedNWE = false; if (!resolvedNWE) { resolvedNWE = true; - ptrNotifyWinEvent = (PtrNotifyWinEvent)QLibrary::resolve(QLatin1String("user32"), "NotifyWinEvent"); + ptrNotifyWinEvent = (PtrNotifyWinEvent)QSystemLibrary::resolve(QLatin1String("user32"), "NotifyWinEvent"); } if (!ptrNotifyWinEvent) return; diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp index 5a7ace9..bd97527 100644 --- a/src/gui/dialogs/qfiledialog_win.cpp +++ b/src/gui/dialogs/qfiledialog_win.cpp @@ -52,7 +52,7 @@ #include #include #include -#include +#include #ifndef QT_NO_THREAD # include @@ -126,10 +126,10 @@ static void qt_win_resolve_libs() triedResolve = true; #if !defined(Q_WS_WINCE) - QLibrary lib(QLatin1String("shell32")); - ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW"); - ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW"); - ptrSHGetMalloc = (PtrSHGetMalloc) lib.resolve("SHGetMalloc"); + QSystemLibrary lib(L"shell32"); + ptrSHBrowseForFolder = (PtrSHBrowseForFolder)lib.resolve("SHBrowseForFolderW"); + ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)lib.resolve("SHGetPathFromIDListW"); + ptrSHGetMalloc = (PtrSHGetMalloc)lib.resolve("SHGetMalloc"); #else // CE stores them in a different lib and does not use unicode version HINSTANCE handle = LoadLibraryW(L"Ceshell"); @@ -436,7 +436,7 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd, { if (!pSHCreateItemFromParsingName) { // This function is available only in Vista & above. - QLibrary shellLib(QLatin1String("Shell32")); + QSystemLibrary shellLib(QLatin1String("Shell32")); pSHCreateItemFromParsingName = (PtrSHCreateItemFromParsingName) shellLib.resolve("SHCreateItemFromParsingName"); if (!pSHCreateItemFromParsingName) diff --git a/src/gui/dialogs/qwizard_win.cpp b/src/gui/dialogs/qwizard_win.cpp index 1390b21..449ad62 100644 --- a/src/gui/dialogs/qwizard_win.cpp +++ b/src/gui/dialogs/qwizard_win.cpp @@ -43,7 +43,7 @@ #ifndef QT_NO_STYLE_WINDOWSVISTA #include "qwizard_win_p.h" -#include "qlibrary.h" +#include #include "qwizard.h" #include "qpaintengine.h" #include "qapplication.h" @@ -691,7 +691,7 @@ bool QVistaHelper::resolveSymbols() static bool tried = false; if (!tried) { tried = true; - QLibrary dwmLib(QString::fromAscii("dwmapi")); + QSystemLibrary dwmLib(L"dwmapi"); pDwmIsCompositionEnabled = (PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); if (pDwmIsCompositionEnabled) { @@ -699,7 +699,7 @@ bool QVistaHelper::resolveSymbols() pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); } - QLibrary themeLib(QString::fromAscii("uxtheme")); + QSystemLibrary themeLib(L"uxtheme"); pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); if (pIsAppThemed) { pDrawThemeBackground = (PtrDrawThemeBackground)themeLib.resolve("DrawThemeBackground"); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index d6896c0..b6b49cc 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -66,7 +66,6 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #include "qdatetime.h" #include "qpointer.h" #include "qhash.h" -#include "qlibrary.h" #include "qmetaobject.h" #include "qmime.h" #include "qpainter.h" @@ -91,6 +90,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #include "qdebug.h" #include #include +#include #include "qevent_p.h" //#define ALIEN_DEBUG @@ -204,7 +204,7 @@ static void resolveAygLibs() { if (!aygResolved) { aygResolved = true; - QLibrary ayglib(QLatin1String("aygshell")); + QSystemLibrary ayglib(QLatin1String("aygshell")); if (!ayglib.load()) return; ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture"); @@ -811,10 +811,10 @@ void qt_init(QApplicationPrivate *priv, int) #ifndef Q_OS_WINCE ptrUpdateLayeredWindowIndirect = - (PtrUpdateLayeredWindowIndirect) QLibrary::resolve(QLatin1String("user32"), + (PtrUpdateLayeredWindowIndirect) QSystemLibrary::resolve(QLatin1String("user32"), "UpdateLayeredWindowIndirect"); ptrUpdateLayeredWindow = - (PtrUpdateLayeredWindow) QLibrary::resolve(QLatin1String("user32"), + (PtrUpdateLayeredWindow) QSystemLibrary::resolve(QLatin1String("user32"), "UpdateLayeredWindow"); if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect) @@ -822,7 +822,7 @@ void qt_init(QApplicationPrivate *priv, int) // Notify Vista and Windows 7 that we support highter DPI settings ptrSetProcessDPIAware = (PtrSetProcessDPIAware) - QLibrary::resolve(QLatin1String("user32"), "SetProcessDPIAware"); + QSystemLibrary::resolve(QLatin1String("user32"), "SetProcessDPIAware"); if (ptrSetProcessDPIAware) ptrSetProcessDPIAware(); #endif @@ -842,30 +842,28 @@ void qt_init(QApplicationPrivate *priv, int) #elif !defined(Q_WS_WINCE) #if !defined(QT_NO_NATIVE_GESTURES) priv->GetGestureInfo = - (PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"), + (PtrGetGestureInfo)QSystemLibrary::resolve(QLatin1String("user32"), "GetGestureInfo"); priv->GetGestureExtraArgs = - (PtrGetGestureExtraArgs)QLibrary::resolve(QLatin1String("user32"), + (PtrGetGestureExtraArgs)QSystemLibrary::resolve(QLatin1String("user32"), "GetGestureExtraArgs"); priv->CloseGestureInfoHandle = - (PtrCloseGestureInfoHandle)QLibrary::resolve(QLatin1String("user32"), + (PtrCloseGestureInfoHandle)QSystemLibrary::resolve(QLatin1String("user32"), "CloseGestureInfoHandle"); priv->SetGestureConfig = - (PtrSetGestureConfig)QLibrary::resolve(QLatin1String("user32"), + (PtrSetGestureConfig)QSystemLibrary::resolve(QLatin1String("user32"), "SetGestureConfig"); priv->GetGestureConfig = - (PtrGetGestureConfig)QLibrary::resolve(QLatin1String("user32"), + (PtrGetGestureConfig)QSystemLibrary::resolve(QLatin1String("user32"), "GetGestureConfig"); #endif // QT_NO_NATIVE_GESTURES + QSystemLibrary libTheme(QLatin1String("uxtheme")); priv->BeginPanningFeedback = - (PtrBeginPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), - "BeginPanningFeedback"); + (PtrBeginPanningFeedback)libTheme.resolve("BeginPanningFeedback"); priv->UpdatePanningFeedback = - (PtrUpdatePanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), - "UpdatePanningFeedback"); + (PtrUpdatePanningFeedback)libTheme.resolve("UpdatePanningFeedback"); priv->EndPanningFeedback = - (PtrEndPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), - "EndPanningFeedback"); + (PtrEndPanningFeedback)libTheme.resolve("EndPanningFeedback"); #endif } @@ -2294,7 +2292,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam if (!oleaccChecked) { oleaccChecked = true; #if !defined(Q_OS_WINCE) - ptrLresultFromObject = (PtrLresultFromObject)QLibrary::resolve(QLatin1String("oleacc.dll"), "LresultFromObject"); + ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"); #endif } if (ptrLresultFromObject) { @@ -3080,7 +3078,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg) static PtrTrackMouseEvent ptrTrackMouseEvent = 0; if (!trackMouseEventLookup) { trackMouseEventLookup = true; - ptrTrackMouseEvent = (PtrTrackMouseEvent)QLibrary::resolve(QLatin1String("comctl32"), "_TrackMouseEvent"); + ptrTrackMouseEvent = (PtrTrackMouseEvent)QSystemLibrary::resolve(QLatin1String("comctl32"), "_TrackMouseEvent"); } if (ptrTrackMouseEvent && !qApp->d_func()->inPopupMode()) { // We always have to set the tracking, since @@ -3600,7 +3598,7 @@ static void initWinTabFunctions() if (!qt_is_gui_used) return; - QLibrary library(QLatin1String("wintab32")); + QSystemLibrary library(QLatin1String("wintab32")); if (library.load()) { ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); @@ -4044,7 +4042,7 @@ void QApplicationPrivate::initializeMultitouch_sys() iInkTablets->Release(); } - QLibrary library(QLatin1String("user32")); + QSystemLibrary library(QLatin1String("user32")); // MinGW (g++ 3.4.5) accepts only C casts. RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow")); GetTouchInputInfo = (PtrGetTouchInputInfo)(library.resolve("GetTouchInputInfo")); diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index 1fea8d6..7d7caac 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -42,7 +42,7 @@ #include "qdesktopwidget.h" #include "qt_windows.h" #include "qapplication_p.h" -#include "qlibrary.h" +#include #include #include #ifdef Q_WS_WINCE @@ -155,7 +155,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) screenCount = 0; #ifndef Q_OS_WINCE - QLibrary user32Lib(QLatin1String("user32")); + QSystemLibrary user32Lib(QLatin1String("user32")); if (user32Lib.load()) { enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); @@ -173,7 +173,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) enumDisplayMonitors = 0; getMonitorInfo = 0; #else - QLibrary coreLib(QLatin1String("coredll")); + QSystemLibrary coreLib(QLatin1String("coredll")); if (coreLib.load()) { // CE >= 4.0 case enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 9acfb70..10d6345 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -47,7 +47,6 @@ #include "qevent.h" #include "qimage.h" #include "qlayout.h" -#include "qlibrary.h" #include "qpainter.h" #include "qstack.h" #include "qt_windows.h" @@ -65,6 +64,7 @@ #include #include #include +#include #if defined(Q_WS_WINCE) #include "qguifunctions_wince.h" @@ -143,7 +143,7 @@ static void init_wintab_functions() #else if (!qt_is_gui_used) return; - QLibrary library(QLatin1String("wintab32")); + QSystemLibrary library(QLatin1String("wintab32")); ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW"); ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); ptrWTClose = (PtrWTClose)library.resolve("WTClose"); @@ -1860,7 +1860,7 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) static bool function_resolved = false; if (!function_resolved) { ptrSetLayeredWindowAttributes = - (PtrSetLayeredWindowAttributes) QLibrary::resolve(QLatin1String("user32"), + (PtrSetLayeredWindowAttributes) QSystemLibrary::resolve(QLatin1String("user32"), "SetLayeredWindowAttributes"); function_resolved = true; } diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 6c48590..53d32da 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -45,7 +45,7 @@ #if !defined(QT_NO_STYLE_WINDOWS) || defined(QT_PLUGIN) -#include "qlibrary.h" +#include #include "qapplication.h" #include "qbitmap.h" #include "qdrawutil.h" // for now @@ -126,7 +126,7 @@ QWindowsStylePrivate::QWindowsStylePrivate() #if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { - QLibrary shellLib(QLatin1String("shell32")); + QSystemLibrary shellLib(QLatin1String("shell32")); pSHGetStockIconInfo = (PtrSHGetStockIconInfo)shellLib.resolve("SHGetStockIconInfo"); } #endif @@ -921,9 +921,9 @@ static const char *const question_xpm[] = { static QPixmap loadIconFromShell32( int resourceId, int size ) { #ifdef Q_OS_WINCE - HMODULE hmod = LoadLibrary(L"ceshell.dll"); + HMODULE hmod = LoadLibrary(L"ceshell"); #else - HMODULE hmod = LoadLibrary(L"shell32.dll"); + HMODULE hmod = QSystemLibrary::load(L"shell32"); #endif if( hmod ) { HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0); diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 67a7b85..92688c0 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -42,6 +42,7 @@ #include "qwindowsvistastyle.h" #include "qwindowsvistastyle_p.h" #include +#include #if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN) @@ -2597,7 +2598,7 @@ bool QWindowsVistaStylePrivate::resolveSymbols() static bool tried = false; if (!tried) { tried = true; - QLibrary themeLib(QLatin1String("uxtheme")); + QSystemLibrary themeLib(QLatin1String("uxtheme")); pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme"); pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined"); pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index efb1224..a2538fe 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -344,7 +344,7 @@ bool QWindowsXPStylePrivate::resolveSymbols() static bool tried = false; if (!tried) { tried = true; - QLibrary themeLib(QLatin1String("uxtheme")); + QSystemLibrary themeLib(QLatin1String("uxtheme")); pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); if (pIsAppThemed) { pIsThemeActive = (PtrIsThemeActive )themeLib.resolve("IsThemeActive"); diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp index a6ceee1..160b139 100644 --- a/src/gui/text/qfontdatabase_win.cpp +++ b/src/gui/text/qfontdatabase_win.cpp @@ -45,7 +45,7 @@ #include "qfont_p.h" #include "qfontengine_p.h" #include "qpaintdevice.h" -#include "qlibrary.h" +#include #include "qabstractfileengine.h" #include "qendian.h" @@ -1049,7 +1049,7 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) { if(!fnt->data.isEmpty()) { #ifndef Q_OS_WINCE - PtrAddFontMemResourceEx ptrAddFontMemResourceEx = (PtrAddFontMemResourceEx)QLibrary::resolve(QLatin1String("gdi32"), + PtrAddFontMemResourceEx ptrAddFontMemResourceEx = (PtrAddFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), "AddFontMemResourceEx"); if (!ptrAddFontMemResourceEx) return; @@ -1112,7 +1112,7 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) return; #else // supported from 2000 on, so no need to deal with the *A variant - PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"), + PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), "AddFontResourceExW"); if (!ptrAddFontResourceExW || ptrAddFontResourceExW((wchar_t*)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0) @@ -1141,7 +1141,7 @@ bool QFontDatabase::removeApplicationFont(int handle) if (!removeSucceeded) return false; #else - PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QLibrary::resolve(QLatin1String("gdi32"), + PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx"); if (!ptrRemoveFontMemResourceEx || !ptrRemoveFontMemResourceEx(font.handle)) @@ -1152,7 +1152,7 @@ bool QFontDatabase::removeApplicationFont(int handle) if (!RemoveFontResource((LPCWSTR)font.fileName.utf16())) return false; #else - PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"), + PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontResourceExW"); if (!ptrRemoveFontResourceExW || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0)) diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index eea196e..be90f1c 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -50,7 +50,7 @@ #include "qt_windows.h" #include -#include +#include #include #include #include @@ -140,7 +140,7 @@ static void resolveGetCharWidthI() if (resolvedGetCharWidthI) return; resolvedGetCharWidthI = true; - ptrGetCharWidthI = (PtrGetCharWidthI)QLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI"); + ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI"); } #endif // !defined(Q_WS_WINCE) diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp index 9f3b6e1..359710f 100644 --- a/src/gui/util/qdesktopservices_win.cpp +++ b/src/gui/util/qdesktopservices_win.cpp @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include #include @@ -177,9 +177,9 @@ QString QDesktopServices::storageLocation(StandardLocation type) QString result; #ifndef Q_OS_WINCE - QLibrary library(QLatin1String("shell32")); + QSystemLibrary library(QLatin1String("shell32")); #else - QLibrary library(QLatin1String("coredll")); + QSystemLibrary library(QLatin1String("coredll")); #endif // Q_OS_WINCE typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); static GetSpecialFolderPath SHGetSpecialFolderPath = diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp index 1571b94..6e78dfd 100644 --- a/src/gui/util/qsystemtrayicon_win.cpp +++ b/src/gui/util/qsystemtrayicon_win.cpp @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include #include #include @@ -134,14 +134,14 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object) // Allow the WM_TASKBARCREATED message through the UIPI filter on Windows Vista and higher static PtrChangeWindowMessageFilterEx pChangeWindowMessageFilterEx = - (PtrChangeWindowMessageFilterEx)QLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilterEx"); + (PtrChangeWindowMessageFilterEx)QSystemLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilterEx"); if (pChangeWindowMessageFilterEx) { // Call the safer ChangeWindowMessageFilterEx API if available pChangeWindowMessageFilterEx(winId(), MYWM_TASKBARCREATED, Q_MSGFLT_ALLOW, 0); } else { static PtrChangeWindowMessageFilter pChangeWindowMessageFilter = - (PtrChangeWindowMessageFilter)QLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilter"); + (PtrChangeWindowMessageFilter)QSystemLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilter"); if (pChangeWindowMessageFilter) { // Call the deprecated ChangeWindowMessageFilter API otherwise @@ -352,7 +352,7 @@ void QSystemTrayIconPrivate::install_sys() QRect QSystemTrayIconSys::findIconGeometry(const int iconId) { static PtrShell_NotifyIconGetRect Shell_NotifyIconGetRect = - (PtrShell_NotifyIconGetRect)QLibrary::resolve(QLatin1String("shell32"), "Shell_NotifyIconGetRect"); + (PtrShell_NotifyIconGetRect)QSystemLibrary::resolve(QLatin1String("shell32"), "Shell_NotifyIconGetRect"); if (Shell_NotifyIconGetRect) { Q_NOTIFYICONIDENTIFIER nid; diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index b30204b..8241c84 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -49,7 +49,7 @@ #include "qhostinfo_p.h" #include "private/qnativesocketengine_p.h" #include -#include +#include #include #include #include @@ -90,13 +90,13 @@ static void resolveLibrary() // Attempt to resolve getaddrinfo(); without it we'll have to fall // back to gethostbyname(), which has no IPv6 support. #if !defined(Q_OS_WINCE) - local_getaddrinfo = (getaddrinfoProto) QLibrary::resolve(QLatin1String("ws2_32.dll"), "getaddrinfo"); - local_freeaddrinfo = (freeaddrinfoProto) QLibrary::resolve(QLatin1String("ws2_32.dll"), "freeaddrinfo"); - local_getnameinfo = (getnameinfoProto) QLibrary::resolve(QLatin1String("ws2_32.dll"), "getnameinfo"); + local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getaddrinfo"); + local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo"); + local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo"); #else - local_getaddrinfo = (getaddrinfoProto) QLibrary::resolve(QLatin1String("ws2.dll"), "getaddrinfo"); - local_freeaddrinfo = (freeaddrinfoProto) QLibrary::resolve(QLatin1String("ws2.dll"), "freeaddrinfo"); - local_getnameinfo = (getnameinfoProto) QLibrary::resolve(QLatin1String("ws2.dll"), "getnameinfo"); + local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getaddrinfo"); + local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "freeaddrinfo"); + local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getnameinfo"); #endif } diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index 056650d..a1d1df6 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -48,6 +48,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -66,7 +67,7 @@ static void resolveLibs() if (!done) { done = true; - HINSTANCE iphlpapiHnd = LoadLibrary(L"iphlpapi"); + HINSTANCE iphlpapiHnd = QSystemLibrary::load(L"iphlpapi"); if (iphlpapiHnd == NULL) return; diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index e801738..de7c245 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -51,6 +51,7 @@ #include #include #include +#include /* * Information on the WinHTTP DLL: @@ -273,15 +274,15 @@ void QWindowsSystemProxy::init() return; #else // load the winhttp.dll library - HINSTANCE winhttpHnd = LoadLibrary(L"winhttp"); - if (!winhttpHnd) + QSystemLibrary lib(L"winhttp"); + if (!lib.load()) return; // failed to load - ptrWinHttpOpen = (PtrWinHttpOpen)GetProcAddress(winhttpHnd, "WinHttpOpen"); - ptrWinHttpCloseHandle = (PtrWinHttpCloseHandle)GetProcAddress(winhttpHnd, "WinHttpCloseHandle"); - ptrWinHttpGetProxyForUrl = (PtrWinHttpGetProxyForUrl)GetProcAddress(winhttpHnd, "WinHttpGetProxyForUrl"); - ptrWinHttpGetDefaultProxyConfiguration = (PtrWinHttpGetDefaultProxyConfiguration)GetProcAddress(winhttpHnd, "WinHttpGetDefaultProxyConfiguration"); - ptrWinHttpGetIEProxyConfigForCurrentUser = (PtrWinHttpGetIEProxyConfigForCurrentUser)GetProcAddress(winhttpHnd, "WinHttpGetIEProxyConfigForCurrentUser"); + ptrWinHttpOpen = (PtrWinHttpOpen)lib.resolve("WinHttpOpen"); + ptrWinHttpCloseHandle = (PtrWinHttpCloseHandle)lib.resolve("WinHttpCloseHandle"); + ptrWinHttpGetProxyForUrl = (PtrWinHttpGetProxyForUrl)lib.resolve("WinHttpGetProxyForUrl"); + ptrWinHttpGetDefaultProxyConfiguration = (PtrWinHttpGetDefaultProxyConfiguration)lib.resolve("WinHttpGetDefaultProxyConfiguration"); + ptrWinHttpGetIEProxyConfigForCurrentUser = (PtrWinHttpGetIEProxyConfigForCurrentUser)lib.resolve("WinHttpGetIEProxyConfigForCurrentUser"); // Try to obtain the Internet Explorer configuration. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 8620e00..9e550ae 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -42,7 +42,11 @@ #include "qsslsocket_openssl_symbols_p.h" -#include +#ifdef Q_OS_WIN +# include +#else +# include +#endif #include #include #include @@ -343,22 +347,22 @@ static QStringList findAllLibSsl() } # endif -static QPair loadOpenSsl() +#ifdef Q_OS_WIN +static QPair loadOpenSslWin32() { - QPair pair; + QPair pair; pair.first = 0; pair.second = 0; -# ifdef Q_OS_WIN - QLibrary *ssleay32 = new QLibrary(QLatin1String("ssleay32")); - if (!ssleay32->load()) { + QSystemLibrary *ssleay32 = new QSystemLibrary(QLatin1String("ssleay32")); + if (!ssleay32->load(false)) { // Cannot find ssleay32.dll delete ssleay32; return pair; } - QLibrary *libeay32 = new QLibrary(QLatin1String("libeay32")); - if (!libeay32->load()) { + QSystemLibrary *libeay32 = new QSystemLibrary(QLatin1String("libeay32")); + if (!libeay32->load(false)) { delete ssleay32; delete libeay32; return pair; @@ -367,7 +371,16 @@ static QPair loadOpenSsl() pair.first = ssleay32; pair.second = libeay32; return pair; -# elif defined(Q_OS_SYMBIAN) +} +#else + +static QPair loadOpenSsl() +{ + QPair pair; + pair.first = 0; + pair.second = 0; + +# if defined(Q_OS_SYMBIAN) QLibrary *libssl = new QLibrary(QLatin1String("libssl")); if (!libssl->load()) { // Cannot find ssleay32.dll @@ -467,6 +480,7 @@ static QPair loadOpenSsl() return pair; # endif } +#endif bool q_resolveOpenSslSymbols() { @@ -481,7 +495,11 @@ bool q_resolveOpenSslSymbols() return false; triedToResolveSymbols = true; +#ifdef Q_OS_WIN + QPair libs = loadOpenSslWin32(); +#else QPair libs = loadOpenSsl(); +#endif if (!libs.first || !libs.second) // failed to load them return false; diff --git a/src/qt3support/network/q3dns.cpp b/src/qt3support/network/q3dns.cpp index ab042c4..e0e9909 100644 --- a/src/qt3support/network/q3dns.cpp +++ b/src/qt3support/network/q3dns.cpp @@ -41,6 +41,7 @@ #include "qplatformdefs.h" #include "qbytearray.h" +#include #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_CYGWIN) # include "qt_windows.h" #else @@ -2299,7 +2300,7 @@ void Q3Dns::doResInit() bool gotNetworkParams = false; // try the API call GetNetworkParams() first and use registry lookup only // as a fallback - HINSTANCE hinstLib = LoadLibrary( L"iphlpapi" ); + HINSTANCE hinstLib = QSystemLibrary::load( L"iphlpapi" ); if ( hinstLib != 0 ) { #ifdef Q_OS_WINCE GNP getNetworkParams = (GNP) GetProcAddress( hinstLib, L"GetNetworkParams" ); diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 0dbb90f..21fd412 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -87,7 +87,8 @@ unix:SOURCES += ../../corelib/io/qfsfileengine_unix.cpp \ ../../corelib/io/qfsfileengine_iterator_unix.cpp win32:SOURCES += ../../corelib/io/qfsfileengine_win.cpp \ - ../../corelib/io/qfsfileengine_iterator_win.cpp + ../../corelib/io/qfsfileengine_iterator_win.cpp \ + ../../corelib/plugin/qsystemlibrary.cpp \ macx: { QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 #enables weak linking for 10.4 (exported) -- cgit v0.12 From d869e2da86d46cff772252e053098555c3151eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Fri, 3 Sep 2010 14:26:41 +0200 Subject: Compile fix WinCE Task-number: QT-3825 --- src/corelib/plugin/qsystemlibrary.cpp | 13 +++++++++---- src/corelib/plugin/qsystemlibrary_p.h | 6 +++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp index 7e9fdde..f781770 100644 --- a/src/corelib/plugin/qsystemlibrary.cpp +++ b/src/corelib/plugin/qsystemlibrary.cpp @@ -36,6 +36,13 @@ in the documentation for LoadLibrary for Windows CE at MSDN. (http://msdn.microsoft.com/en-us/library/ms886736.aspx) */ +#if defined(Q_OS_WINCE) +HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory/*= true*/) +{ + return ::LoadLibrary(libraryName); +} +#else + #if !defined(QT_BOOTSTRAPPED) extern QString qAppFileName(); #endif @@ -55,9 +62,6 @@ static QString qSystemDirectory() HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirectory/*= true*/) { -#if defined(Q_OS_WINCE) - return ::LoadLibrary(lpFileName); -#else QStringList searchOrder; #if !defined(QT_BOOTSTRAPPED) @@ -85,6 +89,7 @@ HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirect return inst; } return 0; -#endif + } +#endif //Q_OS_WINCE diff --git a/src/corelib/plugin/qsystemlibrary_p.h b/src/corelib/plugin/qsystemlibrary_p.h index 60c59e2..5d925ca 100644 --- a/src/corelib/plugin/qsystemlibrary_p.h +++ b/src/corelib/plugin/qsystemlibrary_p.h @@ -41,7 +41,11 @@ public: load(); if (!m_handle) return 0; - return (void*)GetProcAddress(m_handle, symbol); +#ifdef Q_OS_WINCE + return (void*)GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16()); +#else + return (void*)GetProcAddress(m_handle, symbol); +#endif } static void *resolve(const QString &libraryName, const char *symbol) -- cgit v0.12 From a465b9e92bea7669052882dc6dd59a8b6f447bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Mon, 6 Sep 2010 08:23:42 +0200 Subject: Compile fix MinGW, 5738dcd705e7edde816940f9c0ab2c364c81ad20 broke it. Task-number: QT-3825 --- qmake/Makefile.win32-g++ | 4 ++++ qmake/Makefile.win32-g++-sh | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index 169de3c..5b59154 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -81,6 +81,7 @@ QTOBJS= \ qutfcodec.o \ qstring.o \ qstringlist.o \ + qsystemlibrary.o \ qtextstream.o \ quuid.o \ qvector.o \ @@ -236,6 +237,9 @@ qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp +qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp + qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qmap.cpp diff --git a/qmake/Makefile.win32-g++-sh b/qmake/Makefile.win32-g++-sh index 98237e7..5295ddb 100644 --- a/qmake/Makefile.win32-g++-sh +++ b/qmake/Makefile.win32-g++-sh @@ -81,6 +81,7 @@ QTOBJS= \ qutfcodec.o \ qstring.o \ qstringlist.o \ + qsystemlibrary.o \ qtextstream.o \ quuid.o \ qvector.o \ @@ -235,6 +236,9 @@ qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp +qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp + qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qmap.cpp -- cgit v0.12 From 5eba3f8f449256ace5aa70ab004a63f3e5d79d7a Mon Sep 17 00:00:00 2001 From: axis Date: Fri, 27 Aug 2010 10:31:39 +0200 Subject: Revert "Long-press shortcuts for symbols on QWERTY keyboard don't work" This reverts commit 05eacd9ad40f8adb5aaa12a8b90113a73b43f642. Conflicts: src/gui/inputmethod/qcoefepinputcontext_p.h src/gui/inputmethod/qcoefepinputcontext_s60.cpp (cherry picked from commit c5901037f0d3ccd45b0c79b38ef5b04552dad0aa) --- src/gui/inputmethod/qcoefepinputcontext_p.h | 1 - src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 15 +-------------- src/gui/widgets/qlinecontrol.cpp | 2 +- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index d5243c3..cc14e89 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -151,7 +151,6 @@ private: int m_inlinePosition; MFepInlineTextFormatRetriever *m_formatRetriever; MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; - int m_cursorPos; QBasicTimer m_tempPreeditStringTimeout; bool m_hasTempPreeditString; }; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 44fe7da..eddb7cc 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -76,7 +76,6 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_inlinePosition(0), m_formatRetriever(0), m_pointerHandler(0), - m_cursorPos(0), m_hasTempPreeditString(false) { m_fepState->SetObjectProvider(this); @@ -571,8 +570,6 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, commitTemporaryPreeditString(); - m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); - QList attributes; m_cursorVisibility = aCursorVisibility ? 1 : 0; @@ -795,23 +792,13 @@ void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction) { int longPress = 0; - if (m_preeditString.size() == 0) { - QWidget *w = focusWidget(); - if (!cancelFepTransaction && w) { - // We must replace the last character only if the input box has already accepted one - if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos) - longPress = 1; - } - } - QList attributes; QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(m_preeditString, 0-longPress, longPress); + event.setCommitString(m_preeditString, 0, 0); m_preeditString.clear(); sendEvent(event); m_hasTempPreeditString = false; - longPress = 0; if (cancelFepTransaction) { CCoeFep* fep = CCoeEnv::Static()->Fep(); diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 9ec0feb..ef2bfe2 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -419,7 +419,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) int c = m_cursor; // cursor position after insertion of commit string - if (event->replacementStart() == 0) + if (event->replacementStart() <= 0) c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); m_cursor += event->replacementStart(); -- cgit v0.12 From a2e2d2207d3b7f164ba9c9c7fa776e10bb7bc168 Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 31 Aug 2010 13:15:28 +0200 Subject: Cleaned up position tracking in the Symbian input methods. This fixed a case where using password mode would lead to Qt believing that the cursor was one step to the left of where it really was. This would have the effect of replacing the last character instead of appending to it, and even crashing if the cursor was all the way to the left. The code is also much cleaner this way, but it meant that QTBUG-9867 had to be solved differently this time. We do this by assuming that and empty FEP update means "erase last character", which seems to work well in practice. Also added a long overdue autotest for the FEP input methods. Most tests pass, but some don't, which I will try to fix later. Task: QTBUG-9867 Task: QTBUG-12949 RevBy: Miikka Heikkinen AutoTest: Included (cherry picked from commit 52cf47565e402dc682038ccaf8d725401802b603) --- src/gui/inputmethod/qcoefepinputcontext_p.h | 10 +- src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 19 +- src/gui/kernel/qt_s60_p.h | 4 +- tests/auto/qinputcontext/qinputcontext.pro | 4 + tests/auto/qinputcontext/tst_qinputcontext.cpp | 659 +++++++++++++++++++++++- 5 files changed, 679 insertions(+), 17 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index cc14e89..2fd6d16 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -66,10 +66,10 @@ QT_BEGIN_NAMESPACE -class QCoeFepInputContext : public QInputContext, - public MCoeFepAwareTextEditor, - public MCoeFepAwareTextEditor_Extension1, - public MObjectProvider +class Q_AUTOTEST_EXPORT QCoeFepInputContext : public QInputContext, + public MCoeFepAwareTextEditor, + public MCoeFepAwareTextEditor_Extension1, + public MObjectProvider { Q_OBJECT @@ -153,6 +153,8 @@ private: MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; QBasicTimer m_tempPreeditStringTimeout; bool m_hasTempPreeditString; + + friend class tst_QInputContext; }; QT_END_NAMESPACE diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index eddb7cc..278f6d4 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -237,7 +237,6 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) && focusWidget()->inputMethodHints() & Qt::ImhHiddenText && !keyEvent->text().isEmpty()) { // Send some temporary preedit text in order to make text visible for a moment. - m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); m_preeditString = keyEvent->text(); QList attributes; QInputMethodEvent imEvent(m_preeditString, attributes); @@ -293,10 +292,6 @@ void QCoeFepInputContext::commitTemporaryPreeditString() return; commitCurrentString(false); - - //update cursor position, now this pre-edit text has been committed. - //this prevents next keypress overwriting it (QTBUG-11673) - m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); } void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) @@ -584,9 +579,10 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, // Let's remove the selected text if aInitialInlineText is empty and there is selected text if (m_preeditString.isEmpty()) { int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt(); - int replacementLength = qAbs(m_cursorPos-anchor); + int cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); + int replacementLength = qAbs(cursorPos-anchor); if (replacementLength > 0) { - int replacementStart = m_cursorPos < anchor ? 0 : -replacementLength; + int replacementStart = cursorPos < anchor ? 0 : -replacementLength; QList clearSelectionAttributes; QInputMethodEvent clearSelectionEvent(QLatin1String(""), clearSelectionAttributes); clearSelectionEvent.setCommitString(QLatin1String(""), replacementStart, replacementLength); @@ -619,8 +615,13 @@ void QCoeFepInputContext::UpdateFepInlineTextL(const TDesC& aNewInlineText, m_inlinePosition, m_cursorVisibility, QVariant())); - m_preeditString = qt_TDesC2QString(aNewInlineText); - QInputMethodEvent event(m_preeditString, attributes); + QString newPreeditString = qt_TDesC2QString(aNewInlineText); + QInputMethodEvent event(newPreeditString, attributes); + if (newPreeditString.isEmpty() && m_preeditString.isEmpty()) { + // In Symbian world this means "erase last character". + event.setCommitString("", -1, 1); + } + m_preeditString = newPreeditString; sendEvent(event); } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index bf71062..929043c 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -86,7 +86,7 @@ const TInt KInternalStatusPaneChange = 0x50000000; //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 #define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13) -class QS60ThreadLocalData +class Q_AUTOTEST_EXPORT QS60ThreadLocalData { public: QS60ThreadLocalData(); @@ -154,7 +154,7 @@ public: #endif }; -QS60Data* qGlobalS60Data(); +Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data(); #define S60 qGlobalS60Data() class QAbstractLongTapObserver diff --git a/tests/auto/qinputcontext/qinputcontext.pro b/tests/auto/qinputcontext/qinputcontext.pro index b3ea8c2..ec6831e 100644 --- a/tests/auto/qinputcontext/qinputcontext.pro +++ b/tests/auto/qinputcontext/qinputcontext.pro @@ -1,2 +1,6 @@ load(qttest_p4) SOURCES += tst_qinputcontext.cpp + +symbian { + LIBS += -lws32 -lcone +} diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 644b463..23cfd9e 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -48,17 +48,26 @@ #include #include #include +#include + +#ifdef Q_OS_SYMBIAN +#include +#include + +#include +#include +#endif class tst_QInputContext : public QObject { Q_OBJECT public: - tst_QInputContext() {} + tst_QInputContext() : m_phoneIsQwerty(false) {} virtual ~tst_QInputContext() {} public slots: - void initTestCase() {} + void initTestCase(); void cleanupTestCase() {} void init() {} void cleanup() {} @@ -69,8 +78,176 @@ private slots: void closeSoftwareInputPanel(); void selections(); void focusProxy(); + void symbianTestCoeFepInputContext_data(); + void symbianTestCoeFepInputContext(); + +private: + bool m_phoneIsQwerty; }; +#ifdef Q_OS_SYMBIAN +class KeyEvent : public TWsEvent +{ +public: + KeyEvent(QWidget *w, TInt type, TInt scanCode, TUint code, TUint modifiers, TInt repeats) { + iHandle = w->effectiveWinId()->DrawableWindow()->WindowGroupId(); + iType = type; + SetTimeNow(); + TKeyEvent *keyEvent = reinterpret_cast(iEventData); + keyEvent->iScanCode = scanCode; + keyEvent->iCode = code; + keyEvent->iModifiers = modifiers; + keyEvent->iRepeats = repeats; + } +}; + +class FepReplayEvent +{ +public: + enum Type { + Pause, + Key, + CompleteKey + }; + + FepReplayEvent(int msecsToPause) + : m_type(Pause) + , m_msecsToPause(msecsToPause) + { + } + + FepReplayEvent(TInt keyType, TInt scanCode, TUint code, TUint modifiers, TInt repeats) + : m_type(Key) + , m_keyType(keyType) + , m_scanCode(scanCode) + , m_code(code) + , m_modifiers(modifiers) + , m_repeats(repeats) + { + } + + FepReplayEvent(TInt scanCode, TUint code, TUint modifiers, TInt repeats) + : m_type(CompleteKey) + , m_scanCode(scanCode) + , m_code(code) + , m_modifiers(modifiers) + , m_repeats(repeats) + { + } + + void sendEvent(QWidget *w, TInt type, TInt scanCode, TUint code, TUint modifiers, TInt repeats) + { + KeyEvent event(w, type, scanCode, code, modifiers, repeats); + S60->wsSession().SendEventToWindowGroup(w->effectiveWinId()->DrawableWindow()->WindowGroupId(), event); + } + + void pause(int msecs) + { + // Don't use qWait here. The polling nature of that function screws up the test. + QTimer timer; + QEventLoop loop; + QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + timer.setSingleShot(true); + timer.start(msecs); + loop.exec(); + } + + // For some reason, the test fails if using processEvents instead of an event loop + // with a zero timer to quit it, so use the timer. +#define KEY_WAIT 0 + + void replay(QWidget *w) + { + if (m_type == Pause) { + pause(m_msecsToPause); + } else if (m_type == Key) { + sendEvent(w, m_keyType, m_scanCode, m_code, m_modifiers, m_repeats); + if (m_keyType != EEventKeyDown) + // EEventKeyDown events should have no pause before the EEventKey event. + pause(KEY_WAIT); + } else if (m_type == CompleteKey) { + sendEvent(w, EEventKeyDown, m_scanCode, 0, m_modifiers, m_repeats); + // EEventKeyDown events should have no pause before the EEventKey event. + sendEvent(w, EEventKey, m_scanCode, m_code, m_modifiers, m_repeats); + pause(KEY_WAIT); + sendEvent(w, EEventKeyUp, m_scanCode, 0, m_modifiers, m_repeats); + pause(KEY_WAIT); + } + } + +private: + Type m_type; + int m_msecsToPause; + TInt m_keyType; + TInt m_scanCode; + TUint m_code; + TUint m_modifiers; + TInt m_repeats; +}; + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(Qt::InputMethodHints) +Q_DECLARE_METATYPE(QLineEdit::EchoMode); + +#endif // Q_OS_SYMBIAN + +void tst_QInputContext::initTestCase() +{ +#ifdef Q_OS_SYMBIAN + // Sanity test. Checks FEP for: + // - T9 mode is default (it will attempt to fix this) + // - Language is English (it cannot fix this; bail out if not correct) + QWidget w; + QLayout *layout = new QVBoxLayout; + w.setLayout(layout); + QLineEdit *lineedit = new QLineEdit; + layout->addWidget(lineedit); + lineedit->setFocus(); +#ifdef QT_KEYPAD_NAVIGATION + lineedit->setEditFocus(true); +#endif + w.show(); + + QDesktopWidget desktop; + QRect screenSize = desktop.screenGeometry(&w); + if (screenSize.width() > screenSize.height()) { + // Crude way of finding out we are running on a qwerty phone. + m_phoneIsQwerty = true; + return; + } + + for (int iterations = 0; iterations < 16; iterations++) { + QTest::qWait(500); + + QList keyEvents; + + keyEvents << FepReplayEvent('9', '9', 0, 0); + keyEvents << FepReplayEvent('6', '6', 0, 0); + keyEvents << FepReplayEvent('8', '8', 0, 0); + keyEvents << FepReplayEvent(EStdKeyRightArrow, EKeyRightArrow, 0, 0); + + foreach(FepReplayEvent event, keyEvents) { + event.replay(lineedit); + } + + QApplication::processEvents(); + + if (lineedit->text().endsWith("you", Qt::CaseInsensitive)) { + // Success! + return; + } + + // Try changing modes. + // After 8 iterations, try to press the mode switch twice before typing. + for (int c = 0; c <= iterations / 8; c++) { + FepReplayEvent(EStdKeyHash, '#', 0, 0).replay(lineedit); + } + } + + QFAIL("FEP sanity test failed. Either the phone is not set to English, or the test was unable to enable T9"); +#endif +} + void tst_QInputContext::maximumTextLength() { QLineEdit le; @@ -285,5 +462,483 @@ void tst_QInputContext::focusProxy() QCOMPARE(gic->focusWidget(), &proxy); } +void tst_QInputContext::symbianTestCoeFepInputContext_data() +{ +#ifdef Q_OS_SYMBIAN + QTest::addColumn ("inputMethodEnabled"); + QTest::addColumn ("inputMethodHints"); + QTest::addColumn ("maxLength"); // Zero for no limit + QTest::addColumn ("echoMode"); + QTest::addColumn > ("keyEvents"); + QTest::addColumn ("finalString"); + QTest::addColumn ("preeditString"); + QList events; + + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + events << FepReplayEvent('5', '5', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('6', '6', 0, 0); + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + events << FepReplayEvent('1', '1', 0, 0); + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + events << FepReplayEvent('2', '2', 0, 0); + events << FepReplayEvent('1', '1', 0, 0); + QTest::newRow("Numbers (no FEP)") + << false + << Qt::InputMethodHints(Qt::ImhNone) + << 0 + << QLineEdit::Normal + << events + << QString("521") + << QString(""); + QTest::newRow("Numbers and password mode (no FEP)") + << false + << Qt::InputMethodHints(Qt::ImhNone) + << 0 + << QLineEdit::Password + << events + << QString("521") + << QString(""); + QTest::newRow("Numbers") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 0 + << QLineEdit::Normal + << events + << QString("521") + << QString(""); + QTest::newRow("Numbers max length (no FEP)") + << false + << Qt::InputMethodHints(Qt::ImhNone) + << 2 + << QLineEdit::Normal + << events + << QString("21") + << QString(""); + QTest::newRow("Numbers max length") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 2 + << QLineEdit::Normal + << events + << QString("21") + << QString(""); + events.clear(); + + events << FepReplayEvent(EEventKeyDown, '5', 0, 0, 0); + events << FepReplayEvent(EEventKey, '5', '5', 0, 0); + events << FepReplayEvent(EEventKey, '5', '5', 0, 1); + events << FepReplayEvent(EEventKey, '5', '5', 0, 1); + events << FepReplayEvent(EEventKeyUp, '5', 0, 0, 0); + QTest::newRow("Numbers and autorepeat (no FEP)") + << false + << Qt::InputMethodHints(Qt::ImhNone) + << 0 + << QLineEdit::Normal + << events + << QString("555") + << QString(""); + events.clear(); + + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + events << FepReplayEvent('2', '2', 0, 0); + events << FepReplayEvent('3', '3', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('5', '5', 0, 0); + events << FepReplayEvent('5', '5', 0, 0); + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + QTest::newRow("Multitap") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText) + << 0 + << QLineEdit::Normal + << events + << QString("Adh") + << QString(""); + QTest::newRow("Multitap with no auto uppercase") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhNoAutoUppercase) + << 0 + << QLineEdit::Normal + << events + << QString("adh") + << QString(""); + QTest::newRow("Multitap with uppercase") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhPreferUppercase) + << 0 + << QLineEdit::Normal + << events + << QString("ADH") + << QString(""); + QTest::newRow("Multitap with lowercase") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Normal + << events + << QString("adh") + << QString(""); + QTest::newRow("Multitap with forced uppercase") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhUppercaseOnly) + << 0 + << QLineEdit::Normal + << events + << QString("ADH") + << QString(""); + QTest::newRow("Multitap with forced lowercase") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhLowercaseOnly) + << 0 + << QLineEdit::Normal + << events + << QString("adh") + << QString(""); + events.clear(); + + events << FepReplayEvent(EStdKeyHash, '#', 0, 0); + events << FepReplayEvent('2', '2', 0, 0); + events << FepReplayEvent('2', '2', 0, 0); + events << FepReplayEvent('3', '3', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('5', '5', 0, 0); + events << FepReplayEvent('5', '5', 0, 0); + events << FepReplayEvent(EStdKeyBackspace, EKeyBackspace, 0, 0); + QTest::newRow("Multitap with mode switch") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText) + << 0 + << QLineEdit::Normal + << events + << QString("bdh") + << QString(""); + events.clear(); + + events << FepReplayEvent('7', '7', 0, 0); + events << FepReplayEvent('7', '7', 0, 0); + events << FepReplayEvent('8', '8', 0, 0); + events << FepReplayEvent('9', '9', 0, 0); + events << FepReplayEvent('9', '9', 0, 0); + QTest::newRow("Multitap with unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText) + << 0 + << QLineEdit::Normal + << events + << QString("Qt") + << QString("x"); + events << FepReplayEvent(2000); + QTest::newRow("Multitap with committed text") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText) + << 0 + << QLineEdit::Normal + << events + << QString("Qtx") + << QString(""); + events.clear(); + + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + // Simulate holding down hash key. + events << FepReplayEvent(EEventKeyDown, EStdKeyHash, 0, 0, 0); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 0); + events << FepReplayEvent(500); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 1); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 1); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 1); + events << FepReplayEvent(EEventKeyUp, EStdKeyHash, 0, 0, 0); + events << FepReplayEvent('7', '7', 0, 0); + events << FepReplayEvent('7', '7', 0, 0); + events << FepReplayEvent('8', '8', 0, 0); + // QTBUG-9867: Switch back as well to make sure we don't get extra symbols + events << FepReplayEvent(EEventKeyDown, EStdKeyHash, 0, 0, 0); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 0); + events << FepReplayEvent(500); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 1); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 1); + events << FepReplayEvent(EEventKey, EStdKeyHash, '#', 0, 1); + events << FepReplayEvent(EEventKeyUp, EStdKeyHash, 0, 0, 0); + events << FepReplayEvent('9', '9', 0, 0); + events << FepReplayEvent('6', '6', 0, 0); + events << FepReplayEvent('8', '8', 0, 0); + events << FepReplayEvent(2000); + events << FepReplayEvent(EStdKeyDevice3, EKeyDevice3, 0, 0); // Select key + QTest::newRow("Multitap and numbers") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText) + << 0 + << QLineEdit::Normal + << events + << QString("H778wmt") + << QString(""); + QTest::newRow("T9 and numbers") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Normal + << events + << QString("hi778you") + << QString(""); + events.clear(); + + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent(EStdKeyDevice3, EKeyDevice3, 0, 0); // Select key + QTest::newRow("T9") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Normal + << events + << QString("hi") + << QString(""); + QTest::newRow("T9 with uppercase") + << true + << Qt::InputMethodHints(Qt::ImhPreferUppercase) + << 0 + << QLineEdit::Normal + << events + << QString("HI") + << QString(""); + QTest::newRow("T9 with forced lowercase") + << true + << Qt::InputMethodHints(Qt::ImhLowercaseOnly) + << 0 + << QLineEdit::Normal + << events + << QString("hi") + << QString(""); + QTest::newRow("T9 with forced uppercase") + << true + << Qt::InputMethodHints(Qt::ImhUppercaseOnly) + << 0 + << QLineEdit::Normal + << events + << QString("HI") + << QString(""); + QTest::newRow("T9 with maxlength") + << true + << Qt::InputMethodHints(Qt::ImhLowercaseOnly) + << 1 + << QLineEdit::Normal + << events + << QString("i") + << QString(""); + events.clear(); + + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent('4', '4', 0, 0); + events << FepReplayEvent(EStdKeyLeftArrow, EKeyLeftArrow, 0, 0); + events << FepReplayEvent(EStdKeyLeftArrow, EKeyLeftArrow, 0, 0); + events << FepReplayEvent('9', '9', 0, 0); + events << FepReplayEvent('6', '6', 0, 0); + events << FepReplayEvent('8', '8', 0, 0); + events << FepReplayEvent('0', '0', 0, 0); + events << FepReplayEvent(EStdKeyRightArrow, EKeyRightArrow, 0, 0); + events << FepReplayEvent(EStdKeyRightArrow, EKeyRightArrow, 0, 0); + events << FepReplayEvent('8', '8', 0, 0); + events << FepReplayEvent('8', '8', 0, 0); + QTest::newRow("T9 with movement and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Normal + << events + << QString("you hi") + << QString("tv"); + QTest::newRow("T9 with movement, password and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Password + << events + << QString("wmt h") + << QString("u"); + QTest::newRow("T9 with movement, maxlength, password and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 2 + << QLineEdit::Password + << events + << QString("wh") + << QString(""); + QTest::newRow("T9 with movement, maxlength and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 2 + << QLineEdit::Normal + << events + << QString("hi") + << QString(""); + QTest::newRow("Multitap with movement and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Normal + << events + << QString("wmt h") + << QString("u"); + QTest::newRow("Multitap with movement, maxlength and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhPreferLowercase) + << 2 + << QLineEdit::Normal + << events + << QString("wh") + << QString(""); + QTest::newRow("Numbers with movement") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 0 + << QLineEdit::Normal + << events + << QString("96804488") + << QString(""); + QTest::newRow("Numbers with movement and maxlength") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 2 + << QLineEdit::Normal + << events + << QString("44") + << QString(""); + QTest::newRow("Numbers with movement, password and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 0 + << QLineEdit::Password + << events + << QString("9680448") + << QString("8"); + QTest::newRow("Numbers with movement, maxlength, password and unfinished text") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 2 + << QLineEdit::Password + << events + << QString("44") + << QString(""); + events << FepReplayEvent(EStdKeyRightArrow, EKeyRightArrow, 0, 0); + QTest::newRow("T9 with movement") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Normal + << events + << QString("you htvi") + << QString(""); + QTest::newRow("T9 with movement and password") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Password + << events + << QString("wmt hu") + << QString(""); + QTest::newRow("T9 with movement, maxlength and password") + << true + << Qt::InputMethodHints(Qt::ImhPreferLowercase) + << 2 + << QLineEdit::Password + << events + << QString("wh") + << QString(""); + QTest::newRow("Multitap with movement") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhPreferLowercase) + << 0 + << QLineEdit::Normal + << events + << QString("wmt hu") + << QString(""); + QTest::newRow("Multitap with movement and maxlength") + << true + << Qt::InputMethodHints(Qt::ImhNoPredictiveText | Qt::ImhPreferLowercase) + << 2 + << QLineEdit::Normal + << events + << QString("wh") + << QString(""); + QTest::newRow("Numbers with movement and password") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 0 + << QLineEdit::Password + << events + << QString("96804488") + << QString(""); + QTest::newRow("Numbers with movement, maxlength and password") + << true + << Qt::InputMethodHints(Qt::ImhDigitsOnly) + << 2 + << QLineEdit::Password + << events + << QString("44") + << QString(""); + events.clear(); +#endif +} + +void tst_QInputContext::symbianTestCoeFepInputContext() +{ +#ifndef Q_OS_SYMBIAN + QSKIP("This is a Symbian-only test", SkipAll); +#else + QCoeFepInputContext *ic = qobject_cast(qApp->inputContext()); + if (!ic) { + QSKIP("coefep is not the active input context; skipping test", SkipAll); + } + + QFETCH(bool, inputMethodEnabled); + QFETCH(Qt::InputMethodHints, inputMethodHints); + QFETCH(int, maxLength); + QFETCH(QLineEdit::EchoMode, echoMode); + QFETCH(QList, keyEvents); + QFETCH(QString, finalString); + QFETCH(QString, preeditString); + + if (inputMethodEnabled && m_phoneIsQwerty) { + QSKIP("Skipping advanced input method tests on QWERTY phones", SkipSingle); + } + + QWidget w; + QLayout *layout = new QVBoxLayout; + w.setLayout(layout); + QLineEdit *lineedit = new QLineEdit; + layout->addWidget(lineedit); + lineedit->setFocus(); +#ifdef QT_KEYPAD_NAVIGATION + lineedit->setEditFocus(true); +#endif + w.show(); + + lineedit->setAttribute(Qt::WA_InputMethodEnabled, inputMethodEnabled); + lineedit->setInputMethodHints(inputMethodHints); + if (maxLength > 0) + lineedit->setMaxLength(maxLength); + lineedit->setEchoMode(echoMode); + + QTest::qWait(200); + + foreach(FepReplayEvent event, keyEvents) { + event.replay(lineedit); + } + + QApplication::processEvents(); + + QCOMPARE(lineedit->text(), finalString); + QEXPECT_FAIL("Numbers with movement, maxlength, password and unfinished text" + , "Fails due to QTBUG-12949" + , Continue); + QCOMPARE(ic->m_preeditString, preeditString); +#endif +} + QTEST_MAIN(tst_QInputContext) #include "tst_qinputcontext.moc" -- cgit v0.12 From b754ce6cef8931806175e9e7725087b46c04758f Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 1 Sep 2010 13:53:32 +0200 Subject: Fixed input context trying to squeeze content into a full widget. Problem was reproduced on N97. If the FEP detects that the widget is full while still editing text, it will try to send those events as key events instead. Since this screws up the content in the widget, we stop those events from reaching the widget in the input context. AutoTest: Passed Task: QTBUG-12949 RevBy: Miikka Heikkinen (cherry picked from commit 5ca6264933af60b3cd376b7f08bea008fa69b515) --- src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 7 +++++++ tests/auto/qinputcontext/tst_qinputcontext.cpp | 3 --- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 278f6d4..ce0c9ff 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -233,6 +233,13 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) break; } + QString widgetText = focusWidget()->inputMethodQuery(Qt::ImSurroundingText).toString(); + int maxLength = focusWidget()->inputMethodQuery(Qt::ImMaximumTextLength).toInt(); + if (!keyEvent->text().isEmpty() && widgetText.size() + m_preeditString.size() >= maxLength) { + // Don't send key events with string content if the widget is "full". + return true; + } + if (keyEvent->type() == QEvent::KeyPress && focusWidget()->inputMethodHints() & Qt::ImhHiddenText && !keyEvent->text().isEmpty()) { diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 23cfd9e..8eef2cc 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -933,9 +933,6 @@ void tst_QInputContext::symbianTestCoeFepInputContext() QApplication::processEvents(); QCOMPARE(lineedit->text(), finalString); - QEXPECT_FAIL("Numbers with movement, maxlength, password and unfinished text" - , "Fails due to QTBUG-12949" - , Continue); QCOMPARE(ic->m_preeditString, preeditString); #endif } -- cgit v0.12 From 688deeee6c8c2892becb4207f8c40dddba0e3769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Mon, 6 Sep 2010 12:36:36 +0200 Subject: Add missing license header Task-number: QT-3825 --- src/corelib/plugin/qsystemlibrary.cpp | 41 +++++++++++++++++++++++++++++++++++ src/corelib/plugin/qsystemlibrary_p.h | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp index f781770..a11ed50 100644 --- a/src/corelib/plugin/qsystemlibrary.cpp +++ b/src/corelib/plugin/qsystemlibrary.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qsystemlibrary_p.h" #include #include diff --git a/src/corelib/plugin/qsystemlibrary_p.h b/src/corelib/plugin/qsystemlibrary_p.h index 5d925ca..3251a3c 100644 --- a/src/corelib/plugin/qsystemlibrary_p.h +++ b/src/corelib/plugin/qsystemlibrary_p.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QSYSTEMLIBRARY_P_H #define QSYSTEMLIBRARY_P_H -- cgit v0.12