diff options
author | Alexis Menard <alexis.menard@trolltech.com> | 2011-06-23 09:59:51 (GMT) |
---|---|---|
committer | Alexis Menard <alexis.menard@trolltech.com> | 2011-06-23 09:59:51 (GMT) |
commit | e1c651f1284f1041ba5e03246686018e363d0e44 (patch) | |
tree | cb482b45dc7adcc15ed8f85901d52f0440ae6dbe | |
parent | 221fa23ed7307a42e576a6070e37d0152c6a8d08 (diff) | |
parent | fa0332ce6cec38e3ba9396c4c535e65cc8e10770 (diff) | |
download | Qt-e1c651f1284f1041ba5e03246686018e363d0e44.zip Qt-e1c651f1284f1041ba5e03246686018e363d0e44.tar.gz Qt-e1c651f1284f1041ba5e03246686018e363d0e44.tar.bz2 |
Merge branch '4.8' of git://gitorious.org/qt/qt into 4.8
90 files changed, 2459 insertions, 1166 deletions
diff --git a/config.tests/unix/ipc_posix/ipc.cpp b/config.tests/unix/ipc_posix/ipc.cpp new file mode 100644 index 0000000..fde8a99 --- /dev/null +++ b/config.tests/unix/ipc_posix/ipc.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests 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 <sys/types.h> +#include <sys/ipc.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <fcntl.h> + +int main(int, char **) +{ + sem_t *semaphore = sem_open("test", O_CREAT | O_EXCL, 0666, 0); + if (semaphore != SEM_FAILED) + sem_close(semaphore); + + shm_open("test", O_RDWR | O_CREAT | O_EXCL, 0666); + shm_unlink("test"); + + return 0; +} diff --git a/config.tests/unix/ipc_posix/ipc_posix.pro b/config.tests/unix/ipc_posix/ipc_posix.pro new file mode 100644 index 0000000..1b6de02 --- /dev/null +++ b/config.tests/unix/ipc_posix/ipc_posix.pro @@ -0,0 +1,3 @@ +SOURCES = ipc.cpp +CONFIG -= qt dylib +mac:CONFIG -= app_bundle diff --git a/config.tests/unix/ipc_sysv/ipc.cpp b/config.tests/unix/ipc_sysv/ipc.cpp new file mode 100644 index 0000000..7f04552 --- /dev/null +++ b/config.tests/unix/ipc_sysv/ipc.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests 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 <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <sys/shm.h> +#include <fcntl.h> + +int main(int, char **) +{ + key_t unix_key = ftok("test", 'Q'); + int semaphore = semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL); + if (semaphore != -1) + semctl(semaphore, 0, IPC_RMID, 0); + + shmget(unix_key, 0, 0666 | IPC_CREAT | IPC_EXCL); + shmctl(0, 0, static_cast<struct shmid_ds *>(0)); + + return 0; +} diff --git a/config.tests/unix/ipc_sysv/ipc_sysv.pro b/config.tests/unix/ipc_sysv/ipc_sysv.pro new file mode 100644 index 0000000..1b6de02 --- /dev/null +++ b/config.tests/unix/ipc_sysv/ipc_sysv.pro @@ -0,0 +1,3 @@ +SOURCES = ipc.cpp +CONFIG -= qt dylib +mac:CONFIG -= app_bundle @@ -5112,6 +5112,19 @@ if [ "$XPLATFORM_SYMBIAN" = "yes" ]; then fi fi +# check IPC support +if ! "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/ipc_sysv "ipc_sysv" $L_FLAGS $I_FLAGS $l_FLAGS ; then + # SYSV IPC is not supported - check POSIX IPC + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/ipc_posix "ipc_posix" $L_FLAGS $I_FLAGS $l_FLAGS ; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_POSIX_IPC" + else + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_SYSTEMSEMAPHORE QT_NO_SHAREDMEMORY" + if [ "$PLATFORM_QWS" = "yes" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_SEMAPHORE QT_NO_QWS_MULTIPROCESS QT_NO_QWS_SHARE_FONTS" + fi + fi +fi + # detect zlib if [ "$CFG_ZLIB" = "no" ]; then # Note: Qt no longer support builds without zlib diff --git a/dist/changes-4.8.0 b/dist/changes-4.8.0 index 1703633..02205b3 100644 --- a/dist/changes-4.8.0 +++ b/dist/changes-4.8.0 @@ -99,6 +99,8 @@ Qt for Mac OS X Qt for Embedded Linux --------------------- + - Added support for QNX 6.5 with multi-process support, and much improved mouse, + keyboard and screen drivers. Qt for Windows CE diff --git a/doc/src/platforms/platform-notes-rtos.qdoc b/doc/src/platforms/platform-notes-rtos.qdoc index 62d5add..0b1265b 100644 --- a/doc/src/platforms/platform-notes-rtos.qdoc +++ b/doc/src/platforms/platform-notes-rtos.qdoc @@ -160,7 +160,7 @@ X11 embedded server is not recommended due to missing support for X11 extensions, resulting in poor rendering quality. - Qt for QNX contains experimental screen and input drivers based on QNX's + Qt for QNX contains screen and input drivers based on QNX's \c devi-hid and \c io-display. For more information, check the class documentation for QQnxScreen, QWSQnxKeyboardHandler and QQnxMouseHandler. See the \l{Porting Qt for Embedded Linux to a New Architecture} document for information @@ -170,7 +170,7 @@ \section1 Supported Versions - Qt has been tested on QNX 6.4 on i386 and PowerPC targets with QNX's default + Qt has been tested on QNX 6.5 on i386, ARM/ARM-v7 and PowerPC targets with QNX's default gcc compiler. \section1 Limitations @@ -179,16 +179,12 @@ \table \header \o Function \o Notes - \row \o QProcess - \o Not available - QNX doesn't support mixing threads and processes. - \row \o QSharedMemory - \o Not available - QNX doesn't support SYSV style shared memory. - \row \o QSystemSemaphore - \o Not available - QNX doesn't support SYSV style system semaphores. - \row \o QWS Multi Process - \o QT_NO_QWS_MULTIPROCESS is always on due to missing shared memory support. \row \o Phonon \o There is no standard audio backend, which could be integrated into Phonon. + \row \o QtMultimedia + \o There is no standard backend, which could be integrated into QtMultimedia. + \row \o QtDBus + \o The the QtDBus library is not available on QNX. \row \o Qt3Support \o The Qt3Support library is not available on QNX. \endtable @@ -203,24 +199,25 @@ i386 QNX target: \code - configure -xplatform unsupported/qws/qnx-i386-g++ -embedded i386 -no-gfx-linuxfb -no-mouse-linuxtp -no-kbd-tty -no-qt3support -qt-gfx-qnx -qt-mouse-qnx -qt-kbd-qnx -no-exceptions + configure -xplatform unsupported/qws/qnx-i386-g++ -embedded x86 -no-gfx-linuxfb -no-mouse-linuxtp -no-kbd-tty -no-qt3support -qt-mouse-qnx -qt-kbd-qnx -qt-gfx-qnx -depths 16,24,32,generic -no-exceptions \endcode \list \o \c{-xplatform unsupported/qws/qnx-i386-g++} - selects the i386-g++ mkspec for QNX - \o \c{-embedded i386} - builds the embedded version of Qt and sets the architecture to i386 + \o \c{-embedded x86} - builds the embedded version of Qt and sets the architecture to i386 \o \c{-no-gfx-linuxfb}, \c{-no-mouse-linuxtp} and \c{-no-kbd-tty} are Linux specific and won't work on QNX \o \c{-no-qt3support} - required since the Qt3 support classes are not supported on QNX \o \c{-no-exceptions} - reduces the size of the library by disabling exception support - \o \c{-qt-gfx-qnx} - enables the experimental \c{io-graphics} based display driver - \o \c{-qt-mouse-qnx} - enables the experimental \c{devi-hig} based mouse driver - \o \c{-qt-kbd-qnx} - enables the experimental \c{devi-hig} based keyboard driver + \o \c{-qt-mouse-qnx} - enables the \c{devi-hid} based mouse driver + \o \c{-qt-kbd-qnx} - enables the \c{devi-hid} based keyboard driver + \o \c{-qt-gfx-qnx} - enables the \c{io-graphics} based screen driver + \o \c{-depths 16,24,32,generic} - enables all modes supported by the QNX screen driver \endlist \section1 General Notes \list - \o To enable the experimental QNX display and input drivers, \c{io-display} needs to be + \o To enable the QNX screen and input drivers, \c{io-display} needs to be up and running. The \c devi-hid based Qt input drivers require \c devi-hid to run in resource mode without Photon support. To enable a standard mouse and keyboard combination, run \c devi-hid as follows: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}. @@ -235,8 +232,8 @@ with a newer version, or disable the TIFF plugin entierly by appending \c{QT_CONFIG += no-tiff} to \c{.qmake.cache} after configuring Qt. - \o Some of the tools, examples and demos do not compile due to dependencies on QProcess - or other classes that are not available on QNX. + \o Some of the tools, examples and demos do not compile due to dependencies on classes + that are not available on QNX. \endlist \section1 Platform Regressions @@ -244,6 +241,14 @@ Qt for QNX's behavior is mostly identical with \l{Qt for Embedded Linux}. However, some regressions were spotted in QDateTime computation around year 0 and year 1970, which have been tracked back to faulty time zone data on some QNX versions. + + QString::localeAwareCompare() only works for C locale. + + QTranslator's default locale-based fallback mechanism doesn't work. + + QSystemSemaphore: Due to POSIX semaphores limitations, the semaphore operations aren't + automatically undone when the process terminates. This potentially may lead to unexpected + lock-ups in applications which does use the SysV semaphores behavior. */ /*! diff --git a/mkspecs/common/qnx/qmake.conf b/mkspecs/common/qnx/qmake.conf new file mode 100644 index 0000000..d241b61 --- /dev/null +++ b/mkspecs/common/qnx/qmake.conf @@ -0,0 +1,33 @@ +# +# qmake configuration common for qnx-g++ without X11 +# + +include(../gcc-base-unix.conf) +include(../g++-unix.conf) +include(../linux.conf) +include(../qws.conf) + +CONFIG += qnx +QT -= network + +QMAKE_COMPILER_DEFINES += __QNXNTO__ + +# modifications to linux.conf and qws.conf +QMAKE_LIBS = +QMAKE_LIBS_DYNLOAD = +QMAKE_LIBS_NIS = +QMAKE_LIBS_EGL = -lEGL +QMAKE_LIBS_OPENGL = $$QMAKE_LIBS_EGL -lGLESv1_CM -lGLESv2 +QMAKE_LIBS_OPENGL_QT = $$QMAKE_LIBS_OPENGL +QMAKE_LIBS_OPENGL_ES1 = $$QMAKE_LIBS_EGL -lGLESv1_CM +QMAKE_LIBS_OPENGL_ES2 = $$QMAKE_LIBS_EGL -lGLESv2 +QMAKE_LIBS_OPENVG = $$QMAKE_LIBS_EGL -lOpenVG +QMAKE_LIBS_THREAD = + +QMAKE_LIBS_CORE = +QMAKE_LIBS_NETWORK += -lsocket +QMAKE_LIBS_GUI += -lsocket + +# QNX doesn't have install +QMAKE_INSTALL_FILE = +QMAKE_INSTALL_PROGRAM = diff --git a/mkspecs/common/qnx/qplatformdefs.h b/mkspecs/common/qnx/qplatformdefs.h new file mode 100644 index 0000000..bf7a0a0 --- /dev/null +++ b/mkspecs/common/qnx/qplatformdefs.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake spec 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 QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +// Get Qt defines/settings +#include <qglobal.h> + +// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs + +#include <unistd.h> + +// We are hot - unistd.h should have turned on the specific APIs we requested + +#include <pthread.h> +#include <dirent.h> +#include <fcntl.h> +#include <grp.h> +#include <pwd.h> +#include <signal.h> + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/ipc.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <netinet/in.h> +#ifndef QT_NO_IPV6IFNAME +#include <net/if.h> +#endif + +// for htonl +#include <arpa/inet.h> + +#define QT_USE_XOPEN_LFS_EXTENSIONS +#define QT_NO_READDIR64 +#include "../posix/qplatformdefs.h" + +#include <stdlib.h> + +#define QT_SNPRINTF ::snprintf +#define QT_VSNPRINTF ::vsnprintf + + +#include <sys/neutrino.h> + +#if !defined(_NTO_VERSION) || _NTO_VERSION < 650 +// pre-6.5 versions of QNX doesn't have getpagesize() +inline int getpagesize() +{ + return ::sysconf(_SC_PAGESIZE); +} + +// pre-6.5 versions of QNX doesn't have strtof() +inline float strtof(const char *b, char **e) +{ + return float(strtod(b, e)); +} +#endif + +#define QT_QWS_TEMP_DIR QString::fromLocal8Bit(qgetenv("TMPDIR").constData()) + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/unsupported/qnx-g++/qmake.conf b/mkspecs/unsupported/qnx-g++/qmake.conf index 83c4a26..e354b2c 100644 --- a/mkspecs/unsupported/qnx-g++/qmake.conf +++ b/mkspecs/unsupported/qnx-g++/qmake.conf @@ -4,58 +4,16 @@ # Written for QNX RTOS v6 with X11 # -MAKEFILE_GENERATOR = UNIX -TARGET_PLATFORM = unix -TEMPLATE = app -CONFIG += qt warn_on release link_prl -QT += core gui +include(../../common/qnx/qmake.conf) -include(../common/gcc-base-unix.conf) -include(../common/g++-unix.conf) -include(../common/unix.conf) - -QMAKE_CFLAGS_THREAD = -D_REENTRANT -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CLFAGS_THREAD -QMAKE_COMPILER_DEFINES += __QNXNTO__ - -QMAKE_INCDIR = -QMAKE_LIBDIR = QMAKE_INCDIR_X11 = /opt/X11R6/include QMAKE_LIBDIR_X11 = /opt/X11R6/lib -QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS] -QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS] QMAKE_INCDIR_OPENGL = /opt/X11R6/include QMAKE_LIBDIR_OPENGL = /opt/X11R6/lib -#QMAKE_LIBS = -lunix -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = QMAKE_LIBS_X11 = -lXext -lX11 -lm -lsocket QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL -QMAKE_LIBS_THREAD = -QMAKE_LIBS_NETWORK = -lsocket - -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - -QMAKE_AR = ar cqs -QMAKE_RANLIB = - -QMAKE_TAR = tar -cf -QMAKE_GZIP = gzip -9f -QMAKE_COPY = cp -f -QMAKE_COPY_FILE = $(COPY) -QMAKE_COPY_DIR = $(COPY) -r -QMAKE_MOVE = mv -f -QMAKE_DEL_FILE = rm -f -QMAKE_DEL_DIR = rmdir -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p -QMAKE_STRIP = strip -QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p load(qt_config) diff --git a/mkspecs/unsupported/qnx-g++/qplatformdefs.h b/mkspecs/unsupported/qnx-g++/qplatformdefs.h index 8b50f92..34c1525 100644 --- a/mkspecs/unsupported/qnx-g++/qplatformdefs.h +++ b/mkspecs/unsupported/qnx-g++/qplatformdefs.h @@ -39,68 +39,4 @@ ** ****************************************************************************/ -#ifndef QPLATFORMDEFS_H -#define QPLATFORMDEFS_H - -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -#include <unistd.h> - - -// We are hot - unistd.h should have turned on the specific APIs we requested - - -#include <pthread.h> -#include <dirent.h> -#include <fcntl.h> -#include <grp.h> -#include <pwd.h> -#include <signal.h> - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/ipc.h> -#include <sys/time.h> -// QNX doesn't have the System V <sys/shm.h> header. This is not a standard -// POSIX header, it's only documented in the Single UNIX Specification. -// The preferred POSIX compliant way to share memory is to use the functions -// in <sys/mman.h> that comply with the POSIX Real Time Interface (1003.1b). -#include <sys/mman.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <netinet/in.h> -#ifndef QT_NO_IPV6IFNAME -#include <net/if.h> -#endif - -// for htonl -#include <arpa/inet.h> - -#define QT_USE_XOPEN_LFS_EXTENSIONS -#include "../../common/posix/qplatformdefs.h" - -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf - -// QNX6 doesn't have getpagesize() -inline int getpagesize() -{ - return ::sysconf(_SC_PAGESIZE); -} - -#include <stdlib.h> - -// QNX6 doesn't have strtof - use strtod instead -inline float strtof(const char *b, char **e) -{ - return float(strtod(b, e)); -} - -#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP")) - -#endif // QPLATFORMDEFS_H +#include "../../common/qnx/qplatformdefs.h" diff --git a/mkspecs/unsupported/qws/qnx-641/qmake.conf b/mkspecs/unsupported/qws/qnx-641/qmake.conf index 441f408..304ac67 100644 --- a/mkspecs/unsupported/qws/qnx-641/qmake.conf +++ b/mkspecs/unsupported/qws/qnx-641/qmake.conf @@ -59,7 +59,7 @@ QMAKE_PCH_OUTPUT_EXT = .gch QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions QMAKE_LFLAGS_DYNAMIC_LIST = -Wl,--dynamic-list, -include(../../common/unix.conf) +include(../../../common/unix.conf) QMAKE_CFLAGS_THREAD = -D_REENTRANT QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD diff --git a/mkspecs/unsupported/qws/qnx-641/qplatformdefs.h b/mkspecs/unsupported/qws/qnx-641/qplatformdefs.h index 0c71265..ea04d0f 100644 --- a/mkspecs/unsupported/qws/qnx-641/qplatformdefs.h +++ b/mkspecs/unsupported/qws/qnx-641/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../../qnx-g++/qplatformdefs.h" +#include "../../../common/qnx/qplatformdefs.h" diff --git a/mkspecs/unsupported/qws/qnx-arm-g++/qmake.conf b/mkspecs/unsupported/qws/qnx-arm-g++/qmake.conf new file mode 100644 index 0000000..b9f946e --- /dev/null +++ b/mkspecs/unsupported/qws/qnx-arm-g++/qmake.conf @@ -0,0 +1,32 @@ +# +# qmake configuration for qnx-arm-g++ +# +# Written for QNX RTOS v6 +# + +include(../../../common/qnx/qmake.conf) + +# modifications to gcc-base.conf and g++-base.conf + +#Bug in arm compiler for QNX +QMAKE_CFLAGS_RELEASE = -O1 +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -O1 -g + +QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE +QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO + +QMAKE_CC = ntoarm-gcc +QMAKE_CXX = ntoarm-g++ + +QMAKE_LINK = ntoarm-g++ +QMAKE_LINK_SHLIB = $$QMAKE_LINK +QMAKE_LINK_C = ntoarm-gcc +QMAKE_LINK_C_SHLIB = $$QMAKE_LINK_C + +# modifications to linux.conf +QMAKE_AR = ntoarm-ar cqs +QMAKE_STRIP = ntoarm-strip +QMAKE_RANLIB = ntoarm-ranlib +QMAKE_OBJCOPY = ntoarm-objcopy + +load(qt_config) diff --git a/mkspecs/unsupported/qws/qnx-arm-g++/qplatformdefs.h b/mkspecs/unsupported/qws/qnx-arm-g++/qplatformdefs.h new file mode 100644 index 0000000..5817a53 --- /dev/null +++ b/mkspecs/unsupported/qws/qnx-arm-g++/qplatformdefs.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake spec 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 "../../../common/qnx/qplatformdefs.h" diff --git a/mkspecs/unsupported/qws/qnx-armv7-g++/qmake.conf b/mkspecs/unsupported/qws/qnx-armv7-g++/qmake.conf new file mode 100644 index 0000000..c6763d5 --- /dev/null +++ b/mkspecs/unsupported/qws/qnx-armv7-g++/qmake.conf @@ -0,0 +1,32 @@ +# +# qmake configuration for qnx-armv7-g++ +# +# Written for QNX RTOS v6 +# + +include(../../../common/qnx/qmake.conf) + +# modifications to gcc-base.conf and g++-base.conf + +# note: on the NVidia Tegra 2 and on the Marvell Dovecott, '-mfpu=neon' should be removed +QMAKE_CFLAGS_RELEASE = -O3 -march=armv7-a -mfpu=neon -mfloat-abi=softfp +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -O3 -g -march=armv7-a -mfpu=neon -mfloat-abi=softfp + +QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE +QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO + +QMAKE_CC = ntoarmv7-gcc +QMAKE_CXX = ntoarmv7-g++ + +QMAKE_LINK = ntoarmv7-g++ +QMAKE_LINK_SHLIB = $$QMAKE_LINK +QMAKE_LINK_C = ntoarmv7-gcc +QMAKE_LINK_C_SHLIB = $$QMAKE_LINK_C + +# modifications to linux.conf +QMAKE_AR = ntoarmv7-ar cqs +QMAKE_STRIP = ntoarmv7-strip +QMAKE_RANLIB = ntoarmv7-ranlib +QMAKE_OBJCOPY = ntoarmv7-objcopy + +load(qt_config) diff --git a/mkspecs/unsupported/qws/qnx-armv7-g++/qplatformdefs.h b/mkspecs/unsupported/qws/qnx-armv7-g++/qplatformdefs.h new file mode 100644 index 0000000..5817a53 --- /dev/null +++ b/mkspecs/unsupported/qws/qnx-armv7-g++/qplatformdefs.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake spec 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 "../../../common/qnx/qplatformdefs.h" diff --git a/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf b/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf index bb760b2..f5e7045 100644 --- a/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf +++ b/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf @@ -1,102 +1,24 @@ # -# qmake configuration for qnx-g++ +# qmake configuration for qnx-generic-g++ # # Written for QNX RTOS v6 # -MAKEFILE_GENERATOR = UNIX -TARGET_PLATFORM = unix -TEMPLATE = app -CONFIG += qt warn_on release link_prl -QT += core gui +include(../../../common/qnx/qmake.conf) -# -# qmake configuration for common gcc -# - -QMAKE_CC = ntox86-gcc-3.3.5 -QMAKE_CFLAGS += -pipe -QMAKE_CFLAGS_DEPS += -M -QMAKE_CFLAGS_WARN_ON += -Wall -W -QMAKE_CFLAGS_WARN_OFF += -w -QMAKE_CFLAGS_RELEASE += -O2 -QMAKE_CFLAGS_DEBUG += -g -QMAKE_CFLAGS_SHLIB += -fPIC -QMAKE_CFLAGS_STATIC_LIB += -fPIC -QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses -QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden -QMAKE_CFLAGS_PRECOMPILE += -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CFLAGS_USE_PRECOMPILE += -include ${QMAKE_PCH_OUTPUT_BASE} -QMAKE_COMPILER_DEFINES += __QNXNTO__ - -QMAKE_CXX = ntox86-g++-3.3.5 -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS -QMAKE_CXXFLAGS_WARN_ON += $$QMAKE_CFLAGS_WARN_ON -QMAKE_CXXFLAGS_WARN_OFF += $$QMAKE_CFLAGS_WARN_OFF -QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE -QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_DEBUG -QMAKE_CXXFLAGS_SHLIB += $$QMAKE_CFLAGS_SHLIB -QMAKE_CXXFLAGS_STATIC_LIB += $$QMAKE_CFLAGS_STATIC_LIB -QMAKE_CXXFLAGS_YACC += $$QMAKE_CFLAGS_YACC -QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden -QMAKE_CXXFLAGS_PRECOMPILE += -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE - -QMAKE_LINK = ntox86-gcc-3.3.5 -QMAKE_LINK_SHLIB = ntox86-gcc-3.3.5 -QMAKE_LFLAGS += -Wl,--no-undefined -QMAKE_LFLAGS_RELEASE += -QMAKE_LFLAGS_DEBUG += -QMAKE_LFLAGS_APP += -QMAKE_LFLAGS_SHLIB += -shared -QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_SONAME += -Wl,-soname, -QMAKE_LFLAGS_THREAD += -QMAKE_LFLAGS_RPATH = -Wl,-rpath, - -QMAKE_PCH_OUTPUT_EXT = .gch - -# -Bsymbolic-functions (ld) support -QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions -QMAKE_LFLAGS_DYNAMIC_LIST = -Wl,--dynamic-list, - -include(../../common/unix.conf) - -QMAKE_CFLAGS_THREAD = -D_REENTRANT -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CLFAGS_THREAD - -QMAKE_INCDIR = -QMAKE_LIBDIR = -QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS] -QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS] - -#QMAKE_LIBS = -lunix -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_THREAD = -QMAKE_LIBS_NETWORK += -lsocket -QMAKE_LIBS_GUI += -lsocket - -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic +# derived from g++-base.conf +#QMAKE_CC = gcc +#QMAKE_CXX = g++ -QMAKE_AR = ar cqs -QMAKE_RANLIB = +#QMAKE_LINK = g++ +#QMAKE_LINK_SHLIB = g++ +#QMAKE_LINK_C = gcc +#QMAKE_LINK_C_SHLIB = gcc -QMAKE_TAR = tar -cf -QMAKE_GZIP = gzip -9f +# derived from linux.conf +#QMAKE_AR = ar cqs +#QMAKE_OBJCOPY = objcopy +#QMAKE_RANLIB = +#QMAKE_STRIP = strip -QMAKE_COPY = cp -f -QMAKE_COPY_FILE = $(COPY) -QMAKE_COPY_DIR = $(COPY) -r -QMAKE_MOVE = mv -f -QMAKE_DEL_FILE = rm -f -QMAKE_DEL_DIR = rmdir -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p -QMAKE_STRIP = strip -QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p load(qt_config) diff --git a/mkspecs/unsupported/qws/qnx-generic-g++/qplatformdefs.h b/mkspecs/unsupported/qws/qnx-generic-g++/qplatformdefs.h index 0c71265..ea04d0f 100644 --- a/mkspecs/unsupported/qws/qnx-generic-g++/qplatformdefs.h +++ b/mkspecs/unsupported/qws/qnx-generic-g++/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../../qnx-g++/qplatformdefs.h" +#include "../../../common/qnx/qplatformdefs.h" diff --git a/mkspecs/unsupported/qws/qnx-i386-g++/qmake.conf b/mkspecs/unsupported/qws/qnx-i386-g++/qmake.conf index b43c391..6940bd8 100644 --- a/mkspecs/unsupported/qws/qnx-i386-g++/qmake.conf +++ b/mkspecs/unsupported/qws/qnx-i386-g++/qmake.conf @@ -1,98 +1,24 @@ # -# qmake configuration for qnx-g++ +# qmake configuration for qnx-i386-g++ # # Written for QNX RTOS v6 # -MAKEFILE_GENERATOR = UNIX -TARGET_PLATFORM = unix -TEMPLATE = app -CONFIG += qt warn_on release link_prl -QT += core gui +include(../../../common/qnx/qmake.conf) -QMAKE_CC = ntox86-gcc-4.2.4 -QMAKE_CFLAGS += -pipe -QMAKE_CFLAGS_DEPS += -M -QMAKE_CFLAGS_WARN_ON += -Wall -W -QMAKE_CFLAGS_WARN_OFF += -w -QMAKE_CFLAGS_RELEASE += -O2 -QMAKE_CFLAGS_DEBUG += -g -QMAKE_CFLAGS_SHLIB += -fPIC -QMAKE_CFLAGS_STATIC_LIB += -fPIC -QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses -QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden -QMAKE_CFLAGS_PRECOMPILE += -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CFLAGS_USE_PRECOMPILE += -include ${QMAKE_PCH_OUTPUT_BASE} -QMAKE_COMPILER_DEFINES += __QNXNTO__ +# modifications to g++-base.conf +QMAKE_CC = ntox86-gcc +QMAKE_CXX = ntox86-g++ -QMAKE_CXX = ntox86-g++-4.2.4 -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS -QMAKE_CXXFLAGS_WARN_ON += $$QMAKE_CFLAGS_WARN_ON -QMAKE_CXXFLAGS_WARN_OFF += $$QMAKE_CFLAGS_WARN_OFF -QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE -QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_DEBUG -QMAKE_CXXFLAGS_SHLIB += $$QMAKE_CFLAGS_SHLIB -QMAKE_CXXFLAGS_STATIC_LIB += $$QMAKE_CFLAGS_STATIC_LIB -QMAKE_CXXFLAGS_YACC += $$QMAKE_CFLAGS_YACC -QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden -QMAKE_CXXFLAGS_PRECOMPILE += -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE +QMAKE_LINK = ntox86-g++ +QMAKE_LINK_SHLIB = $$QMAKE_LINK +QMAKE_LINK_C = ntox86-gcc +QMAKE_LINK_C_SHLIB = $$QMAKE_LINK_C -QMAKE_LINK = ntox86-g++-4.2.4 -QMAKE_LINK_SHLIB = ntox86-g++-4.2.4 -QMAKE_LFLAGS += -Wl,--no-undefined -QMAKE_LFLAGS_RELEASE += -QMAKE_LFLAGS_DEBUG += -QMAKE_LFLAGS_APP += -QMAKE_LFLAGS_SHLIB += -shared -QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_SONAME += -Wl,-soname, -QMAKE_LFLAGS_THREAD += -QMAKE_LFLAGS_RPATH = -Wl,-rpath, +# modifications to linux.conf +QMAKE_AR = ntox86-ar cqs +QMAKE_OBJCOPY = ntox86-objcopy +QMAKE_RANLIB = ntox86-ranlib +QMAKE_STRIP = ntox86-strip -QMAKE_PCH_OUTPUT_EXT = .gch - -# -Bsymbolic-functions (ld) support -QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions -QMAKE_LFLAGS_DYNAMIC_LIST = -Wl,--dynamic-list, - -include(../../../common/unix.conf) - -QMAKE_CFLAGS_THREAD = -D_REENTRANT -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD - -QMAKE_INCDIR = -QMAKE_LIBDIR = -QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS] -QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS] - -#QMAKE_LIBS = -lunix -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_THREAD = -QMAKE_LIBS_NETWORK += -lsocket -QMAKE_LIBS_GUI += -lsocket - -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - -QMAKE_AR = ar cqs -QMAKE_RANLIB = - -QMAKE_TAR = tar -cf -QMAKE_GZIP = gzip -9f - -QMAKE_COPY = cp -f -QMAKE_COPY_FILE = $(COPY) -QMAKE_COPY_DIR = $(COPY) -r -QMAKE_MOVE = mv -f -QMAKE_DEL_FILE = rm -f -QMAKE_DEL_DIR = rmdir -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p -QMAKE_STRIP = strip -QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p load(qt_config) diff --git a/mkspecs/unsupported/qws/qnx-i386-g++/qplatformdefs.h b/mkspecs/unsupported/qws/qnx-i386-g++/qplatformdefs.h index 0c71265..ea04d0f 100644 --- a/mkspecs/unsupported/qws/qnx-i386-g++/qplatformdefs.h +++ b/mkspecs/unsupported/qws/qnx-i386-g++/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../../qnx-g++/qplatformdefs.h" +#include "../../../common/qnx/qplatformdefs.h" diff --git a/mkspecs/unsupported/qws/qnx-ppc-g++/qmake.conf b/mkspecs/unsupported/qws/qnx-ppc-g++/qmake.conf index 29a2952..cb4d391 100644 --- a/mkspecs/unsupported/qws/qnx-ppc-g++/qmake.conf +++ b/mkspecs/unsupported/qws/qnx-ppc-g++/qmake.conf @@ -1,98 +1,24 @@ # -# qmake configuration for qnx-g++ +# qmake configuration for qnx-ppc-g++ # # Written for QNX RTOS v6 # -MAKEFILE_GENERATOR = UNIX -TARGET_PLATFORM = unix -TEMPLATE = app -CONFIG += qt warn_on release link_prl -QT += core gui +include(../../../common/qnx/qmake.conf) -QMAKE_CC = ntoppc-gcc-4.3.3 -QMAKE_CFLAGS += -pipe -QMAKE_CFLAGS_DEPS += -M -QMAKE_CFLAGS_WARN_ON += -Wall -W -QMAKE_CFLAGS_WARN_OFF += -w -QMAKE_CFLAGS_RELEASE += -O2 -QMAKE_CFLAGS_DEBUG += -g -QMAKE_CFLAGS_SHLIB += -fPIC -QMAKE_CFLAGS_STATIC_LIB += -fPIC -QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses -QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden -QMAKE_CFLAGS_PRECOMPILE += -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CFLAGS_USE_PRECOMPILE += -include ${QMAKE_PCH_OUTPUT_BASE} -QMAKE_COMPILER_DEFINES += __QNXNTO__ +# modifications to g++-base.conf +QMAKE_CC = ntoppc-gcc +QMAKE_CXX = ntoppc-g++ -QMAKE_CXX = ntoppc-g++-4.3.3 -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS -QMAKE_CXXFLAGS_WARN_ON += $$QMAKE_CFLAGS_WARN_ON -QMAKE_CXXFLAGS_WARN_OFF += $$QMAKE_CFLAGS_WARN_OFF -QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE -QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_DEBUG -QMAKE_CXXFLAGS_SHLIB += $$QMAKE_CFLAGS_SHLIB -QMAKE_CXXFLAGS_STATIC_LIB += $$QMAKE_CFLAGS_STATIC_LIB -QMAKE_CXXFLAGS_YACC += $$QMAKE_CFLAGS_YACC -QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden -QMAKE_CXXFLAGS_PRECOMPILE += -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE +QMAKE_LINK = ntoppc-g++ +QMAKE_LINK_SHLIB = $$QMAKE_LINK +QMAKE_LINK_C = ntoppc-gcc +QMAKE_LINK_C_SHLIB = $$QMAKE_LINK_C -QMAKE_LINK = ntoppc-g++-4.3.3 -QMAKE_LINK_SHLIB = ntoppc-g++-4.3.3 -QMAKE_LFLAGS += -Wl,--no-undefined -QMAKE_LFLAGS_RELEASE += -QMAKE_LFLAGS_DEBUG += -QMAKE_LFLAGS_APP += -QMAKE_LFLAGS_SHLIB += -shared -QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_SONAME += -Wl,-soname, -QMAKE_LFLAGS_THREAD += -QMAKE_LFLAGS_RPATH = -Wl,-rpath, +# modifications to linux.conf +QMAKE_AR = ntoppc-ar cqs +QMAKE_STRIP = ntoppc-strip +QMAKE_RANLIB = ntoppc-ranlib +QMAKE_OBJCOPY = ntoppc-objcopy -QMAKE_PCH_OUTPUT_EXT = .gch - -# -Bsymbolic-functions (ld) support -QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions -QMAKE_LFLAGS_DYNAMIC_LIST = -Wl,--dynamic-list, - -include(../../common/unix.conf) - -QMAKE_CFLAGS_THREAD = -D_REENTRANT -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CLFAGS_THREAD - -QMAKE_INCDIR = -QMAKE_LIBDIR = -QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS] -QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS] - -#QMAKE_LIBS = -lunix -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_THREAD = -QMAKE_LIBS_NETWORK += -lsocket -QMAKE_LIBS_GUI += -lsocket - -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - -QMAKE_AR = ar cqs -QMAKE_RANLIB = - -QMAKE_TAR = tar -cf -QMAKE_GZIP = gzip -9f - -QMAKE_COPY = cp -f -QMAKE_COPY_FILE = $(COPY) -QMAKE_COPY_DIR = $(COPY) -r -QMAKE_MOVE = mv -f -QMAKE_DEL_FILE = rm -f -QMAKE_DEL_DIR = rmdir -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p -QMAKE_STRIP = strip -QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p load(qt_config) diff --git a/mkspecs/unsupported/qws/qnx-ppc-g++/qplatformdefs.h b/mkspecs/unsupported/qws/qnx-ppc-g++/qplatformdefs.h index 0c71265..ea04d0f 100644 --- a/mkspecs/unsupported/qws/qnx-ppc-g++/qplatformdefs.h +++ b/mkspecs/unsupported/qws/qnx-ppc-g++/qplatformdefs.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../../qnx-g++/qplatformdefs.h" +#include "../../../common/qnx/qplatformdefs.h" diff --git a/qmake/qmake.pri b/qmake/qmake.pri index d6c5f09..87735d6 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -146,7 +146,7 @@ bootstrap { #Qt code qnx { CFLAGS += -fhonor-std - LFLAGS += -lcpp + LFLAGS += -lcpp -lm } DEFINES *= QT_NO_QOBJECT } else { diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 32b3e6b..1f5f537 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -173,7 +173,6 @@ namespace QT_NAMESPACE {} RELIANT - Reliant UNIX DYNIX - DYNIX/ptx QNX - QNX - QNX6 - QNX RTP 6.1 LYNX - LynxOS BSD4 - Any BSD 4.4 system UNIX - Any UNIX BSD/SYSV system @@ -2746,17 +2745,6 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_CONCURRENT_FILTER #endif -#ifdef Q_OS_QNX -// QNX doesn't have SYSV style shared memory. Multiprocess QWS apps, -// shared fonts and QSystemSemaphore + QSharedMemory are not available -# define QT_NO_QWS_MULTIPROCESS -# define QT_NO_QWS_SHARE_FONTS -# define QT_NO_SYSTEMSEMAPHORE -# define QT_NO_SHAREDMEMORY -// QNX currently doesn't support forking in a thread, so disable QProcess -# define QT_NO_PROCESS -#endif - #if defined (__ELF__) # if defined (Q_OS_LINUX) || defined (Q_OS_SOLARIS) || defined (Q_OS_FREEBSD) || defined (Q_OS_OPENBSD) || defined (Q_OS_IRIX) # define Q_OF_ELF diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 70a70c2..4b689c5 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -751,12 +751,16 @@ QProcessPrivate::QProcessPrivate() sequenceNumber = 0; exitCode = 0; exitStatus = QProcess::NormalExit; +#ifndef Q_OS_QNX startupSocketNotifier = 0; +#endif deathNotifier = 0; notifier = 0; pipeWriter = 0; +#ifndef Q_OS_QNX childStartedPipe[0] = INVALID_Q_PIPE; childStartedPipe[1] = INVALID_Q_PIPE; +#endif deathPipe[0] = INVALID_Q_PIPE; deathPipe[1] = INVALID_Q_PIPE; exitCode = 0; @@ -825,11 +829,13 @@ void QProcessPrivate::cleanup() qDeleteInEventHandler(stdinChannel.notifier); stdinChannel.notifier = 0; } +#ifndef Q_OS_QNX if (startupSocketNotifier) { startupSocketNotifier->setEnabled(false); qDeleteInEventHandler(startupSocketNotifier); startupSocketNotifier = 0; } +#endif if (deathNotifier) { deathNotifier->setEnabled(false); qDeleteInEventHandler(deathNotifier); @@ -842,7 +848,9 @@ void QProcessPrivate::cleanup() destroyPipe(stdoutChannel.pipe); destroyPipe(stderrChannel.pipe); destroyPipe(stdinChannel.pipe); +#ifndef Q_OS_QNX destroyPipe(childStartedPipe); +#endif destroyPipe(deathPipe); #ifdef Q_OS_UNIX serial = 0; @@ -1077,8 +1085,10 @@ bool QProcessPrivate::_q_startupNotification() qDebug("QProcessPrivate::startupNotification()"); #endif +#ifndef Q_OS_QNX if (startupSocketNotifier) startupSocketNotifier->setEnabled(false); +#endif if (processStarted()) { q->setProcessState(QProcess::Running); emit q->started(); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 9adb331..f24a7bc 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -288,11 +288,15 @@ public: QRingBuffer errorReadBuffer; QRingBuffer writeBuffer; +#ifndef Q_OS_QNX Q_PIPE childStartedPipe[2]; +#endif Q_PIPE deathPipe[2]; void destroyPipe(Q_PIPE pipe[2]); +#ifndef Q_OS_QNX QSocketNotifier *startupSocketNotifier; +#endif QSocketNotifier *deathNotifier; // the wonderful windows notifier @@ -301,8 +305,10 @@ public: QWinEventNotifier *processFinishedNotifier; void startProcess(); -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_QNX) void execChild(const char *workingDirectory, char **path, char **argv, char **envp); +#elif defined(Q_OS_QNX) + pid_t spawnChild(const char *workingDirectory, char **argv, char **envp); #endif bool processStarted(); void terminateProcess(); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 07e3087..725e4c5 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -105,6 +105,10 @@ QT_END_NAMESPACE #include <errno.h> #include <stdlib.h> #include <string.h> +#ifdef Q_OS_QNX +# include <spawn.h> +#endif + QT_BEGIN_NAMESPACE @@ -521,16 +525,6 @@ static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environm return envp; } -// under QNX RTOS we have to use vfork() when multithreading -inline pid_t qt_fork() -{ -#if defined(Q_OS_QNX) - return vfork(); -#else - return fork(); -#endif -} - #ifdef Q_OS_MAC Q_GLOBAL_STATIC(QMutex, cfbundleMutex); #endif @@ -550,15 +544,18 @@ void QProcessPrivate::startProcess() !createChannel(stdoutChannel) || !createChannel(stderrChannel)) return; +#if !defined(Q_OS_QNX) qt_create_pipe(childStartedPipe); +#endif qt_create_pipe(deathPipe); if (threadData->eventDispatcher) { +#if !defined(Q_OS_QNX) startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], QSocketNotifier::Read, q); QObject::connect(startupSocketNotifier, SIGNAL(activated(int)), q, SLOT(_q_startupNotification())); - +#endif deathNotifier = new QSocketNotifier(deathPipe[0], QSocketNotifier::Read, q); QObject::connect(deathNotifier, SIGNAL(activated(int)), @@ -650,7 +647,11 @@ void QProcessPrivate::startProcess() // Start the process manager, and fork off the child process. processManager()->lock(); - pid_t childPid = qt_fork(); +#if defined(Q_OS_QNX) + pid_t childPid = spawnChild(workingDirPtr, argv, envp); +#else + pid_t childPid = fork(); +#endif int lastForkErrno = errno; if (childPid != 0) { // Clean up duplicated memory. @@ -668,7 +669,7 @@ void QProcessPrivate::startProcess() if (childPid < 0) { // Cleanup, report error and return #if defined (QPROCESS_DEBUG) - qDebug("qt_fork failed: %s", qPrintable(qt_error_string(lastForkErrno))); + qDebug("fork() failed: %s", qPrintable(qt_error_string(lastForkErrno))); #endif processManager()->unlock(); q->setProcessState(QProcess::NotRunning); @@ -679,11 +680,13 @@ void QProcessPrivate::startProcess() return; } +#if !defined(Q_OS_QNX) // Start the child. if (childPid == 0) { execChild(workingDirPtr, path, argv, envp); ::_exit(-1); } +#endif // Register the child. In the mean time, we can get a SIGCHLD, so we need // to keep the lock held to avoid a race to catch the child. @@ -694,14 +697,15 @@ void QProcessPrivate::startProcess() // parent // close the ends we don't use and make all pipes non-blocking ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK); +#if !defined(Q_OS_QNX) qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; +#endif if (stdinChannel.pipe[0] != -1) { qt_safe_close(stdinChannel.pipe[0]); stdinChannel.pipe[0] = -1; } - if (stdinChannel.pipe[1] != -1) ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK); @@ -709,7 +713,6 @@ void QProcessPrivate::startProcess() qt_safe_close(stdoutChannel.pipe[1]); stdoutChannel.pipe[1] = -1; } - if (stdoutChannel.pipe[0] != -1) ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK); @@ -721,6 +724,7 @@ void QProcessPrivate::startProcess() ::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK); } +#if !defined(Q_OS_QNX) void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp) { ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored @@ -728,17 +732,17 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv Q_Q(QProcess); // copy the stdin socket (without closing on exec) - qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); + qt_safe_dup2(stdinChannel.pipe[0], QT_FILENO(stdin), 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { - qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); + qt_safe_dup2(stdoutChannel.pipe[1], QT_FILENO(stdout), 0); // merge stdout and stderr if asked to if (processChannelMode == QProcess::MergedChannels) { - qt_safe_dup2(fileno(stdout), fileno(stderr), 0); + qt_safe_dup2(QT_FILENO(stdout), QT_FILENO(stderr), 0); } else { - qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); + qt_safe_dup2(stderrChannel.pipe[1], QT_FILENO(stderr), 0); } } @@ -807,6 +811,87 @@ bool QProcessPrivate::processStarted() return i <= 0; } +#else // Q_OS_QNX + +static pid_t doSpawn(int fd_count, int fd_map[], char **argv, char **envp, bool spawn_detached) +{ + // A multi threaded QNX Process can't fork so we call spawn() instead. + + struct inheritance inherit; + memset(&inherit, 0, sizeof(inherit)); + inherit.flags |= SPAWN_SETSID; + inherit.flags |= SPAWN_CHECK_SCRIPT; + if (spawn_detached) + inherit.flags |= SPAWN_NOZOMBIE; + inherit.flags |= SPAWN_SETSIGDEF; + sigaddset(&inherit.sigdefault, SIGPIPE); // reset the signal that we ignored + + pid_t childPid; + EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); + if (childPid == -1) { + inherit.flags |= SPAWN_SEARCH_PATH; + EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); + } + + return childPid; +} + +pid_t QProcessPrivate::spawnChild(const char *workingDir, char **argv, char **envp) +{ + Q_Q(QProcess); + + const int fd_count = 3; + int fd_map[fd_count]; + switch (processChannelMode) { + case QProcess::ForwardedChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = QT_FILENO(stdout); + fd_map[2] = QT_FILENO(stderr); + break; + case QProcess::MergedChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = stdoutChannel.pipe[1]; + fd_map[2] = stdoutChannel.pipe[1]; + break; + case QProcess::SeparateChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = stdoutChannel.pipe[1]; + fd_map[2] = stderrChannel.pipe[1]; + break; + } + + // enter the working directory + char *oldWorkingDir = 0; + char buff[PATH_MAX + 1]; + if (workingDir) { + oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1); + QT_CHDIR(workingDir); + } + + pid_t childPid = doSpawn(fd_count, fd_map, argv, envp, false); + + if (oldWorkingDir) + QT_CHDIR(oldWorkingDir); + + if (childPid != -1) { + q->setProcessState(QProcess::Running); + QMetaObject::invokeMethod(q, "_q_startupNotification", Qt::QueuedConnection); + } + + return childPid; +} + +bool QProcessPrivate::processStarted() +{ + return processState == QProcess::Running; +} + +bool QProcessPrivate::waitForStarted(int /*msecs*/) +{ + return processStarted(); +} +#endif // Q_OS_QNX + qint64 QProcessPrivate::bytesAvailableFromStdout() const { int nbytes = 0; @@ -924,6 +1009,7 @@ static int qt_timeout_value(int msecs, int elapsed) return timeout < 0 ? 0 : timeout; } +#if !defined(Q_OS_QNX) bool QProcessPrivate::waitForStarted(int msecs) { Q_Q(QProcess); @@ -951,6 +1037,7 @@ bool QProcessPrivate::waitForStarted(int msecs) #endif return startedEmitted; } +#endif // Q_OS_QNX bool QProcessPrivate::waitForReadyRead(int msecs) { @@ -972,8 +1059,10 @@ bool QProcessPrivate::waitForReadyRead(int msecs) int nfds = deathPipe[0]; FD_SET(deathPipe[0], &fdread); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -994,10 +1083,12 @@ bool QProcessPrivate::waitForReadyRead(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif bool readyReadEmitted = false; if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) { @@ -1044,8 +1135,10 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) int nfds = deathPipe[0]; FD_SET(deathPipe[0], &fdread); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -1068,10 +1161,12 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) return _q_canWrite(); @@ -1109,8 +1204,10 @@ bool QProcessPrivate::waitForFinished(int msecs) FD_ZERO(&fdread); FD_ZERO(&fdwrite); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -1134,10 +1231,12 @@ bool QProcessPrivate::waitForFinished(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) _q_canWrite(); @@ -1199,6 +1298,47 @@ void QProcessPrivate::_q_notified() { } +#if defined(Q_OS_QNX) +bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) +{ + QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory); + + // enter the working directory + char *oldWorkingDir = 0; + char buff[PATH_MAX + 1]; + if (!encodedWorkingDirectory.isEmpty()) { + oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1); + QT_CHDIR(encodedWorkingDirectory.constData()); + } + + const int fd_count = 3; + int fd_map[fd_count] = { QT_FILENO(stdin), QT_FILENO(stdout), QT_FILENO(stderr) }; + + QList<QByteArray> enc_args; + enc_args.append(QFile::encodeName(program)); + for (int i = 0; i < arguments.size(); ++i) + enc_args.append(arguments.at(i).toLocal8Bit()); + + const int argc = enc_args.size(); + QScopedArrayPointer<char*> raw_argv(new char*[argc + 1]); + for (int i = 0; i < argc; ++i) + raw_argv[i] = const_cast<char *>(enc_args.at(i).data()); + raw_argv[argc] = 0; + + char **envp = 0; // inherit environment + + pid_t childPid = doSpawn(fd_count, fd_map, raw_argv.data(), envp, true); + if (pid && childPid != -1) + *pid = childPid; + + if (oldWorkingDir) + QT_CHDIR(oldWorkingDir); + + return childPid != -1; +} + +#else + bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) { processManager()->start(); @@ -1212,7 +1352,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a int pidPipe[2]; qt_safe_pipe(pidPipe); - pid_t childPid = qt_fork(); + pid_t childPid = fork(); if (childPid == 0) { struct sigaction noaction; memset(&noaction, 0, sizeof(noaction)); @@ -1224,7 +1364,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a qt_safe_close(startedPipe[0]); qt_safe_close(pidPipe[0]); - pid_t doubleForkPid = qt_fork(); + pid_t doubleForkPid = fork(); if (doubleForkPid == 0) { qt_safe_close(pidPipe[1]); @@ -1312,6 +1452,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a qt_safe_close(pidPipe[0]); return success; } +#endif // Q_OS_QNX void QProcessPrivate::initializeProcessManager() { diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7694a0f..dd46bc5 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -98,6 +98,12 @@ # include <taskLib.h> #endif +#ifdef Q_OS_QNX +# include <sys/neutrino.h> +# include <pthread.h> +# include <sched.h> +#endif + QT_BEGIN_NAMESPACE class QMutexUnlocker @@ -353,6 +359,22 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint qt_application_thread_id = QThread::currentThreadId(); #endif +#ifdef Q_OS_QNX + // make the kernel attempt to emulate an instruction with a misaligned access + // if the attempt fails, it faults with a SIGBUS + int tv = -1; + ThreadCtl(_NTO_TCTL_ALIGN_FAULT, &tv); + + // without Round Robin drawn intensive apps will hog the cpu + // and make the system appear frozen + int sched_policy; + sched_param param; + if (pthread_getschedparam(0, &sched_policy, ¶m) == 0 && sched_policy != SCHED_RR) { + sched_policy = SCHED_RR; + pthread_setschedparam(0, sched_policy, ¶m); + } +#endif + // note: this call to QThread::currentThread() may end up setting theMainThread! if (QThread::currentThread() != theMainThread) qWarning("WARNING: QApplication was not created in the main() thread."); diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index 2882279..371974c 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -80,6 +80,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, return result; #elif defined(Q_OS_SYMBIAN) return result.left(KMaxKernelName); +#elif defined(QT_POSIX_IPC) + return QLatin1Char('/') + result; #else return QDir::tempPath() + QLatin1Char('/') + result; #endif @@ -117,6 +119,9 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash. + \o QNX: Due to possible race conditions in the POSIX IPC implementation, create() + should be called prior to any attach() calls (even across multiple threads). + \o HP-UX: Only one attach to a shared memory segment is allowed per process. This means that QSharedMemory should not be used across multiple threads in the same process in HP-UX. diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 21b8612..780e52e 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -135,6 +135,8 @@ public: const QString &prefix = QLatin1String("qipc_sharedmemory_")); #ifdef Q_OS_WIN HANDLE handle(); +#elif defined(QT_POSIX_IPC) + int handle(); #else key_t handle(); #endif @@ -166,6 +168,8 @@ private: HANDLE hand; #elif defined(Q_OS_SYMBIAN) RChunk chunk; +#elif defined(QT_POSIX_IPC) + int hand; #else key_t unix_key; #endif diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index e991ce9..a086acd 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -50,8 +50,12 @@ #ifndef QT_NO_SHAREDMEMORY #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/shm.h> +#else +#include <sys/mman.h> #include <sys/stat.h> +#endif #include <fcntl.h> #include <unistd.h> #endif // QT_NO_SHAREDMEMORY @@ -70,7 +74,11 @@ QSharedMemoryPrivate::QSharedMemoryPrivate() #ifndef QT_NO_SYSTEMSEMAPHORE systemSemaphore(QString()), lockedByMe(false), #endif +#ifndef QT_POSIX_IPC unix_key(0) +#else + hand(0) +#endif { } @@ -91,12 +99,18 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) errorString = QSharedMemory::tr("%1: doesn't exist").arg(function); error = QSharedMemory::NotFound; break; + case EAGAIN: case EMFILE: + case ENFILE: case ENOMEM: case ENOSPC: errorString = QSharedMemory::tr("%1: out of resources").arg(function); error = QSharedMemory::OutOfResources; break; + case EOVERFLOW: + errorString = QSharedMemory::tr("%1: invalid size").arg(function); + error = QSharedMemory::InvalidSize; + break; default: errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errno); error = QSharedMemory::UnknownError; @@ -112,6 +126,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) If not already made create the handle used for accessing the shared memory. */ +#ifndef QT_POSIX_IPC key_t QSharedMemoryPrivate::handle() { // already made @@ -140,6 +155,20 @@ key_t QSharedMemoryPrivate::handle() } return unix_key; } +#else +int QSharedMemoryPrivate::handle() +{ + // don't allow making handles on empty keys + QString safeKey = makePlatformSafeKey(key); + if (safeKey.isEmpty()) { + errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle")); + error = QSharedMemory::KeyError; + return 0; + } + + return 1; +} +#endif // QT_POSIX_IPC #endif // QT_NO_SHAREDMEMORY @@ -155,6 +184,7 @@ key_t QSharedMemoryPrivate::handle() */ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) { +#ifndef QT_POSIX_IPC if (QFile::exists(fileName)) return 0; @@ -168,6 +198,11 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) qt_safe_close(fd); } return 1; +#else + Q_UNUSED(fileName); + // nothing to do + return -1; +#endif } #endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE @@ -175,11 +210,17 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) void QSharedMemoryPrivate::cleanHandle() { +#ifndef QT_POSIX_IPC unix_key = 0; +#else + qt_safe_close(hand); + hand = 0; +#endif } bool QSharedMemoryPrivate::create(int size) { +#ifndef QT_POSIX_IPC // build file if needed int built = createUnixKeyFile(nativeKey); if (built == -1) { @@ -211,12 +252,46 @@ bool QSharedMemoryPrivate::create(int size) QFile::remove(nativeKey); return false; } +#else + if (!handle()) + return false; + + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + + int fd; + EINTR_LOOP(fd, shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0666)); + if (fd == -1) { + QString function = QLatin1String("QSharedMemory::create"); + switch (errno) { + case ENAMETOOLONG: + case EINVAL: + errorString = QSharedMemory::tr("%1: bad name").arg(function); + error = QSharedMemory::KeyError; + break; + default: + setErrorString(function); + } + return false; + } + + // the size may only be set once; ignore errors + int ret; + EINTR_LOOP(ret, ftruncate(fd, size)); + if (ret == -1) { + setErrorString(QLatin1String("QSharedMemory::create (ftruncate)")); + qt_safe_close(fd); + return false; + } + + qt_safe_close(fd); +#endif // QT_POSIX_IPC return true; } bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) { +#ifndef QT_POSIX_IPC // grab the shared memory segment id int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660)); if (-1 == id) { @@ -240,12 +315,55 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) setErrorString(QLatin1String("QSharedMemory::attach (shmctl)")); return false; } +#else + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + + int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR); + mode_t omode = (mode == QSharedMemory::ReadOnly ? 0444 : 0660); + + EINTR_LOOP(hand, shm_open(shmName.constData(), oflag, omode)); + if (hand == -1) { + QString function = QLatin1String("QSharedMemory::attach (shm_open)"); + switch (errno) { + case ENAMETOOLONG: + case EINVAL: + errorString = QSharedMemory::tr("%1: bad name").arg(function); + error = QSharedMemory::KeyError; + break; + default: + setErrorString(function); + } + hand = 0; + return false; + } + + // grab the size + QT_STATBUF st; + if (QT_FSTAT(hand, &st) == -1) { + setErrorString(QLatin1String("QSharedMemory::attach (fstat)")); + cleanHandle(); + return false; + } + size = st.st_size; + + // grab the memory + int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE); + memory = mmap(0, size, mprot, MAP_SHARED, hand, 0); + if (memory == MAP_FAILED || !memory) { + setErrorString(QLatin1String("QSharedMemory::attach (mmap)")); + cleanHandle(); + memory = 0; + size = 0; + return false; + } +#endif // QT_POSIX_IPC return true; } bool QSharedMemoryPrivate::detach() { +#ifndef QT_POSIX_IPC // detach from the memory segment if (-1 == shmdt(memory)) { QString function = QLatin1String("QSharedMemory::detach"); @@ -292,6 +410,31 @@ bool QSharedMemoryPrivate::detach() if (!QFile::remove(nativeKey)) return false; } +#else + // detach from the memory segment + if (munmap(memory, size) == -1) { + setErrorString(QLatin1String("QSharedMemory::detach (munmap)")); + return false; + } + memory = 0; + size = 0; + + // get the number of current attachments + int shm_nattch = 0; + QT_STATBUF st; + if (QT_FSTAT(hand, &st) == 0) { + // subtract 2 from linkcount: one for our own open and one for the dir entry + shm_nattch = st.st_nlink - 2; + } + cleanHandle(); + // if there are no attachments then unlink the shared memory + if (shm_nattch == 0) { + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + if (shm_unlink(shmName.constData()) == -1 && errno != ENOENT) + setErrorString(QLatin1String("QSharedMemory::detach (shm_unlink)")); + } +#endif // QT_POSIX_IPC + return true; } diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp index 98ee6f4..ae30348 100644 --- a/src/corelib/kernel/qsystemsemaphore.cpp +++ b/src/corelib/kernel/qsystemsemaphore.cpp @@ -151,6 +151,11 @@ QT_BEGIN_NAMESPACE creates a new semaphore for that key and sets its resource count to \a initialValue. + In QNX, if the \a mode is \l {QSystemSemaphore::} {Create} and the + system already has a semaphore identified by \a key, that semaphore + will be deleted and the new one will be created for that key with + a resource count set to \a initialValue. + In Windows and in Symbian, \a mode is ignored, and the system always tries to create a semaphore for the specified \a key. If the system does not already have a semaphore identified as \a key, it creates the @@ -234,7 +239,7 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m return; d->error = NoError; d->errorString = QString(); -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) && !defined(QT_POSIX_IPC) // optimization to not destroy/create the file & semaphore if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) { d->initialValue = initialValue; diff --git a/src/corelib/kernel/qsystemsemaphore_p.h b/src/corelib/kernel/qsystemsemaphore_p.h index 3e5f737..d84d416 100644 --- a/src/corelib/kernel/qsystemsemaphore_p.h +++ b/src/corelib/kernel/qsystemsemaphore_p.h @@ -61,6 +61,9 @@ #ifndef Q_OS_WINCE # include <sys/types.h> #endif +#ifdef QT_POSIX_IPC +# include <semaphore.h> +#endif #ifdef Q_OS_SYMBIAN class RSemaphore; @@ -84,6 +87,9 @@ public: #elif defined(Q_OS_SYMBIAN) int handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); void setErrorString(const QString &function,int err = 0); +#elif defined(QT_POSIX_IPC) + bool handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); + void setErrorString(const QString &function); #else key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); void setErrorString(const QString &function); @@ -99,6 +105,9 @@ public: HANDLE semaphoreLock; #elif defined(Q_OS_SYMBIAN) RSemaphore semaphore; +#elif defined(QT_POSIX_IPC) + sem_t *semaphore; + bool createdSemaphore; #else key_t unix_key; int semaphore; diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp index 704afaf..e060eb2 100644 --- a/src/corelib/kernel/qsystemsemaphore_unix.cpp +++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp @@ -50,7 +50,9 @@ #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/sem.h> +#endif #include <fcntl.h> #include <errno.h> @@ -67,7 +69,11 @@ QT_BEGIN_NAMESPACE QSystemSemaphorePrivate::QSystemSemaphorePrivate() : +#ifndef QT_POSIX_IPC unix_key(-1), semaphore(-1), createdFile(false), +#else + semaphore(SEM_FAILED), +#endif createdSemaphore(false), error(QSystemSemaphore::NoError) { } @@ -90,10 +96,18 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function) error = QSystemSemaphore::NotFound; break; case ERANGE: + case ENOMEM: case ENOSPC: + case EMFILE: + case ENFILE: + case EOVERFLOW: errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function); error = QSystemSemaphore::OutOfResources; break; + case ENAMETOOLONG: + errorString = QCoreApplication::translate("QSystemSemaphore", "%1: name error").arg(function); + error = QSystemSemaphore::KeyError; + break; default: errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(errno); error = QSystemSemaphore::UnknownError; @@ -109,6 +123,7 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function) Initialise the semaphore */ +#ifndef QT_POSIX_IPC key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) { if (-1 != unix_key) @@ -170,6 +185,54 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) return unix_key; } +#else +bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) +{ + if (semaphore != SEM_FAILED) + return true; // we already have a semaphore + + if (fileName.isEmpty()) { + errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle")); + error = QSystemSemaphore::KeyError; + return false; + } + + QByteArray semName = QFile::encodeName(fileName); + + // Always try with O_EXCL so we know whether we created the semaphore. + int oflag = O_CREAT | O_EXCL; + for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) { + do { + semaphore = sem_open(semName.constData(), oflag, 0666, initialValue); + } while (semaphore == SEM_FAILED && errno == EINTR); + if (semaphore == SEM_FAILED && errno == EEXIST) { + if (mode == QSystemSemaphore::Create) { + if (sem_unlink(semName.constData()) == -1 && errno != ENOENT) { + setErrorString(QLatin1String("QSystemSemaphore::handle (sem_unlink)")); + return false; + } + // Race condition: the semaphore might be recreated before + // we call sem_open again, so we'll retry several times. + maxTries = 3; + } else { + // Race condition: if it no longer exists at the next sem_open + // call, we won't realize we created it, so we'll leak it later. + oflag &= ~O_EXCL; + maxTries = 2; + } + } else { + break; + } + } + if (semaphore == SEM_FAILED) { + setErrorString(QLatin1String("QSystemSemaphore::handle")); + return false; + } + + createdSemaphore = (oflag & O_EXCL) != 0; + return true; +} +#endif // QT_POSIX_IPC /*! \internal @@ -178,6 +241,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) */ void QSystemSemaphorePrivate::cleanHandle() { +#ifndef QT_POSIX_IPC unix_key = -1; // remove the file if we made it @@ -198,6 +262,27 @@ void QSystemSemaphorePrivate::cleanHandle() } createdSemaphore = false; } +#else + if (semaphore != SEM_FAILED) { + if (sem_close(semaphore) == -1) { + setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_close)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_close failed."); +#endif + } + semaphore = SEM_FAILED; + } + + if (createdSemaphore) { + if (sem_unlink(QFile::encodeName(fileName).constData()) == -1 && errno != ENOENT) { + setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_unlink)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_unlink failed."); +#endif + } + createdSemaphore = false; + } +#endif // QT_POSIX_IPC } /*! @@ -205,6 +290,7 @@ void QSystemSemaphorePrivate::cleanHandle() */ bool QSystemSemaphorePrivate::modifySemaphore(int count) { +#ifndef QT_POSIX_IPC if (-1 == handle()) return false; @@ -229,6 +315,44 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count) #endif return false; } +#else + if (!handle()) + return false; + + if (count > 0) { + int cnt = count; + do { + if (sem_post(semaphore) == -1) { + setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_post)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::modify sem_post failed") << count << errno; +#endif + // rollback changes to preserve the SysV semaphore behavior + for ( ; cnt < count; ++cnt) { + register int res; + EINTR_LOOP(res, sem_wait(semaphore)); + } + return false; + } + --cnt; + } while (cnt > 0); + } else { + register int res; + EINTR_LOOP(res, sem_wait(semaphore)); + if (res == -1) { + // If the semaphore was removed be nice and create it and then modifySemaphore again + if (errno == EINVAL || errno == EIDRM) { + semaphore = SEM_FAILED; + return modifySemaphore(count); + } + setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_wait)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::modify sem_wait failed") << count << errno; +#endif + return false; + } + } +#endif // QT_POSIX_IPC return true; } diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 839a396..765969e 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -479,6 +479,11 @@ void QThread::usleep(unsigned long usecs) // sched_priority is OUT only static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority) { +#ifdef Q_OS_QNX + // without Round Robin drawn intensive apps will hog the cpu + // and make the system appear frozen + *sched_policy = SCHED_RR; +#endif #ifdef SCHED_IDLE if (priority == QThread::IdlePriority) { *sched_policy = SCHED_IDLE; diff --git a/src/declarative/debugger/qdeclarativeinspectorservice.cpp b/src/declarative/debugger/qdeclarativeinspectorservice.cpp index 9fec006..15dbf58 100644 --- a/src/declarative/debugger/qdeclarativeinspectorservice.cpp +++ b/src/declarative/debugger/qdeclarativeinspectorservice.cpp @@ -67,11 +67,13 @@ QDeclarativeInspectorService *QDeclarativeInspectorService::instance() void QDeclarativeInspectorService::addView(QDeclarativeView *view) { m_views.append(view); + updateStatus(); } void QDeclarativeInspectorService::removeView(QDeclarativeView *view) { m_views.removeAll(view); + updateStatus(); } void QDeclarativeInspectorService::sendMessage(const QByteArray &message) @@ -84,10 +86,18 @@ void QDeclarativeInspectorService::sendMessage(const QByteArray &message) void QDeclarativeInspectorService::statusChanged(Status status) { - if (m_views.isEmpty()) + updateStatus(); +} + +void QDeclarativeInspectorService::updateStatus() +{ + if (m_views.isEmpty()) { + if (m_inspectorPlugin) + m_inspectorPlugin->deactivate(); return; + } - if (status == Enabled) { + if (status() == Enabled) { if (!m_inspectorPlugin) m_inspectorPlugin = loadInspectorPlugin(); diff --git a/src/declarative/debugger/qdeclarativeinspectorservice_p.h b/src/declarative/debugger/qdeclarativeinspectorservice_p.h index 9fe0d601f..9a14155 100644 --- a/src/declarative/debugger/qdeclarativeinspectorservice_p.h +++ b/src/declarative/debugger/qdeclarativeinspectorservice_p.h @@ -78,6 +78,8 @@ protected: virtual void messageReceived(const QByteArray &); private: + void updateStatus(); + static QDeclarativeInspectorInterface *loadInspectorPlugin(); QList<QDeclarativeView*> m_views; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index bc9b6fd..d2897eb 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1941,12 +1941,12 @@ void QDeclarativeTextInput::selectionChanged() void QDeclarativeTextInput::q_textChanged() { Q_D(QDeclarativeTextInput); + emit textChanged(); + emit displayTextChanged(); updateSize(); d->determineHorizontalAlignment(); d->updateHorizontalScroll(); updateMicroFocus(); - emit textChanged(); - emit displayTextChanged(); if(hasAcceptableInput() != d->oldValidity){ d->oldValidity = hasAcceptableInput(); emit acceptableInputChanged(); diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index ca3bc37..689cd00 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -243,12 +243,13 @@ QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeCont if (id < 0) return 0; + Q_ASSERT(ctxt); QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(ctxt); - QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(obj)); + QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(ctxtdata->engine); QDeclarativeCompiledData *cdata = 0; QDeclarativeTypeData *typeData = 0; - if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { + if (!ctxtdata->url.isEmpty()) { typeData = engine->typeLoader.get(ctxtdata->url); cdata = typeData->compiledData(); } diff --git a/src/gui/embedded/embedded.pri b/src/gui/embedded/embedded.pri index 31f0bc6..836c116 100644 --- a/src/gui/embedded/embedded.pri +++ b/src/gui/embedded/embedded.pri @@ -117,7 +117,7 @@ embedded { contains( gfx-drivers, qnx ) { HEADERS += embedded/qscreenqnx_qws.h SOURCES += embedded/qscreenqnx_qws.cpp - LIBS += -lgf + LIBS_PRIVATE += -lgf } contains( gfx-drivers, integrityfb ) { diff --git a/src/gui/embedded/qkbdqnx_qws.cpp b/src/gui/embedded/qkbdqnx_qws.cpp index 5a8118d..ad76446 100644 --- a/src/gui/embedded/qkbdqnx_qws.cpp +++ b/src/gui/embedded/qkbdqnx_qws.cpp @@ -40,16 +40,16 @@ ****************************************************************************/ #include "qkbdqnx_qws.h" -#include "QtCore/qsocketnotifier.h" + +#include "qplatformdefs.h" +#include "qsocketnotifier.h" +#include "private/qcore_unix_p.h" #include "QtCore/qdebug.h" #include <sys/dcmd_input.h> -#include <photon/keycodes.h> - -#include "qplatformdefs.h" +#include <sys/keycodes.h> #include <errno.h> - QT_BEGIN_NAMESPACE /*! @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse} Note that after running \c{devi-hid}, you will not be able to use the local - shell anymore. It is suggested to run the command in a shell scrip, that launches + shell anymore. It is suggested to run the command in a shell script, that launches a Qt application after invocation of \c{devi-hid}. To make \l{Qt for Embedded Linux} explicitly choose the qnx keyboard @@ -100,15 +100,13 @@ QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device) QT_OPEN_RDONLY); if (keyboardFD == -1) { qErrnoWarning(errno, "QWSQnxKeyboardHandler: Unable to open device"); - return; - } - - // create a socket notifier so we'll wake up whenever keyboard input is detected. - QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this); - connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated())); - - qDebug() << "QWSQnxKeyboardHandler: connected."; + } else { + // create a socket notifier so we'll wake up whenever keyboard input is detected. + QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated())); + qDebug("QWSQnxKeyboardHandler: connected."); + } } /*! @@ -116,7 +114,16 @@ QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device) */ QWSQnxKeyboardHandler::~QWSQnxKeyboardHandler() { - QT_CLOSE(keyboardFD); + if (keyboardFD != -1) + QT_CLOSE(keyboardFD); +} + +// similar to PhKeyToMb +static inline bool key_sym_displayable(unsigned long sym) +{ + if (sym >= 0xF000) + return sym >= 0xF100 && (sizeof(wchar_t) > 2 || sym < 0x10000); + return (sym & ~0x9F) != 0; // exclude 0...0x1F and 0x80...0x9F } /*! \internal @@ -136,6 +143,11 @@ void QWSQnxKeyboardHandler::socketActivated() // the bytes read must be the size of a keyboard packet Q_ASSERT(bytesRead == sizeof(_keyboard_packet)); + if (packet.data.flags & KEY_SYM_VALID_EX) + packet.data.flags |= KEY_SYM_VALID; + else if (!(packet.data.flags & (KEY_SYM_VALID | KEY_CAP_VALID))) + return; + #if 0 qDebug() << "keyboard got scancode" << hex << packet.data.modifiers @@ -145,86 +157,157 @@ void QWSQnxKeyboardHandler::socketActivated() << packet.data.key_scan; #endif - // QNX is nice enough to translate the raw keyboard data into a QNX data structure + // QNX is nice enough to translate the raw keyboard data into generic format for us. // Now we just have to translate it into a format Qt understands. - // figure out whether it's a press - bool isPress = packet.data.key_cap & KEY_DOWN; - // figure out whether the key is still pressed and the key event is repeated - bool isRepeat = packet.data.key_cap & KEY_REPEAT; - - Qt::Key key = Qt::Key_unknown; - int unicode = 0xffff; - - // TODO - this switch is not complete! - switch (packet.data.key_scan) { - case KEYCODE_SPACE: key = Qt::Key_Space; unicode = 0x20; break; - case KEYCODE_F1: key = Qt::Key_F1; break; - case KEYCODE_F2: key = Qt::Key_F2; break; - case KEYCODE_F3: key = Qt::Key_F3; break; - case KEYCODE_F4: key = Qt::Key_F4; break; - case KEYCODE_F5: key = Qt::Key_F5; break; - case KEYCODE_F6: key = Qt::Key_F6; break; - case KEYCODE_F7: key = Qt::Key_F7; break; - case KEYCODE_F8: key = Qt::Key_F8; break; - case KEYCODE_F9: key = Qt::Key_F9; break; - case KEYCODE_F10: key = Qt::Key_F10; break; - case KEYCODE_F11: key = Qt::Key_F11; break; - case KEYCODE_F12: key = Qt::Key_F12; break; - case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; break; - case KEYCODE_TAB: key = Qt::Key_Tab; break; - case KEYCODE_RETURN: key = Qt::Key_Return; break; - case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break; - case KEYCODE_UP: - case KEYCODE_KP_UP: - key = Qt::Key_Up; break; - case KEYCODE_DOWN: - case KEYCODE_KP_DOWN: - key = Qt::Key_Down; break; - case KEYCODE_LEFT: - case KEYCODE_KP_LEFT: - key = Qt::Key_Left; break; - case KEYCODE_RIGHT: - case KEYCODE_KP_RIGHT: - key = Qt::Key_Right; break; - case KEYCODE_HOME: - case KEYCODE_KP_HOME: - key = Qt::Key_Home; break; - case KEYCODE_END: - case KEYCODE_KP_END: - key = Qt::Key_End; break; - case KEYCODE_PG_UP: - case KEYCODE_KP_PG_UP: - key = Qt::Key_PageUp; break; - case KEYCODE_PG_DOWN: - case KEYCODE_KP_PG_DOWN: - key = Qt::Key_PageDown; break; - case KEYCODE_INSERT: - case KEYCODE_KP_INSERT: - key = Qt::Key_Insert; break; - case KEYCODE_DELETE: - case KEYCODE_KP_DELETE: - key = Qt::Key_Delete; break; - case KEYCODE_ESCAPE: - key = Qt::Key_Escape; break; - default: // none of the above, try the key_scan directly - unicode = packet.data.key_scan; - break; - } - // figure out the modifiers that are currently pressed Qt::KeyboardModifiers modifiers = Qt::NoModifier; - if (packet.data.flags & KEYMOD_SHIFT) + if (packet.data.modifiers & KEYMOD_SHIFT) modifiers |= Qt::ShiftModifier; - if (packet.data.flags & KEYMOD_CTRL) + if (packet.data.modifiers & KEYMOD_CTRL) modifiers |= Qt::ControlModifier; - if (packet.data.flags & KEYMOD_ALT) + if (packet.data.modifiers & KEYMOD_ALT) modifiers |= Qt::AltModifier; + if (packet.data.modifiers & KEYMOD_NUM_LOCK) + modifiers |= Qt::KeypadModifier; +#if 0 + // special case for AltGr + if (packet.data.modifiers & KEYMOD_ALTGR) + key = Qt::Key_AltGr; +#endif + + // figure out whether it's a press + bool isPress = packet.data.flags & KEY_DOWN; + // figure out whether the key is still pressed and the key event is repeated + bool isRepeat = packet.data.flags & KEY_REPEAT; + + int key = Qt::Key_unknown; + int unicode = 0; + + if (((packet.data.flags & KEY_SYM_VALID) && key_sym_displayable(unicode = packet.data.key_sym)) + || ((packet.data.flags & KEY_CAP_VALID) && key_sym_displayable(unicode = packet.data.key_cap))) { + if (unicode <= 0x0ff) { + if (unicode >= 'a' && unicode <= 'z') + key = Qt::Key_A + unicode - 'a'; + else + key = unicode; + } + // Ctrl<something> or Alt<something> is not a displayable character + if (modifiers & (Qt::ControlModifier | Qt::AltModifier)) + unicode = 0; + } else { + unicode = 0; + + unsigned long sym = 0; + if (packet.data.flags & KEY_SYM_VALID) + sym = packet.data.key_sym; + else if (packet.data.flags & KEY_CAP_VALID) + sym = packet.data.key_cap; - // if the unicode value is not ascii, we ignore it. - // TODO - do a complete mapping between all QNX scan codes and Qt codes - if (unicode != 0xffff && !isascii(unicode)) - return; // unprintable character + switch (sym) { + case KEYCODE_ESCAPE: key = Qt::Key_Escape; unicode = 27; break; + case KEYCODE_TAB: key = Qt::Key_Tab; unicode = 9; break; + case KEYCODE_BACK_TAB: key = Qt::Key_Backtab; break; + case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; unicode = 127; break; + case KEYCODE_RETURN: key = Qt::Key_Return; break; + case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break; + case KEYCODE_INSERT: + case KEYCODE_KP_INSERT: + key = Qt::Key_Insert; break; + case KEYCODE_KP_DELETE: + if (modifiers & Qt::KeypadModifier) { + key = Qt::Key_Comma; + break; + } + // fall through + case KEYCODE_DELETE: + key = Qt::Key_Delete; break; + case KEYCODE_PAUSE: + case KEYCODE_BREAK: + if (modifiers & (Qt::ControlModifier | Qt::AltModifier)) + return; // sometimes occurs at the middle of a key sequence + key = Qt::Key_Pause; break; + case KEYCODE_PRINT: + if (modifiers & (Qt::ControlModifier | Qt::AltModifier)) + return; // sometimes occurs at the middle of a key sequence + key = Qt::Key_Print; break; + case KEYCODE_SYSREQ: + key = Qt::Key_SysReq; break; + case KEYCODE_HOME: + case KEYCODE_KP_HOME: + key = Qt::Key_Home; break; + case KEYCODE_END: + case KEYCODE_KP_END: + key = Qt::Key_End; break; + case KEYCODE_LEFT: + case KEYCODE_KP_LEFT: + key = Qt::Key_Left; break; + case KEYCODE_UP: + case KEYCODE_KP_UP: + key = Qt::Key_Up; break; + case KEYCODE_RIGHT: + case KEYCODE_KP_RIGHT: + key = Qt::Key_Right; break; + case KEYCODE_DOWN: + case KEYCODE_KP_DOWN: + key = Qt::Key_Down; break; + case KEYCODE_PG_UP: + case KEYCODE_KP_PG_UP: + key = Qt::Key_PageUp; break; + case KEYCODE_PG_DOWN: + case KEYCODE_KP_PG_DOWN: + key = Qt::Key_PageDown; break; + + case KEYCODE_LEFT_SHIFT: + case KEYCODE_RIGHT_SHIFT: + key = Qt::Key_Shift; break; + case KEYCODE_LEFT_CTRL: + case KEYCODE_RIGHT_CTRL: + key = Qt::Key_Control; break; + case KEYCODE_LEFT_ALT: + case KEYCODE_RIGHT_ALT: + key = Qt::Key_Alt; break; + case KEYCODE_CAPS_LOCK: + key = Qt::Key_CapsLock; break; + case KEYCODE_NUM_LOCK: + key = Qt::Key_NumLock; break; + case KEYCODE_SCROLL_LOCK: + key = Qt::Key_ScrollLock; break; + + case KEYCODE_F1: + case KEYCODE_F2: + case KEYCODE_F3: + case KEYCODE_F4: + case KEYCODE_F5: + case KEYCODE_F6: + case KEYCODE_F7: + case KEYCODE_F8: + case KEYCODE_F9: + case KEYCODE_F10: + case KEYCODE_F11: + case KEYCODE_F12: + key = Qt::Key_F1 + sym - KEYCODE_F1; break; + + case KEYCODE_MENU: key = Qt::Key_Menu; break; + case KEYCODE_LEFT_HYPER: key = Qt::Key_Hyper_L; break; + case KEYCODE_RIGHT_HYPER: key = Qt::Key_Hyper_R; break; + + case KEYCODE_KP_PLUS: key = Qt::Key_Plus; break; + case KEYCODE_KP_MINUS: key = Qt::Key_Minus; break; + case KEYCODE_KP_MULTIPLY: key = Qt::Key_multiply; break; + case KEYCODE_KP_DIVIDE: key = Qt::Key_Slash; break; + case KEYCODE_KP_FIVE: + if (!(modifiers & Qt::KeypadModifier)) + key = Qt::Key_5; + break; + + default: // none of the above + break; + } + } + + if (key == Qt::Key_unknown && unicode == 0) + return; // call processKeyEvent. This is where all the magic happens to insert a // key event into Qt's event loop. diff --git a/src/gui/embedded/qlock.cpp b/src/gui/embedded/qlock.cpp index ac15431..eaad15c 100644 --- a/src/gui/embedded/qlock.cpp +++ b/src/gui/embedded/qlock.cpp @@ -41,7 +41,6 @@ #include "qlock_p.h" - #ifdef QT_NO_QWS_MULTIPROCESS QT_BEGIN_NAMESPACE @@ -83,7 +82,7 @@ QT_END_NAMESPACE #else // QT_NO_QWS_MULTIPROCESS #if defined(Q_OS_DARWIN) -# define Q_NO_SEMAPHORE +# define QT_NO_SEMAPHORE #endif #include "qwssignalhandler_p.h" @@ -91,11 +90,13 @@ QT_END_NAMESPACE #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> -#if defined(Q_NO_SEMAPHORE) +#if defined(QT_NO_SEMAPHORE) # include <sys/stat.h> # include <sys/file.h> -#else +#elif !defined(QT_POSIX_IPC) # include <sys/sem.h> +#else +# include <semaphore.h> #endif #include <string.h> #include <errno.h> @@ -109,17 +110,24 @@ QT_BEGIN_NAMESPACE class QLockData { public: -#ifdef Q_NO_SEMAPHORE +#if defined(QT_NO_SEMAPHORE) || defined(QT_POSIX_IPC) QByteArray file; -#endif // Q_NO_SEMAPHORE +#endif +#if !defined(QT_POSIX_IPC) int id; +#else + sem_t *id; // Read mode resource counter + sem_t *rsem; // Read mode lock + sem_t *wsem; // Write mode lock +#endif int count; bool owned; }; + /*! \class QLock - \brief The QLock class is a wrapper for a System V shared semaphore. + \brief The QLock class is a wrapper for a system shared semaphore. \ingroup qws @@ -148,7 +156,7 @@ QLock::QLock(const QString &filename, char id, bool create) { data = new QLockData; data->count = 0; -#ifdef Q_NO_SEMAPHORE +#if defined(QT_NO_SEMAPHORE) data->file = filename.toLocal8Bit() + id; for (int x = 0; x < 2; ++x) { data->id = QT_OPEN(data->file.constData(), O_RDWR | (x ? O_CREAT : 0), S_IRWXU); @@ -157,7 +165,7 @@ QLock::QLock(const QString &filename, char id, bool create) break; } } -#else +#elif !defined(QT_POSIX_IPC) key_t semkey = ftok(filename.toLocal8Bit().constData(), id); data->id = semget(semkey, 0, 0); data->owned = create; @@ -170,6 +178,28 @@ QLock::QLock(const QString &filename, char id, bool create) arg.val = MAX_LOCKS; semctl(data->id, 0, SETVAL, arg); } +#else + data->file = filename.toLocal8Bit() + id; + data->owned = create; + + char ids[3] = { 'c', 'r', 'w' }; + sem_t **sems[3] = { &data->id, &data->rsem, &data->wsem }; + unsigned short initialValues[3] = { MAX_LOCKS, 1, 1 }; + for (int i = 0; i < 3; ++i) { + QByteArray file = data->file + ids[i]; + do { + *sems[i] = sem_open(file.constData(), 0, 0666, 0); + } while (*sems[i] == SEM_FAILED && errno == EINTR); + if (create) { + if (*sems[i] != SEM_FAILED) { + sem_close(*sems[i]); + sem_unlink(file.constData()); + } + do { + *sems[i] = sem_open(file.constData(), O_CREAT, 0666, initialValues[i]); + } while (*sems[i] == SEM_FAILED && errno == EINTR); + } + } #endif if (!isValid()) { qWarning("QLock::QLock: Cannot %s semaphore %s '%c' (%d, %s)", @@ -193,17 +223,32 @@ QLock::~QLock() while (locked()) unlock(); -#ifdef Q_NO_SEMAPHORE + +#if defined(QT_NO_SEMAPHORE) if (isValid()) QT_CLOSE(data->id); +#elif defined(QT_POSIX_IPC) + if (data->id != SEM_FAILED) + sem_close(data->id); + if (data->rsem != SEM_FAILED) + sem_close(data->rsem); + if (data->wsem != SEM_FAILED) + sem_close(data->wsem); #endif + if (data->owned) { -#ifdef Q_NO_SEMAPHORE +#if defined(QT_NO_SEMAPHORE) unlink(data->file.constData()); -#else +#elif !defined(QT_POSIX_IPC) qt_semun semval; semval.val = 0; semctl(data->id, 0, IPC_RMID, semval); +#else + char ids[3] = { 'c', 'r', 'w' }; + for (int i = 0; i < 3; ++i) { + QByteArray file = data->file + ids[i]; + sem_unlink(file.constData()); + } #endif } delete data; @@ -216,7 +261,11 @@ QLock::~QLock() */ bool QLock::isValid() const { +#if !defined(QT_POSIX_IPC) return data && data->id != -1; +#else + return data && data->id != SEM_FAILED && data->rsem != SEM_FAILED && data->wsem != SEM_FAILED; +#endif } /*! @@ -232,21 +281,48 @@ bool QLock::isValid() const */ void QLock::lock(Type t) { + if (!isValid()) + return; + if (!data->count) { type = t; int rv; -#ifdef Q_NO_SEMAPHORE +#if defined(QT_NO_SEMAPHORE) int op = type == Write ? LOCK_EX : LOCK_SH; EINTR_LOOP(rv, flock(data->id, op)); -#else +#elif !defined(QT_POSIX_IPC) sembuf sops; sops.sem_num = 0; sops.sem_op = type == Write ? -MAX_LOCKS : -1; sops.sem_flg = SEM_UNDO; EINTR_LOOP(rv, semop(data->id, &sops, 1)); +#else + if (type == Write) { + EINTR_LOOP(rv, sem_wait(data->rsem)); + if (rv != -1) { + EINTR_LOOP(rv, sem_wait(data->wsem)); + if (rv == -1) + sem_post(data->rsem); + } + } else { + EINTR_LOOP(rv, sem_wait(data->wsem)); + if (rv != -1) { + EINTR_LOOP(rv, sem_trywait(data->rsem)); + if (rv != -1 || errno == EAGAIN) { + EINTR_LOOP(rv, sem_wait(data->id)); + if (rv == -1) { + int semval; + sem_getvalue(data->id, &semval); + if (semval == MAX_LOCKS) + sem_post(data->rsem); + } + } + rv = sem_post(data->wsem); + } + } #endif if (rv == -1) { qDebug("QLock::lock(): %s", strerror(errno)); @@ -265,19 +341,37 @@ void QLock::lock(Type t) */ void QLock::unlock() { - if (data->count) { + if (!isValid()) + return; + + if (data->count > 0) { data->count--; if (!data->count) { int rv; -#ifdef Q_NO_SEMAPHORE +#if defined(QT_NO_SEMAPHORE) EINTR_LOOP(rv, flock(data->id, LOCK_UN)); -#else +#elif !defined(QT_POSIX_IPC) sembuf sops; sops.sem_num = 0; sops.sem_op = type == Write ? MAX_LOCKS : 1; sops.sem_flg = SEM_UNDO; EINTR_LOOP(rv, semop(data->id, &sops, 1)); +#else + if (type == Write) { + sem_post(data->wsem); + rv = sem_post(data->rsem); + } else { + EINTR_LOOP(rv, sem_wait(data->wsem)); + if (rv != -1) { + sem_post(data->id); + int semval; + sem_getvalue(data->id, &semval); + if (semval == MAX_LOCKS) + sem_post(data->rsem); + rv = sem_post(data->wsem); + } + } #endif if (rv == -1) qDebug("QLock::unlock(): %s", strerror(errno)); diff --git a/src/gui/embedded/qmouselinuxinput_qws.cpp b/src/gui/embedded/qmouselinuxinput_qws.cpp index efcf6d4..19a9a99 100644 --- a/src/gui/embedded/qmouselinuxinput_qws.cpp +++ b/src/gui/embedded/qmouselinuxinput_qws.cpp @@ -135,19 +135,21 @@ void QWSLinuxInputMousePrivate::readMouseData() int n = 0; forever { - n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); - - if (n == 0) { + int bytesRead = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); + if (bytesRead == 0) { qWarning("Got EOF from the input device."); return; - } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) { - qWarning("Could not read from input device: %s", strerror(errno)); - return; - } else if (n % sizeof(buffer[0]) == 0) { + } + if (bytesRead == -1) { + if (errno != EAGAIN) + qWarning("Could not read from input device: %s", strerror(errno)); break; } - } + n += bytesRead; + if (n % sizeof(buffer[0]) == 0) + break; + } n /= sizeof(buffer[0]); for (int i = 0; i < n; ++i) { diff --git a/src/gui/embedded/qmouseqnx_qws.cpp b/src/gui/embedded/qmouseqnx_qws.cpp index a9647c0..d0b892e 100644 --- a/src/gui/embedded/qmouseqnx_qws.cpp +++ b/src/gui/embedded/qmouseqnx_qws.cpp @@ -39,14 +39,13 @@ ** ****************************************************************************/ -#include "qplatformdefs.h" #include "qmouseqnx_qws.h" +#include "qplatformdefs.h" #include "qsocketnotifier.h" -#include "qdebug.h" +#include "private/qcore_unix_p.h" #include <sys/dcmd_input.h> - #include <errno.h> QT_BEGIN_NAMESPACE @@ -92,22 +91,28 @@ QT_BEGIN_NAMESPACE \sa QMouseDriverFactory */ -QQnxMouseHandler::QQnxMouseHandler(const QString & /*driver*/, const QString &device) +QQnxMouseHandler::QQnxMouseHandler(const QString & driver, const QString &device) + : QObject(), QWSMouseHandler(driver, device), mouseButtons(Qt::NoButton) { // open the mouse device with O_NONBLOCK so reading won't block when there's no data mouseFD = QT_OPEN(device.isEmpty() ? "/dev/devi/mouse0" : device.toLatin1().constData(), - QT_OPEN_RDONLY | O_NONBLOCK); + QT_OPEN_RDONLY | O_NONBLOCK); if (mouseFD == -1) { qErrnoWarning(errno, "QQnxMouseHandler: Unable to open mouse device"); - return; + } else { + struct _pointer_info data; + if (devctl(mouseFD, _POINTERGETINFO, &data, sizeof(data), NULL) == EOK) + absolutePositioning = (data.flags & _POINTER_FLAG_ABSOLUTE); + else + absolutePositioning = !device.isEmpty() && device.contains(QLatin1String("touch")); + + // register a socket notifier on the file descriptor so we'll wake up whenever + // there's a mouse move waiting for us. + mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this); + connect(mouseNotifier, SIGNAL(activated(int)), SLOT(socketActivated())); + + qDebug("QQnxMouseHandler: connected."); } - - // register a socket notifier on the file descriptor so we'll wake up whenever - // there's a mouse move waiting for us. - mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this); - connect(mouseNotifier, SIGNAL(activated(int)), SLOT(socketActivated())); - - qDebug() << "QQnxMouseHandler: connected."; } /*! @@ -115,7 +120,8 @@ QQnxMouseHandler::QQnxMouseHandler(const QString & /*driver*/, const QString &de */ QQnxMouseHandler::~QQnxMouseHandler() { - QT_CLOSE(mouseFD); + if (mouseFD != -1) + QT_CLOSE(mouseFD); } /*! \reimp */ @@ -140,39 +146,45 @@ void QQnxMouseHandler::suspend() */ void QQnxMouseHandler::socketActivated() { + QPoint queuedPos = mousePos; + // _mouse_packet is a QNX structure. devi-hid is nice enough to translate // the raw byte data from mouse devices into generic format for us. - _mouse_packet packet; + struct _mouse_packet buffer[32]; + int n = 0; - int iteration = 0; - - // read mouse events in batches of 10. Since we're getting quite a lot - // of mouse events, it's better to do them in batches than to return to the - // event loop every time. - do { - int bytesRead = QT_READ(mouseFD, &packet, sizeof(packet)); + forever { + int bytesRead = QT_READ(mouseFD, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); if (bytesRead == -1) { // EAGAIN means that there are no more mouse events to read if (errno != EAGAIN) - qErrnoWarning(errno, "QQnxMouseHandler: Unable to read from socket"); - return; + qErrnoWarning(errno, "QQnxMouseHandler: Could not read from input device"); + break; } - // bytes read should always be equal to the size of a packet. - Q_ASSERT(bytesRead == sizeof(packet)); + n += bytesRead; + if (n % sizeof(buffer[0]) == 0) + break; + } + n /= sizeof(buffer[0]); - // translate the coordinates from the QNX data structure to Qt coordinates - // note the swapped y axis - QPoint pos = mousePos; - pos += QPoint(packet.dx, -packet.dy); + for (int i = 0; i < n; ++i) { + const struct _mouse_packet &packet = buffer[i]; - // QNX only tells us relative mouse movements, not absolute ones, so limit the - // cursor position manually to the screen - limitToScreen(pos); + // translate the coordinates from the QNX data structure to the Qt coordinates + if (absolutePositioning) { + queuedPos = QPoint(packet.dx, packet.dy); + } else { + // note the swapped y axis + queuedPos += QPoint(packet.dx, -packet.dy); + + // QNX only tells us relative mouse movements, not absolute ones, so + // limit the cursor position manually to the screen + limitToScreen(queuedPos); + } // translate the QNX mouse button bitmask to Qt buttons int buttons = Qt::NoButton; - if (packet.hdr.buttons & _POINTER_BUTTON_LEFT) buttons |= Qt::LeftButton; if (packet.hdr.buttons & _POINTER_BUTTON_MIDDLE) @@ -180,11 +192,17 @@ void QQnxMouseHandler::socketActivated() if (packet.hdr.buttons & _POINTER_BUTTON_RIGHT) buttons |= Qt::RightButton; - // call mouseChanged() - this does all the magic to actually move the on-screen - // mouse cursor. - mouseChanged(pos, buttons, 0); - } while (++iteration < 11); + if (buttons != mouseButtons) { + // send the MouseEvent to avoid missing any clicks + mouseChanged(queuedPos, buttons, 0); + // mousePos updated by the mouseChanged() + queuedPos = mousePos; + mouseButtons = buttons; + } + } + + if (queuedPos != mousePos) + mouseChanged(queuedPos, mouseButtons, 0); } QT_END_NAMESPACE - diff --git a/src/gui/embedded/qmouseqnx_qws.h b/src/gui/embedded/qmouseqnx_qws.h index 2a5eef2..54deaf3 100644 --- a/src/gui/embedded/qmouseqnx_qws.h +++ b/src/gui/embedded/qmouseqnx_qws.h @@ -70,6 +70,8 @@ private Q_SLOTS: private: QSocketNotifier *mouseNotifier; int mouseFD; + int mouseButtons; + bool absolutePositioning; }; QT_END_NAMESPACE diff --git a/src/gui/embedded/qscreen_qws.h b/src/gui/embedded/qscreen_qws.h index 2ecc6e7..5ff90f9 100644 --- a/src/gui/embedded/qscreen_qws.h +++ b/src/gui/embedded/qscreen_qws.h @@ -44,7 +44,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qpoint.h> -#include <QtCore/qlist.h> +#include <QtCore/qstringlist.h> #include <QtGui/qrgb.h> #include <QtCore/qrect.h> #include <QtGui/qimage.h> @@ -357,6 +357,7 @@ private: friend class QVNCScreen; friend class QLinuxFbScreen; friend class QVFbScreen; + friend class QQnxScreen; friend class QProxyScreen; friend class QIntfbScreen; #endif diff --git a/src/gui/embedded/qscreenqnx_qws.cpp b/src/gui/embedded/qscreenqnx_qws.cpp index 4afe087..d34e732 100644 --- a/src/gui/embedded/qscreenqnx_qws.cpp +++ b/src/gui/embedded/qscreenqnx_qws.cpp @@ -40,7 +40,9 @@ ****************************************************************************/ #include "qscreenqnx_qws.h" -#include "qdebug.h" + +#include <qapplication.h> +#include <qregexp.h> #include <gf/gf.h> @@ -52,6 +54,10 @@ struct QQnxScreenContext inline QQnxScreenContext() : device(0), display(0), layer(0), hwSurface(0), memSurface(0), context(0) {} + inline ~QQnxScreenContext() + { cleanup(); } + + void cleanup(); gf_dev_t device; gf_dev_info_t deviceInfo; @@ -64,6 +70,35 @@ struct QQnxScreenContext gf_context_t context; }; +void QQnxScreenContext::cleanup() +{ + if (context) { + gf_context_free(context); + context = 0; + } + if (memSurface) { + gf_surface_free(memSurface); + memSurface = 0; + } + if (hwSurface) { + gf_surface_free(hwSurface); + hwSurface = 0; + } + if (layer) { + gf_layer_detach(layer); + layer = 0; + } + if (display) { + gf_display_detach(display); + display = 0; + } + if (device) { + gf_dev_detach(device); + device = 0; + } +} + + /*! \class QQnxScreen \preliminary @@ -117,19 +152,23 @@ QQnxScreen::~QQnxScreen() delete d; } -/*! \reimp +/*! + \reimp */ bool QQnxScreen::initDevice() { - // implement this if you have multiple processes that want to access the display - // (not required if QT_NO_QWS_MULTIPROCESS is set) +#ifndef QT_NO_QWS_CURSOR + QScreenCursor::initSoftwareCursor(); +#endif + return true; } -/*! \internal - Attaches to the named device \a name. +/*! + \internal + Attaches to the named device \a name. */ -static bool attachDevice(QQnxScreenContext * const d, const char *name) +static inline bool attachDevice(QQnxScreenContext * const d, const char *name) { int ret = gf_dev_attach(&d->device, name, &d->deviceInfo); if (ret != GF_ERR_OK) { @@ -139,193 +178,231 @@ static bool attachDevice(QQnxScreenContext * const d, const char *name) return true; } -/*! \internal - Attaches to the display at index \a displayIndex. - */ -static bool attachDisplay(QQnxScreenContext * const d, int displayIndex) +/*! + \internal + Attaches to the display at index \a displayIndex. +*/ +static inline bool attachDisplay(QQnxScreenContext * const d, int displayIndex) { int ret = gf_display_attach(&d->display, d->device, displayIndex, &d->displayInfo); if (ret != GF_ERR_OK) { - qWarning("QQnxScreen: gf_display_attach(%d) failed with error code %d", - displayIndex, ret); + qWarning("QQnxScreen: gf_display_attach(%d) failed with error code %d", displayIndex, ret); return false; } return true; } -/*! \internal - Attaches to the layer \a layerIndex. - */ -static bool attachLayer(QQnxScreenContext * const d, int layerIndex) +/*! + \internal + Attaches to the layer \a layerIndex. +*/ +static inline bool attachLayer(QQnxScreenContext * const d, int layerIndex) { - int ret = gf_layer_attach(&d->layer, d->display, layerIndex, 0); + unsigned flags = QApplication::type() != QApplication::GuiServer ? GF_LAYER_ATTACH_PASSIVE : 0; + int ret = gf_layer_attach(&d->layer, d->display, layerIndex, flags); if (ret != GF_ERR_OK) { - qWarning("QQnxScreen: gf_layer_attach(%d) failed with error code %d", layerIndex, - ret); + qWarning("QQnxScreen: gf_layer_attach(%d) failed with error code %d", layerIndex, ret); return false; } - gf_layer_enable(d->layer); return true; } -/*! \internal - Creates a new hardware surface (usually on the Gfx card memory) with the dimensions \a w * \a h. - */ -static bool createHwSurface(QQnxScreenContext * const d, int w, int h) +/*! + \internal + Creates a new hardware surface (usually on the Gfx card memory) with the dimensions \a w * \a h. +*/ +static inline bool createHwSurface(QQnxScreenContext * const d, int w, int h) { int ret = gf_surface_create_layer(&d->hwSurface, &d->layer, 1, 0, - w, h, GF_FORMAT_ARGB8888, 0, 0); + w, h, d->displayInfo.format, 0, 0); if (ret != GF_ERR_OK) { - qWarning("QQnxScreen: gf_surface_create_layer(%dx%d) failed with error code %d", - w, h, ret); + qWarning("QQnxScreen: gf_surface_create_layer(%dx%d) failed with error code %d", w, h, ret); return false; } gf_layer_set_surfaces(d->layer, &d->hwSurface, 1); + gf_layer_enable(d->layer); + ret = gf_layer_update(d->layer, 0); if (ret != GF_ERR_OK) { qWarning("QQnxScreen: gf_layer_update() failed with error code %d\n", ret); return false; } - return true; -} - -/*! \internal - Creates an in-memory, linear accessible surface of dimensions \a w * \a h. - This is the main surface that QWS blits to. - */ -static bool createMemSurface(QQnxScreenContext * const d, int w, int h) -{ - // Note: gf_surface_attach() could also be used, so we'll create the buffer - // and let the surface point to it. Here, we use surface_create instead. - - int ret = gf_surface_create(&d->memSurface, d->device, w, h, - GF_FORMAT_ARGB8888, 0, - GF_SURFACE_CREATE_CPU_FAST_ACCESS | GF_SURFACE_CREATE_CPU_LINEAR_ACCESSIBLE - | GF_SURFACE_PHYS_CONTIG | GF_SURFACE_CREATE_SHAREABLE); + ret = gf_context_create(&d->context); if (ret != GF_ERR_OK) { - qWarning("QQnxScreen: gf_surface_create(%dx%d) failed with error code %d", - w, h, ret); + qWarning("QQnxScreen: gf_context_create() failed with error code %d", ret); return false; } - gf_surface_get_info(d->memSurface, &d->memSurfaceInfo); - - if (d->memSurfaceInfo.sid == unsigned(GF_SID_INVALID)) { - qWarning("QQnxScreen: gf_surface_get_info() failed."); + ret = gf_context_set_surface(d->context, d->hwSurface); + if (ret != GF_ERR_OK) { + qWarning("QQnxScreen: gf_context_set_surface() failed with error code %d", ret); return false; } return true; } -/* \internal - Creates a QNX gf context and sets our memory surface on it. - */ -static bool createContext(QQnxScreenContext * const d) +/*! + \internal + Creates an in-memory, linear accessible surface of dimensions \a w * \a h. + This is the main surface that QWS blits to. +*/ +static inline bool createMemSurface(QQnxScreenContext * const d, int w, int h) { - int ret = gf_context_create(&d->context); +#ifndef QT_NO_QWS_MULTIPROCESS + if (QApplication::type() != QApplication::GuiServer) { + unsigned sidlist[64]; + int n = gf_surface_sidlist(d->device, sidlist); // undocumented API + for (int i = 0; i < n; ++i) { + int ret = gf_surface_attach_by_sid(&d->memSurface, d->device, sidlist[i]); + if (ret == GF_ERR_OK) { + gf_surface_get_info(d->memSurface, &d->memSurfaceInfo); + if (d->memSurfaceInfo.sid != unsigned(GF_SID_INVALID)) { + // can we use the surface's vaddr? + unsigned flags = GF_SURFACE_CPU_LINEAR_READABLE | GF_SURFACE_CPU_LINEAR_WRITEABLE; + if ((d->memSurfaceInfo.flags & flags) == flags) + return true; + } + + gf_surface_free(d->memSurface); + d->memSurface = 0; + } + } + qWarning("QQnxScreen: cannot attach to an usable surface; create a new one."); + } +#endif + int ret = gf_surface_create(&d->memSurface, d->device, w, h, d->displayInfo.format, 0, + GF_SURFACE_CREATE_CPU_FAST_ACCESS | GF_SURFACE_CREATE_CPU_LINEAR_ACCESSIBLE + | GF_SURFACE_CREATE_PHYS_CONTIG | GF_SURFACE_CREATE_SHAREABLE); if (ret != GF_ERR_OK) { - qWarning("QQnxScreen: gf_context_create() failed with error code %d", ret); + qWarning("QQnxScreen: gf_surface_create(%dx%d) failed with error code %d", + w, h, ret); return false; } - ret = gf_context_set_surface(d->context, d->memSurface); - if (ret != GF_ERR_OK) { - qWarning("QQnxScreen: gf_context_set_surface() failed with error code %d", ret); + gf_surface_get_info(d->memSurface, &d->memSurfaceInfo); + + if (d->memSurfaceInfo.sid == unsigned(GF_SID_INVALID)) { + qWarning("QQnxScreen: gf_surface_get_info() failed."); return false; } return true; } -/*! \reimp - Connects to QNX's io-display based device based on the \a displaySpec parameters - from the \c{QWS_DISPLAY} environment variable. See the QQnxScreen class documentation - for possible parameters. +/*! + \reimp + Connects to QNX's io-display based device based on the \a displaySpec parameters + from the \c{QWS_DISPLAY} environment variable. See the QQnxScreen class documentation + for possible parameters. - \sa QQnxScreen - */ + \sa QQnxScreen +*/ bool QQnxScreen::connect(const QString &displaySpec) { const QStringList params = displaySpec.split(QLatin1Char(':'), QString::SkipEmptyParts); - bool isOk = false; - QRegExp deviceRegExp(QLatin1String("^device=(.+)$")); - if (params.indexOf(deviceRegExp) != -1) { - isOk = attachDevice(d, deviceRegExp.cap(1).toLocal8Bit().constData()); - } else { - // no device specified - attach to device 0 (the default) - isOk = attachDevice(d, GF_DEVICE_INDEX(0)); + // default to device 0 + int deviceIndex = 0; + if (!params.isEmpty()) { + QRegExp deviceRegExp(QLatin1String("^device=(.+)$")); + if (params.indexOf(deviceRegExp) != -1) + deviceIndex = deviceRegExp.cap(1).toInt(); } - if (!isOk) + if (!attachDevice(d, GF_DEVICE_INDEX(deviceIndex))) return false; qDebug("QQnxScreen: Attached to Device, number of displays: %d", d->deviceInfo.ndisplays); - // default to display 0 - int displayIndex = 0; - QRegExp displayRegexp(QLatin1String("^display=(\\d+)$")); - if (params.indexOf(displayRegexp) != -1) { - displayIndex = displayRegexp.cap(1).toInt(); + // default to display id passed to constructor + int displayIndex = displayId; + if (!params.isEmpty()) { + QRegExp displayRegexp(QLatin1String("^display=(\\d+)$")); + if (params.indexOf(displayRegexp) != -1) + displayIndex = displayRegexp.cap(1).toInt(); } if (!attachDisplay(d, displayIndex)) return false; qDebug("QQnxScreen: Attached to Display %d, resolution %dx%d, refresh %d Hz", - displayIndex, d->displayInfo.xres, d->displayInfo.yres, - d->displayInfo.refresh); - + displayIndex, d->displayInfo.xres, d->displayInfo.yres, d->displayInfo.refresh); // default to main_layer_index from the displayInfo struct - int layerIndex = 0; - QRegExp layerRegexp(QLatin1String("^layer=(\\d+)$")); - if (params.indexOf(layerRegexp) != -1) { - layerIndex = layerRegexp.cap(1).toInt(); - } else { - layerIndex = d->displayInfo.main_layer_index; + int layerIndex = d->displayInfo.main_layer_index; + if (!params.isEmpty()) { + QRegExp layerRegexp(QLatin1String("^layer=(\\d+)$")); + if (params.indexOf(layerRegexp) != -1) + layerIndex = layerRegexp.cap(1).toInt(); } if (!attachLayer(d, layerIndex)) return false; + // determine the pixel format and the pixel type + switch (d->displayInfo.format) { +#if defined(QT_QWS_DEPTH_32) || defined(QT_QWS_DEPTH_GENERIC) + case GF_FORMAT_ARGB8888: + pixeltype = QScreen::BGRPixel; + // fall through + case GF_FORMAT_BGRA8888: + setPixelFormat(QImage::Format_ARGB32); + break; +#endif +#if defined(QT_QWS_DEPTH_24) + case GF_FORMAT_BGR888: + pixeltype = QScreen::BGRPixel; + setPixelFormat(QImage::Format_RGB888); + break; +#endif +#if defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_GENERIC) + case GF_FORMAT_PACK_RGB565: + case GF_FORMAT_PKLE_RGB565: + case GF_FORMAT_PKBE_RGB565: +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + setFrameBufferLittleEndian((d->displayInfo.format & GF_FORMAT_PKLE) == GF_FORMAT_PKLE); +#endif + setPixelFormat(QImage::Format_RGB16); + break; +#endif + default: + return false; + } + // tell QWSDisplay the width and height of the display w = dw = d->displayInfo.xres; h = dh = d->displayInfo.yres; - - // we only support 32 bit displays for now. - QScreen::d = 32; + QScreen::d = (d->displayInfo.format & GF_FORMAT_BPP); // colour depth // assume 72 dpi as default, to calculate the physical dimensions if not specified const int defaultDpi = 72; - - // Handle display physical size spec. - QRegExp mmWidthRegexp(QLatin1String("^mmWidth=(\\d+)$")); - if (params.indexOf(mmWidthRegexp) == -1) { - physWidth = qRound(dw * 25.4 / defaultDpi); - } else { - physWidth = mmWidthRegexp.cap(1).toInt(); + // Handle display physical size + physWidth = qRound(dw * 25.4 / defaultDpi); + physHeight = qRound(dh * 25.4 / defaultDpi); + if (!params.isEmpty()) { + QRegExp mmWidthRegexp(QLatin1String("^mmWidth=(\\d+)$")); + if (params.indexOf(mmWidthRegexp) != -1) + physWidth = mmWidthRegexp.cap(1).toInt(); + + QRegExp mmHeightRegexp(QLatin1String("^mmHeight=(\\d+)$")); + if (params.indexOf(mmHeightRegexp) != -1) + physHeight = mmHeightRegexp.cap(1).toInt(); } - QRegExp mmHeightRegexp(QLatin1String("^mmHeight=(\\d+)$")); - if (params.indexOf(mmHeightRegexp) == -1) { - physHeight = qRound(dh * 25.4 / defaultDpi); - } else { - physHeight = mmHeightRegexp.cap(1).toInt(); + if (QApplication::type() == QApplication::GuiServer) { + // create a hardware surface with our dimensions. In the old days, it was possible + // to get a pointer directly to the hw surface, so we could blit directly. Now, we + // have to use one indirection more, because it's not guaranteed that the hw surface + // is mappable into our process. + if (!createHwSurface(d, w, h)) + return false; } - // create a hardware surface with our dimensions. In the old days, it was possible - // to get a pointer directly to the hw surface, so we could blit directly. Now, we - // have to use one indirection more, because it's not guaranteed that the hw surface - // is mappable into our process. - if (!createHwSurface(d, w, h)) - return false; - // create an in-memory linear surface that is used by QWS. QWS will blit directly in here. if (!createMemSurface(d, w, h)) return false; @@ -338,72 +415,84 @@ bool QQnxScreen::connect(const QString &displaySpec) // the overall size of the in-memory buffer is linestep * height size = mapsize = lstep * h; - // create a QNX drawing context - if (!createContext(d)) - return false; - - // we're always using a software cursor for now. Initialize it here. - QScreenCursor::initSoftwareCursor(); - // done, the driver should be connected to the display now. return true; } -/*! \reimp - */ +/*! + \reimp +*/ void QQnxScreen::disconnect() { - if (d->context) - gf_context_free(d->context); - - if (d->memSurface) - gf_surface_free(d->memSurface); - - if (d->hwSurface) - gf_surface_free(d->hwSurface); - - if (d->layer) - gf_layer_detach(d->layer); - - if (d->display) - gf_display_detach(d->display); - - if (d->device) - gf_dev_detach(d->device); - - d->memSurface = 0; - d->hwSurface = 0; - d->context = 0; - d->layer = 0; - d->display = 0; - d->device = 0; + d->cleanup(); } -/*! \reimp - */ +/*! + \reimp +*/ void QQnxScreen::shutdownDevice() { } - -/*! \reimp - QQnxScreen doesn't support setting the mode, use io-display instead. - */ +/*! + \reimp + QQnxScreen doesn't support setting the mode, use io-display instead. +*/ void QQnxScreen::setMode(int,int,int) { qWarning("QQnxScreen: Unable to change mode, use io-display instead."); } -/*! \reimp - */ +/*! + \reimp +*/ bool QQnxScreen::supportsDepth(int depth) const { - // only 32-bit for the moment - return depth == 32; + gf_modeinfo_t displayMode; + for (int i = 0; gf_display_query_mode(d->display, i, &displayMode) == GF_ERR_OK; ++i) { + switch (displayMode.primary_format) { +#if defined(QT_QWS_DEPTH_32) || defined(QT_QWS_DEPTH_GENERIC) + case GF_FORMAT_ARGB8888: + case GF_FORMAT_BGRA8888: + if (depth == 32) + return true; + break; +#endif +#if defined(QT_QWS_DEPTH_24) + case GF_FORMAT_BGR888: + if (depth == 24) + return true; + break; +#endif +#if defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_GENERIC) + case GF_FORMAT_PACK_RGB565: + case GF_FORMAT_PKLE_RGB565: + case GF_FORMAT_PKBE_RGB565: + if (depth == 16) + return true; + break; +#endif + default: + break; + } + } + + return false; } -/*! \reimp - */ +/*! + \reimp +*/ +void QQnxScreen::blank(bool on) +{ + int ret = gf_display_set_dpms(d->display, on ? GF_DPMS_OFF : GF_DPMS_ON); + if (ret != GF_ERR_OK) + qWarning("QQnxScreen: gf_display_set_dpms() failed with error code %d", ret); +} + +/*! + \reimp +*/ void QQnxScreen::exposeRegion(QRegion r, int changing) { // here is where the actual magic happens. QWS will call exposeRegion whenever @@ -414,6 +503,10 @@ void QQnxScreen::exposeRegion(QRegion r, int changing) QScreen::exposeRegion(r, changing); // now our in-memory surface should be up to date with the latest changes. + + if (!d->hwSurface) + return; + // the code below copies the region from the in-memory surface to the hardware. // just get the bounding rectangle of the region. Most screen updates are rectangular @@ -432,16 +525,14 @@ void QQnxScreen::exposeRegion(QRegion r, int changing) // blit the changed region from the memory surface to the hardware surface ret = gf_draw_blit2(d->context, d->memSurface, d->hwSurface, - br.x(), br.y(), br.right(), br.bottom(), br.x(), br.y()); - if (ret != GF_ERR_OK) { + br.x(), br.y(), br.right(), br.bottom(), br.x(), br.y()); + if (ret != GF_ERR_OK) qWarning("QQnxScreen: gf_draw_blit2() failed with error code %d", ret); - } // flush all drawing commands (in our case, a single blit) ret = gf_draw_flush(d->context); - if (ret != GF_ERR_OK) { + if (ret != GF_ERR_OK) qWarning("QQnxScreen: gf_draw_flush() failed with error code %d", ret); - } // tell QNX that we're done drawing. gf_draw_end(d->context); diff --git a/src/gui/embedded/qscreenqnx_qws.h b/src/gui/embedded/qscreenqnx_qws.h index 38c0ac9..6f6d18a 100644 --- a/src/gui/embedded/qscreenqnx_qws.h +++ b/src/gui/embedded/qscreenqnx_qws.h @@ -66,6 +66,7 @@ public: void shutdownDevice(); void setMode(int,int,int); bool supportsDepth(int) const; + void blank(bool on); void exposeRegion(QRegion r, int changing); diff --git a/src/gui/embedded/qwslock.cpp b/src/gui/embedded/qwslock.cpp index c14f50b..f9ea000 100644 --- a/src/gui/embedded/qwslock.cpp +++ b/src/gui/embedded/qwslock.cpp @@ -45,12 +45,15 @@ #include "qwssignalhandler_p.h" +#include <stdint.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/sem.h> +#endif #include <sys/time.h> #include <time.h> #ifdef Q_OS_LINUX @@ -66,6 +69,12 @@ QT_BEGIN_NAMESPACE #error QWSLock currently requires semaphores #endif +#ifdef QT_POSIX_IPC +#include <QtCore/QAtomicInt> + +static QBasicAtomicInt localUniqueId = Q_BASIC_ATOMIC_INITIALIZER(1); +#endif + QWSLock::QWSLock(int id) : semId(id) { static unsigned short initialValues[3] = { 1, 1, 0 }; @@ -74,6 +83,7 @@ QWSLock::QWSLock(int id) : semId(id) QWSSignalHandler::instance()->addWSLock(this); #endif +#ifndef QT_POSIX_IPC if (semId == -1) { semId = semget(IPC_PRIVATE, 3, IPC_CREAT | 0666); if (semId == -1) { @@ -88,6 +98,30 @@ QWSLock::QWSLock(int id) : semId(id) qFatal("Unable to initialize semaphores"); } } +#else + sems[0] = sems[1] = sems[2] = SEM_FAILED; + owned = false; + + if (semId == -1) { + // ### generate really unique IDs + semId = (getpid() << 16) + (localUniqueId.fetchAndAddRelaxed(1) % ushort(-1)); + owned = true; + } + + QByteArray pfx = "/qwslock_" + QByteArray::number(semId, 16) + '_'; + QByteArray keys[3] = { pfx + "BackingStore", pfx + "Communication", pfx + "RegionEvent" }; + for (int i = 0; i < 3; ++i) { + if (owned) + sem_unlink(keys[i].constData()); + do { + sems[i] = sem_open(keys[i].constData(), (owned ? O_CREAT : 0), 0666, initialValues[i]); + } while (sems[i] == SEM_FAILED && errno == EINTR); + if (sems[i] == SEM_FAILED) { + perror("QWSLock::QWSLock"); + qFatal("Unable to %s semaphore", (owned ? "create" : "open")); + } + } +#endif lockCount[0] = lockCount[1] = 0; } @@ -99,10 +133,27 @@ QWSLock::~QWSLock() #endif if (semId != -1) { +#ifndef QT_POSIX_IPC qt_semun semval; semval.val = 0; semctl(semId, 0, IPC_RMID, semval); semId = -1; +#else + // emulate the SEM_UNDO behavior for the BackingStore lock + while (hasLock(BackingStore)) + unlock(BackingStore); + + QByteArray pfx = "/qwslock_" + QByteArray::number(semId, 16) + '_'; + QByteArray keys[3] = { pfx + "BackingStore", pfx + "Communication", pfx + "RegionEvent" }; + for (int i = 0; i < 3; ++i) { + if (sems[i] != SEM_FAILED) { + sem_close(sems[i]); + sems[i] = SEM_FAILED; + } + if (owned) + sem_unlink(keys[i].constData()); + } +#endif } } @@ -110,6 +161,7 @@ bool QWSLock::up(unsigned short semNum) { int ret; +#ifndef QT_POSIX_IPC sembuf sops = { semNum, 1, 0 }; // As the BackingStore lock is a mutex, and only one process may own // the lock, it's safe to use SEM_UNDO. On the other hand, the @@ -119,6 +171,9 @@ bool QWSLock::up(unsigned short semNum) sops.sem_flg |= SEM_UNDO; EINTR_LOOP(ret, semop(semId, &sops, 1)); +#else + ret = sem_post(sems[semNum]); +#endif if (ret == -1) { qDebug("QWSLock::up(): %s", strerror(errno)); return false; @@ -131,6 +186,7 @@ bool QWSLock::down(unsigned short semNum, int) { int ret; +#ifndef QT_POSIX_IPC sembuf sops = { semNum, -1, 0 }; // As the BackingStore lock is a mutex, and only one process may own // the lock, it's safe to use SEM_UNDO. On the other hand, the @@ -140,6 +196,9 @@ bool QWSLock::down(unsigned short semNum, int) sops.sem_flg |= SEM_UNDO; EINTR_LOOP(ret, semop(semId, &sops, 1)); +#else + EINTR_LOOP(ret, sem_wait(sems[semNum])); +#endif if (ret == -1) { qDebug("QWSLock::down(): %s", strerror(errno)); return false; @@ -150,7 +209,13 @@ bool QWSLock::down(unsigned short semNum, int) int QWSLock::getValue(unsigned short semNum) const { - int ret = semctl(semId, semNum, GETVAL, 0); + int ret; +#ifndef QT_POSIX_IPC + ret = semctl(semId, semNum, GETVAL, 0); +#else + if (sem_getvalue(sems[semNum], &ret) == -1) + ret = -1; +#endif if (ret == -1) qDebug("QWSLock::getValue(): %s", strerror(errno)); return ret; diff --git a/src/gui/embedded/qwslock_p.h b/src/gui/embedded/qwslock_p.h index d020b22..71a4cca 100644 --- a/src/gui/embedded/qwslock_p.h +++ b/src/gui/embedded/qwslock_p.h @@ -57,6 +57,10 @@ #ifndef QT_NO_QWS_MULTIPROCESS +#ifdef QT_POSIX_IPC +# include <semaphore.h> +#endif + QT_BEGIN_NAMESPACE class QWSLock @@ -80,6 +84,10 @@ private: int semId; int lockCount[2]; +#ifdef QT_POSIX_IPC + sem_t *sems[3]; + bool owned; +#endif }; QT_END_NAMESPACE diff --git a/src/gui/embedded/qwssharedmemory.cpp b/src/gui/embedded/qwssharedmemory.cpp index a677626..853de61 100644 --- a/src/gui/embedded/qwssharedmemory.cpp +++ b/src/gui/embedded/qwssharedmemory.cpp @@ -45,14 +45,37 @@ #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/shm.h> +#else +#include <sys/mman.h> +#include <sys/stat.h> +#endif +#include <fcntl.h> +#include <unistd.h> + +#include <private/qcore_unix_p.h> //#define QT_SHM_DEBUG QT_BEGIN_NAMESPACE +#ifdef QT_POSIX_IPC +#include <QtCore/QAtomicInt> + +static QBasicAtomicInt localUniqueId = Q_BASIC_ATOMIC_INITIALIZER(1); + +static inline QByteArray makeKey(int id) +{ + return "/qwsshm_" + QByteArray::number(id, 16); +} +#endif + QWSSharedMemory::QWSSharedMemory() : shmId(-1), shmBase(0), shmSize(0) +#ifdef QT_POSIX_IPC + , hand(-1) +#endif { } @@ -66,19 +89,47 @@ bool QWSSharedMemory::create(int size) if (shmId != -1) detach(); +#ifndef QT_POSIX_IPC shmId = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600); +#else + // ### generate really unique IDs + shmId = (getpid() << 16) + (localUniqueId.fetchAndAddRelaxed(1) % ushort(-1)); + QByteArray shmName = makeKey(shmId); + EINTR_LOOP(hand, shm_open(shmName.constData(), O_RDWR | O_CREAT, 0660)); + if (hand != -1) { + // the size may only be set once; ignore errors + int ret; + EINTR_LOOP(ret, ftruncate(hand, size)); + if (ret == -1) + shmId = -1; + } else { + shmId = -1; + } +#endif if (shmId == -1) { #ifdef QT_SHM_DEBUG perror("QWSSharedMemory::create():"); qWarning("Error allocating shared memory of size %d", size); #endif + detach(); return false; } + +#ifndef QT_POSIX_IPC shmBase = shmat(shmId, 0, 0); // On Linux, it is possible to attach a shared memory segment even if it // is already marked to be deleted. However, POSIX.1-2001 does not specify // this behaviour and many other implementations do not support it. shmctl(shmId, IPC_RMID, 0); +#else + // grab the size + QT_STATBUF st; + if (QT_FSTAT(hand, &st) != -1) { + shmSize = st.st_size; + // grab the memory + shmBase = mmap(0, shmSize, PROT_READ | PROT_WRITE, MAP_SHARED, hand, 0); + } +#endif if (shmBase == (void*)-1 || !shmBase) { #ifdef QT_SHM_DEBUG perror("QWSSharedMemory::create():"); @@ -102,7 +153,21 @@ bool QWSSharedMemory::attach(int id) return false; shmId = id; +#ifndef QT_POSIX_IPC shmBase = shmat(shmId, 0, 0); +#else + QByteArray shmName = makeKey(shmId); + EINTR_LOOP(hand, shm_open(shmName.constData(), O_RDWR, 0660)); + if (hand != -1) { + // grab the size + QT_STATBUF st; + if (QT_FSTAT(hand, &st) != -1) { + shmSize = st.st_size; + // grab the memory + shmBase = mmap(0, shmSize, PROT_READ | PROT_WRITE, MAP_SHARED, hand, 0); + } + } +#endif if (shmBase == (void*)-1 || !shmBase) { #ifdef QT_SHM_DEBUG perror("QWSSharedMemory::attach():"); @@ -117,8 +182,28 @@ bool QWSSharedMemory::attach(int id) void QWSSharedMemory::detach() { +#ifndef QT_POSIX_IPC if (shmBase && shmBase != (void*)-1) shmdt(shmBase); +#else + if (shmBase && shmBase != (void*)-1) + munmap(shmBase, shmSize); + if (hand > 0) { + // get the number of current attachments + int shm_nattch = 0; + QT_STATBUF st; + if (QT_FSTAT(hand, &st) == 0) { + // subtract 2 from linkcount: one for our own open and one for the dir entry + shm_nattch = st.st_nlink - 2; + } + qt_safe_close(hand); + // if there are no attachments then unlink the shared memory + if (shm_nattch == 0) { + QByteArray shmName = makeKey(shmId); + shm_unlink(shmName.constData()); + } + } +#endif shmBase = 0; shmSize = 0; shmId = -1; @@ -129,11 +214,13 @@ int QWSSharedMemory::size() const if (shmId == -1) return 0; +#ifndef QT_POSIX_IPC if (!shmSize) { struct shmid_ds shm; shmctl(shmId, IPC_STAT, &shm); - const_cast<QWSSharedMemory *>(this)->shmSize = shm.shm_segsz; + shmSize = shm.shm_segsz; } +#endif return shmSize; } diff --git a/src/gui/embedded/qwssharedmemory_p.h b/src/gui/embedded/qwssharedmemory_p.h index f3ce241..42ef6c8 100644 --- a/src/gui/embedded/qwssharedmemory_p.h +++ b/src/gui/embedded/qwssharedmemory_p.h @@ -77,7 +77,10 @@ public: private: int shmId; void *shmBase; - int shmSize; + mutable int shmSize; +#ifdef QT_POSIX_IPC + int hand; +#endif }; #endif // QT_NO_QWS_MULTIPROCESS diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp index 76d2d04..6fbe849 100644 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ b/src/gui/graphicsview/qgraphicslayout.cpp @@ -269,18 +269,8 @@ void QGraphicsLayout::activate() return; Q_ASSERT(!parentItem->isLayout()); - if (QGraphicsLayout::instantInvalidatePropagation()) { - QGraphicsWidget *parentWidget = static_cast<QGraphicsWidget*>(parentItem); - if (!parentWidget->parentLayoutItem()) { - // we've reached the topmost widget, resize it - bool wasResized = parentWidget->testAttribute(Qt::WA_Resized); - parentWidget->resize(parentWidget->size()); - parentWidget->setAttribute(Qt::WA_Resized, wasResized); - } - - setGeometry(parentItem->contentsRect()); // relayout children - } else { - setGeometry(parentItem->contentsRect()); // relayout children + setGeometry(parentItem->contentsRect()); // relayout children + if (!QGraphicsLayout::instantInvalidatePropagation()) { parentLayoutItem()->updateGeometry(); } } diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 804394a..965b1b34 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -347,11 +347,10 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) { QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func(); QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr.data(); - QRectF newGeom; + QRectF newGeom = rect; QPointF oldPos = d->geom.topLeft(); if (!wd->inSetPos) { setAttribute(Qt::WA_Resized); - newGeom = rect; newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize)) .boundedTo(effectiveSizeHint(Qt::MaximumSize))); @@ -405,14 +404,7 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) emit widthChanged(); if (oldSize.height() != newGeom.size().height()) emit heightChanged(); - QGraphicsLayout *lay = wd->layout; - if (QGraphicsLayout::instantInvalidatePropagation()) { - if (!lay || lay->isActivated()) { - QApplication::sendEvent(this, &re); - } - } else { - QApplication::sendEvent(this, &re); - } + QApplication::sendEvent(this, &re); } } @@ -1091,8 +1083,11 @@ void QGraphicsWidget::updateGeometry() * When the event is received, it will start flowing all the way down to the leaf * widgets in one go. This will make a relayout flicker-free. */ - if (QGraphicsLayout::instantInvalidatePropagation()) - QApplication::postEvent(static_cast<QGraphicsWidget *>(this), new QEvent(QEvent::LayoutRequest)); + if (QGraphicsLayout::instantInvalidatePropagation()) { + Q_D(QGraphicsWidget); + ++d->refCountInvokeRelayout; + QMetaObject::invokeMethod(this, "_q_relayout", Qt::QueuedConnection); + } } if (!QGraphicsLayout::instantInvalidatePropagation()) { bool wasResized = testAttribute(Qt::WA_Resized); diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index 063be2d..5085817 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -234,6 +234,8 @@ protected: private: Q_DISABLE_COPY(QGraphicsWidget) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsWidget) + Q_PRIVATE_SLOT(d_func(), void _q_relayout()) + friend class QGraphicsScene; friend class QGraphicsScenePrivate; friend class QGraphicsView; diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index 8649dec..ca6713b 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -233,6 +233,18 @@ void QGraphicsWidgetPrivate::resolveLayoutDirection() } } +/* private slot */ +void QGraphicsWidgetPrivate::_q_relayout() +{ + --refCountInvokeRelayout; + if (refCountInvokeRelayout == 0) { + Q_Q(QGraphicsWidget); + bool wasResized = q->testAttribute(Qt::WA_Resized); + q->resize(q->size()); // this will restrict the size + q->setAttribute(Qt::WA_Resized, wasResized); + } +} + QPalette QGraphicsWidgetPrivate::naturalWidgetPalette() const { Q_Q(const QGraphicsWidget); @@ -903,4 +915,6 @@ void QGraphicsWidgetPrivate::setGeometryFromSetPos() QT_END_NAMESPACE +#include "moc_qgraphicswidget.cpp" + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h index 398abc3..6ea2586 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.h +++ b/src/gui/graphicsview/qgraphicswidget_p.h @@ -81,6 +81,7 @@ public: polished(0), inSetPos(0), autoFillBackground(0), + refCountInvokeRelayout(0), focusPolicy(Qt::NoFocus), focusNext(0), focusPrev(0), @@ -106,6 +107,7 @@ public: QGraphicsLayout *layout; void setLayoutDirection_helper(Qt::LayoutDirection direction); void resolveLayoutDirection(); + void _q_relayout(); // Style QPalette palette; @@ -179,11 +181,14 @@ public: return false; return (attributes & (1 << bit)) != 0; } + // 32 bits + quint32 refCountInvokeRelayout : 16; quint32 attributes : 10; quint32 inSetGeometry : 1; quint32 polished: 1; quint32 inSetPos : 1; quint32 autoFillBackground : 1; + quint32 padding : 2; // feel free to use // Focus Qt::FocusPolicy focusPolicy; diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 5b75aa1..f07843d 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -56,6 +56,10 @@ #include <QtGui/qpixmap.h> #include <QtCore/qatomic.h> +#ifdef Q_OS_SYMBIAN +#include <QtGui/private/qvolatileimage_p.h> +#endif + QT_BEGIN_NAMESPACE class QImageReader; @@ -135,6 +139,7 @@ public: } #if defined(Q_OS_SYMBIAN) + virtual QVolatileImage toVolatileImage() const { return QVolatileImage(); } virtual void* toNativeType(NativeType type); virtual void fromNativeType(void* pixmap, NativeType type); #endif diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index ebf0ff8..d603540 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -646,6 +646,7 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) { using namespace Qt; + reset(); commitTemporaryPreeditString(); const bool anynumbermodes = hints & (ImhDigitsOnly | ImhFormattedNumbersOnly | ImhDialableCharactersOnly); diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp index abee361..3b6a075 100644 --- a/src/gui/kernel/qapplication_qws.cpp +++ b/src/gui/kernel/qapplication_qws.cpp @@ -209,7 +209,7 @@ QString qws_dataDir() if (!S_ISDIR(buf.st_mode)) qFatal("%s is not a directory", dataDir.constData()); -#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) +#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) && !defined(Q_OS_QNX) if (buf.st_uid != getuid()) qFatal("Qt for Embedded Linux data directory is not owned by user %d", getuid()); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 31d02d4..086cfec 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1531,6 +1531,11 @@ void QSymbianControl::HandleResourceChange(int resourceType) QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size()); QApplication::sendEvent(qt_desktopWidget, &e); } + // Send resize event to dialogs so they can adjust their position if necessary. + if (qwidget->windowType() & Qt::Dialog) { + QResizeEvent e(qwidget->size(), qwidget->size()); + QApplication::sendEvent(qwidget, &e); + } break; } #endif diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 778f1f1..b3bf365 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -4551,6 +4551,11 @@ void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isM QPoint oldp = q->pos(); QSize olds = q->size(); + // Apply size restrictions, applicable for Windows & Widgets. + if (QWExtra *extra = extraData()) { + w = qBound(extra->minw, w, extra->maxw); + h = qBound(extra->minh, h, extra->maxh); + } const bool isResize = (olds != QSize(w, h)); if (!realWindow && !isResize && QPoint(x, y) == oldp) @@ -4560,13 +4565,6 @@ void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isM data.window_state = data.window_state & ~Qt::WindowMaximized; const bool visible = q->isVisible(); - // Apply size restrictions, applicable for Windows & Widgets. - if (QWExtra *extra = extraData()) { - w = qMin(w, extra->maxw); - h = qMin(h, extra->maxh); - w = qMax(w, extra->minw); - h = qMax(h, extra->minh); - } data.crect = QRect(x, y, w, h); if (realWindow) { diff --git a/src/gui/painting/qwindowsurface_qws.cpp b/src/gui/painting/qwindowsurface_qws.cpp index 7e8cf9b..3789a33 100644 --- a/src/gui/painting/qwindowsurface_qws.cpp +++ b/src/gui/painting/qwindowsurface_qws.cpp @@ -1065,10 +1065,12 @@ bool QWSSharedMemSurface::setMemory(int memId) return true; mem.detach(); - if (!mem.attach(memId)) { + + if (memId != -1 && !mem.attach(memId)) { +#ifndef QT_NO_DEBUG perror("QWSSharedMemSurface: attaching to shared memory"); - qCritical("QWSSharedMemSurface: Error attaching to" - " shared memory 0x%x", memId); + qCritical("QWSSharedMemSurface: Error attaching to shared memory 0x%x", memId); +#endif return false; } diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp index c83e929..313000f 100644 --- a/src/gui/text/qfontdatabase_qws.cpp +++ b/src/gui/text/qfontdatabase_qws.cpp @@ -75,6 +75,11 @@ #include <qresource.h> #endif +#ifdef Q_OS_QNX +// ### using QFontEngineQPF leads to artifacts on QNX +# define QT_NO_QWS_SHARE_FONTS +#endif + QT_BEGIN_NAMESPACE #ifndef QT_NO_LIBRARY diff --git a/src/network/access/qnetworkcookiejar.cpp b/src/network/access/qnetworkcookiejar.cpp index a2fa689..1a5f73b 100644 --- a/src/network/access/qnetworkcookiejar.cpp +++ b/src/network/access/qnetworkcookiejar.cpp @@ -220,20 +220,33 @@ bool QNetworkCookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieLis continue; // not accepted } - QList<QNetworkCookie>::Iterator it = d->allCookies.begin(), - end = d->allCookies.end(); - for ( ; it != end; ++it) + for (int i = 0; i < d->allCookies.size(); ++i) { // does this cookie already exist? - if (cookie.name() == it->name() && - cookie.domain() == it->domain() && - cookie.path() == it->path()) { + const QNetworkCookie ¤t = d->allCookies.at(i); + if (cookie.name() == current.name() && + cookie.domain() == current.domain() && + cookie.path() == current.path()) { // found a match - d->allCookies.erase(it); + d->allCookies.removeAt(i); break; } + } // did not find a match if (!isDeletion) { + int countForDomain = 0; + for (int i = d->allCookies.size() - 1; i >= 0; --i) { + // Start from the end and delete the oldest cookies to keep a maximum count of 50. + const QNetworkCookie ¤t = d->allCookies.at(i); + if (isParentDomain(cookie.domain(), current.domain()) + || isParentDomain(current.domain(), cookie.domain())) { + if (countForDomain >= 49) + d->allCookies.removeAt(i); + else + ++countForDomain; + } + } + d->allCookies += cookie; ++added; } diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 15635ff..edd5d6e 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -196,8 +196,14 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so #ifdef QNATIVESOCKETENGINE_DEBUG qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was set" << err; #endif - } else - err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead + } else { +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was not set, using implicit connection"; +#endif + // using implicit connection allows localhost connections without starting any RConnection, see QTBUG-16155 and QTBUG-16843 + // when a remote address is used, socket server will start the system default connection if there is no route. + err = nativeSocket.Open(socketServer, family, type, protocol); + } if (err != KErrNone) { switch (err) { @@ -564,12 +570,12 @@ bool QSymbianSocketEngine::connectToHostByName(const QString &name, quint16 port If there's a connection activity on the socket, process it. Then notify our parent if there really was activity. */ -void QSymbianSocketEngine::connectionNotification() +void QSymbianSocketEngine::connectionComplete() { - // FIXME check if we really need to do it like that in Symbian Q_D(QSymbianSocketEngine); Q_ASSERT(state() == QAbstractSocket::ConnectingState); + // as it was a non blocking connect, call again to find the result. connectToHost(d->peerAddress, d->peerPort); if (state() != QAbstractSocket::ConnectingState) { // we changed states @@ -906,7 +912,6 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, return sentBytes(); } -// FIXME check where the native socket engine called that.. bool QSymbianSocketEnginePrivate::fetchConnectionParameters() { localPort = 0; @@ -990,9 +995,15 @@ void QSymbianSocketEngine::close() d->asyncSelect = 0; } - //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? + //RSocket::Shutdown(EImmediate) performs a fast disconnect. For TCP, + //this would mean sending RST rather than FIN so we don't do that. + //Qt's disconnectFromHost() API doesn't expose this choice. + //RSocket::Close will internally do a normal shutdown of the socket. if (d->socketType == QAbstractSocket::UdpSocket) { - //TODO: Close hangs without this, but only for UDP - why? + //RSocket::Close has been observed to block for a long time with + //UDP sockets. Doing an immediate shutdown first works around this + //problem. Since UDP is connectionless, there should be no difference + //at the network interface. TRequestStatus stat; d->nativeSocket.Shutdown(RSocket::EImmediate, stat); User::WaitForRequest(stat); @@ -1189,7 +1200,6 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool #endif } if (err) { - //TODO: avoidable cast? //set the error here, because read won't always return the same error again as select. const_cast<QSymbianSocketEnginePrivate*>(this)->setError(err); //restart asynchronous notifier (only one IOCTL allowed at a time) @@ -1265,7 +1275,7 @@ bool QSymbianSocketEnginePrivate::multicastGroupMembershipHelper(const QHostAddr QNetworkInterface QSymbianSocketEngine::multicastInterface() const { - //TODO + //### symbian 3 has no API equivalent to this const Q_D(QSymbianSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::multicastInterface(), QNetworkInterface()); Q_CHECK_TYPE(QSymbianSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface()); @@ -1274,7 +1284,8 @@ QNetworkInterface QSymbianSocketEngine::multicastInterface() const bool QSymbianSocketEngine::setMulticastInterface(const QNetworkInterface &iface) { - //TODO - this is possibly a unix'ism as the RConnection on which the socket was created is probably controlling this + //### symbian 3 has no API equivalent to this + //this is possibly a unix'ism as the RConnection on which the socket was created is probably controlling this Q_D(QSymbianSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setMulticastInterface(), false); Q_CHECK_TYPE(QSymbianSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false); @@ -1711,7 +1722,7 @@ void QAsyncSelect::run() if (engine && engine->isWriteNotificationEnabled() && ((m_selectBuf() & KSockSelectWrite) || iStatus != KErrNone)) { if (engine->state() == QAbstractSocket::ConnectingState) - engine->connectionNotification(); + engine->connectionComplete(); else engine->writeNotification(); } diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 81156fc..3b39096 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -136,10 +136,7 @@ public: Q_INVOKABLE void startNotifications(); -public Q_SLOTS: - // TODO: Why do we do this? This is private Qt implementation stuff anyway, no need for it - // non-virtual override; - void connectionNotification(); + void connectionComplete(); private: Q_DECLARE_PRIVATE(QSymbianSocketEngine) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 4747f29..9a137a6 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1338,9 +1338,9 @@ bool QSslSocketBackendPrivate::startHandshake() sslErrors.clear(); } - // if we have a max read buffer size, reset the plain socket's to 16k + // if we have a max read buffer size, reset the plain socket's to 32k if (readBufferMaxSize) - plainSocket->setReadBufferSize(16384); + plainSocket->setReadBufferSize(32768); connectionEncrypted = true; emit q->encrypted(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 9ce7d55..52450b6 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1386,14 +1386,11 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c ensureActive(); d->transferMode(ImageDrawingMode); - QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption|QGLContext::CanFlipNativePixmapBindOption; -#ifdef QGL_USE_TEXTURE_POOL - bindOptions |= QGLContext::TemporarilyCachedBindOption; -#endif - glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLTexture *texture = - ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, bindOptions); + ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, + QGLContext::InternalBindOption + | QGLContext::CanFlipNativePixmapBindOption); GLfloat top = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.top()) : src.top(); GLfloat bottom = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.bottom()) : src.bottom(); @@ -1405,12 +1402,6 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap); - - if (texture->options&QGLContext::TemporarilyCachedBindOption) { - // pixmap was temporarily cached as a QImage texture by pooling system - // and should be destroyed immediately - QGLTextureCache::instance()->remove(ctx, texture->id); - } } void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src, @@ -1435,23 +1426,12 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption; -#ifdef QGL_USE_TEXTURE_POOL - bindOptions |= QGLContext::TemporarilyCachedBindOption; -#endif - - QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, bindOptions); + QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); GLuint id = texture->id; d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, id); d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); - - if (texture->options&QGLContext::TemporarilyCachedBindOption) { - // image was temporarily cached by texture pooling system - // and should be destroyed immediately - QGLTextureCache::instance()->remove(ctx, texture->id); - } } void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) diff --git a/src/opengl/gl2paintengineex/qtriangulator.cpp b/src/opengl/gl2paintengineex/qtriangulator.cpp index 7c3be2b..5293eff 100644 --- a/src/opengl/gl2paintengineex/qtriangulator.cpp +++ b/src/opengl/gl2paintengineex/qtriangulator.cpp @@ -1309,6 +1309,9 @@ inline void QRingBuffer<T>::enqueue(const T &x) //============================================================================// // QTriangulator // //============================================================================// + +typedef QRBTree<int>::Node *QRBTreeIntNodePointer; + template<typename T> class QTriangulator { @@ -1775,7 +1778,7 @@ bool QTriangulator<T>::ComplexToSimple::edgeIsLeftOfEdge(int leftEdgeIndex, int } template <typename T> -QRBTree<int>::Node *QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex) const +QRBTreeIntNodePointer QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex) const { QRBTree<int>::Node *current = m_edgeList.root; QRBTree<int>::Node *result = 0; @@ -1791,7 +1794,7 @@ QRBTree<int>::Node *QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edge } template <typename T> -QRBTree<int>::Node *QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const +QRBTreeIntNodePointer QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const { if (!m_edgeList.root) return after; diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index e7c1c44..ce1a5d2 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -157,10 +157,10 @@ embedded { } symbian { - DEFINES += QGL_USE_TEXTURE_POOL QGL_NO_PRESERVED_SWAP + DEFINES += QGL_NO_PRESERVED_SWAP SOURCES -= qpixmapdata_gl.cpp SOURCES += qgl_symbian.cpp \ - qpixmapdata_poolgl.cpp \ + qpixmapdata_symbiangl.cpp \ qglpixelbuffer_egl.cpp \ qgl_egl.cpp \ qgltexturepool.cpp diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 5f5864d..9520b2b 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -100,7 +100,8 @@ #if defined(QT_OPENGL_ES) && !defined(QT_NO_EGL) #include <EGL/egl.h> #endif -#ifdef QGL_USE_TEXTURE_POOL + +#ifdef Q_OS_SYMBIAN #include <private/qgltexturepool_p.h> #endif @@ -2042,10 +2043,6 @@ struct DDSFormat { the pixmap/image that it stems from, e.g. installing destruction hooks in them. - \omitvalue TemporarilyCachedBindOption Used by paint engines on some - platforms to indicate that the pixmap or image texture is possibly - cached only temporarily and must be destroyed immediately after the use. - \omitvalue InternalBindOption */ @@ -2550,7 +2547,8 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G #endif const QImage &constRef = img; // to avoid detach in bits()... -#ifdef QGL_USE_TEXTURE_POOL +#ifdef Q_OS_SYMBIAN + // On Symbian we always use texture pool to reserve the texture QGLTexturePool::instance()->createPermanentTexture(tx_id, target, 0, internalFormat, @@ -2562,6 +2560,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, pixel_type, constRef.bits()); #endif + #if defined(QT_OPENGL_ES_2) if (genMipmap) glGenerateMipmap(target); @@ -2585,6 +2584,13 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G QGLTexture *texture = new QGLTexture(q, tx_id, target, options); QGLTextureCache::instance()->insert(q, key, texture, cost); +#ifdef Q_OS_SYMBIAN + // Store the key so that QGLTexturePool + // is able to release this texture when needed. + texture->boundKey = key; + // And append to LRU list + QGLTexturePool::instance()->useTexture(texture); +#endif return texture; } @@ -2665,6 +2671,20 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, #endif if (!texture) { +#ifdef Q_OS_SYMBIAN + // On Symbian pixmaps are backed up by native CFbsBitmap + // which can be shared across processes. QVolatileImage wraps + // it and provides locking mechanism to pixel access. + QVolatileImage volatileImage = pd->toVolatileImage(); + if (volatileImage.isNull()) { // TODO: raster graphics system don't provide volatile image (yet) + // NOTE! On Symbian raster graphics system QPixmap::toImage() makes deep copy + texture = bindTexture(pixmap.toImage(), target, format, key, options); + } else { + volatileImage.beginDataAccess(); + texture = bindTexture(volatileImage.imageRef(), target, format, key, options); + volatileImage.endDataAccess(true); + } +#else QImage image = pixmap.toImage(); // If the system depth is 16 and the pixmap doesn't have an alpha channel // then we convert it to RGB16 in the hope that it gets uploaded as a 16 @@ -2672,6 +2692,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, if (pixmap.depth() == 16 && !image.hasAlphaChannel() ) image = image.convertToFormat(QImage::Format_RGB16); texture = bindTexture(image, target, format, key, options); +#endif } // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null Q_ASSERT(texture); @@ -6063,4 +6084,26 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) #undef ctx +#ifdef Q_OS_SYMBIAN +void QGLTexture::freeTexture() +{ + if (!id) + return; + + if (inTexturePool) + QGLTexturePool::instance()->detachTexture(this); + + if (boundPixmap) + boundPixmap->releaseNativeImageHandle(); + + if (options & QGLContext::MemoryManagedBindOption) { + Q_ASSERT(context); + context->d_ptr->texture_destroyer->emitFreeTexture(context, 0, id); + } + + id = 0; + boundKey = 0; +} +#endif + QT_END_NAMESPACE diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 1f4eda3..3d31242 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -341,7 +341,6 @@ public: MemoryManagedBindOption = 0x0010, // internal flag CanFlipNativePixmapBindOption = 0x0020, // internal flag - TemporarilyCachedBindOption = 0x0040, // internal flag DefaultBindOption = LinearFilteringBindOption | InvertedYBindOption diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 4748521..de349a7 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -64,6 +64,12 @@ #include "qcache.h" #include "qglpaintdevice_p.h" +#ifdef Q_OS_SYMBIAN +#include "qgltexturepool_p.h" + +class QGLPixmapData; +#endif + #ifndef QT_NO_EGL #include <QtGui/private/qegl_p.h> #endif @@ -562,10 +568,21 @@ public: options(opt) #if defined(Q_WS_X11) , boundPixmap(0) +#elif defined(Q_OS_SYMBIAN) + , boundPixmap(0) + , boundKey(0) + , nextLRU(0) + , prevLRU(0) + , inLRU(false) + , failedToAlloc(false) + , inTexturePool(false) #endif {} ~QGLTexture() { +#ifdef Q_OS_SYMBIAN + freeTexture(); +#else if (options & QGLContext::MemoryManagedBindOption) { Q_ASSERT(context); #if !defined(Q_WS_X11) @@ -573,7 +590,8 @@ public: #endif context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id); } - } +#endif + } QGLContext *context; GLuint id; @@ -593,6 +611,19 @@ public: (const char *buf, int len, const char *format = 0); QSize bindCompressedTextureDDS(const char *buf, int len); QSize bindCompressedTexturePVR(const char *buf, int len); + +#ifdef Q_OS_SYMBIAN + void freeTexture(); + + QGLPixmapData* boundPixmap; + qint64 boundKey; + + QGLTexture *nextLRU; + QGLTexture *prevLRU; + mutable bool inLRU; + mutable bool failedToAlloc; + mutable bool inTexturePool; +#endif }; struct QGLTextureCacheKey { diff --git a/src/opengl/qgltexturepool.cpp b/src/opengl/qgltexturepool.cpp index d809328..9ad66f2 100644 --- a/src/opengl/qgltexturepool.cpp +++ b/src/opengl/qgltexturepool.cpp @@ -41,6 +41,7 @@ #include "qgltexturepool_p.h" #include "qpixmapdata_gl_p.h" +#include "qgl_p.h" QT_BEGIN_NAMESPACE @@ -53,8 +54,8 @@ class QGLTexturePoolPrivate public: QGLTexturePoolPrivate() : lruFirst(0), lruLast(0) {} - QGLPixmapData *lruFirst; - QGLPixmapData *lruLast; + QGLTexture *lruFirst; + QGLTexture *lruLast; }; QGLTexturePool::QGLTexturePool() @@ -73,36 +74,36 @@ QGLTexturePool *QGLTexturePool::instance() return qt_gl_texture_pool; } -GLuint QGLTexturePool::createTextureForPixmap(GLenum target, +GLuint QGLTexturePool::createTexture(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data) + QGLTexture *texture) { - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(target, texture); + GLuint tex; + glGenTextures(1, &tex); + glBindTexture(target, tex); do { glTexImage2D(target, level, internalformat, width, height, 0, format, type, 0); GLenum error = glGetError(); if (error == GL_NO_ERROR) { - if (data) - moveToHeadOfLRU(data); - return texture; + if (texture) + moveToHeadOfLRU(texture); + return tex; } else if (error != GL_OUT_OF_MEMORY) { qWarning("QGLTexturePool: cannot create temporary texture because of invalid params"); return 0; } - } while (reclaimSpace(internalformat, width, height, format, type, data)); - qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap", + } while (reclaimSpace(internalformat, width, height, format, type, texture)); + qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d texture", width, height); return 0; } -bool QGLTexturePool::createPermanentTexture(GLuint texture, +bool QGLTexturePool::createPermanentTexture(GLuint tex, GLenum target, GLint level, GLint internalformat, @@ -112,7 +113,7 @@ bool QGLTexturePool::createPermanentTexture(GLuint texture, GLenum type, const GLvoid *data) { - glBindTexture(target, texture); + glBindTexture(target, tex); do { glTexImage2D(target, level, internalformat, width, height, 0, format, type, data); @@ -124,32 +125,21 @@ bool QGLTexturePool::createPermanentTexture(GLuint texture, return false; } } while (reclaimSpace(internalformat, width, height, format, type, 0)); - qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap", + qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d texture", width, height); return 0; } -void QGLTexturePool::releaseTexture(QGLPixmapData *data, GLuint texture) +void QGLTexturePool::useTexture(QGLTexture *texture) { - // Very simple strategy at the moment: just destroy the texture. - if (data) - removeFromLRU(data); - - QGLWidget *shareWidget = qt_gl_share_widget(); - if (shareWidget) { - QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &texture); - } -} - -void QGLTexturePool::useTexture(QGLPixmapData *data) -{ - moveToHeadOfLRU(data); + moveToHeadOfLRU(texture); + texture->inTexturePool = true; } -void QGLTexturePool::detachTexture(QGLPixmapData *data) +void QGLTexturePool::detachTexture(QGLTexture *texture) { - removeFromLRU(data); + removeFromLRU(texture); + texture->inTexturePool = false; } bool QGLTexturePool::reclaimSpace(GLint internalformat, @@ -157,7 +147,7 @@ bool QGLTexturePool::reclaimSpace(GLint internalformat, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data) + QGLTexture *texture) { Q_UNUSED(internalformat); // For future use in picking the best texture to eject. Q_UNUSED(width); @@ -167,19 +157,22 @@ bool QGLTexturePool::reclaimSpace(GLint internalformat, bool succeeded = false; bool wasInLRU = false; - if (data) { - wasInLRU = data->inLRU; - moveToHeadOfLRU(data); + if (texture) { + wasInLRU = texture->inLRU; + moveToHeadOfLRU(texture); } - QGLPixmapData *lrudata = pixmapLRU(); - if (lrudata && lrudata != data) { - lrudata->reclaimTexture(); + QGLTexture *lrutexture = textureLRU(); + if (lrutexture && lrutexture != texture) { + if (lrutexture->boundPixmap) + lrutexture->boundPixmap->reclaimTexture(); + else + QGLTextureCache::instance()->remove(lrutexture->boundKey); succeeded = true; } - if (data && !wasInLRU) - removeFromLRU(data); + if (texture && !wasInLRU) + removeFromLRU(texture); return succeeded; } @@ -187,55 +180,58 @@ bool QGLTexturePool::reclaimSpace(GLint internalformat, void QGLTexturePool::hibernate() { Q_D(QGLTexturePool); - QGLPixmapData *pd = d->lruLast; - while (pd) { - QGLPixmapData *prevLRU = pd->prevLRU; - pd->inTexturePool = false; - pd->inLRU = false; - pd->nextLRU = 0; - pd->prevLRU = 0; - pd->hibernate(); - pd = prevLRU; + QGLTexture *texture = d->lruLast; + while (texture) { + QGLTexture *prevLRU = texture->prevLRU; + texture->inTexturePool = false; + texture->inLRU = false; + texture->nextLRU = 0; + texture->prevLRU = 0; + if (texture->boundPixmap) + texture->boundPixmap->hibernate(); + else + QGLTextureCache::instance()->remove(texture->boundKey); + texture = prevLRU; } d->lruFirst = 0; d->lruLast = 0; } -void QGLTexturePool::moveToHeadOfLRU(QGLPixmapData *data) +void QGLTexturePool::moveToHeadOfLRU(QGLTexture *texture) { Q_D(QGLTexturePool); - if (data->inLRU) { - if (!data->prevLRU) + if (texture->inLRU) { + if (!texture->prevLRU) return; // Already at the head of the list. - removeFromLRU(data); + removeFromLRU(texture); } - data->inLRU = true; - data->nextLRU = d->lruFirst; - data->prevLRU = 0; + texture->inLRU = true; + texture->nextLRU = d->lruFirst; + texture->prevLRU = 0; if (d->lruFirst) - d->lruFirst->prevLRU = data; + d->lruFirst->prevLRU = texture; else - d->lruLast = data; - d->lruFirst = data; + d->lruLast = texture; + d->lruFirst = texture; } -void QGLTexturePool::removeFromLRU(QGLPixmapData *data) +void QGLTexturePool::removeFromLRU(QGLTexture *texture) { Q_D(QGLTexturePool); - if (!data->inLRU) + if (!texture->inLRU) return; - if (data->nextLRU) - data->nextLRU->prevLRU = data->prevLRU; + if (texture->nextLRU) + texture->nextLRU->prevLRU = texture->prevLRU; else - d->lruLast = data->prevLRU; - if (data->prevLRU) - data->prevLRU->nextLRU = data->nextLRU; + d->lruLast = texture->prevLRU; + if (texture->prevLRU) + texture->prevLRU->nextLRU = texture->nextLRU; else - d->lruFirst = data->nextLRU; - data->inLRU = false; + d->lruFirst = texture->nextLRU; + texture->inLRU = false; } -QGLPixmapData *QGLTexturePool::pixmapLRU() +QGLTexture *QGLTexturePool::textureLRU() { Q_D(QGLTexturePool); return d->lruLast; diff --git a/src/opengl/qgltexturepool_p.h b/src/opengl/qgltexturepool_p.h index 27b730c..07f9700 100644 --- a/src/opengl/qgltexturepool_p.h +++ b/src/opengl/qgltexturepool_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -class QGLPixmapData; +class QGLTexture; class QGLTexturePoolPrivate; class QGLTexturePool @@ -70,18 +70,18 @@ public: static QGLTexturePool *instance(); // Create a new texture with the specified parameters and associate - // it with "data". The QGLPixmapData will be notified when the + // it with "texture". The QGLTexture will be notified when the // texture needs to be reclaimed by the pool. // // This function will call reclaimSpace() when texture creation fails. - GLuint createTextureForPixmap(GLenum target, + GLuint createTexture(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data); + QGLTexture *texture); // Create a permanent texture with the specified parameters. // If there is insufficient space for the texture, @@ -100,40 +100,37 @@ public: GLenum type, const GLvoid *data); - // Release a texture that is no longer required. - void releaseTexture(QGLPixmapData *data, GLuint texture); - - // Notify the pool that a QGLPixmapData object is using + // Notify the pool that a QGLTexture object is using // an texture again. This allows the pool to move the texture - // within a least-recently-used list of QGLPixmapData objects. - void useTexture(QGLPixmapData *data); + // within a least-recently-used list of QGLTexture objects. + void useTexture(QGLTexture *texture); // Notify the pool that the texture associated with a - // QGLPixmapData is being detached from the pool. The caller + // QGLTexture is being detached from the pool. The caller // will become responsible for calling glDeleteTextures(). - void detachTexture(QGLPixmapData *data); + void detachTexture(QGLTexture *texture); // Reclaim space for an image allocation with the specified parameters. // Returns true if space was reclaimed, or false if there is no - // further space that can be reclaimed. The "data" parameter - // indicates the pixmap that is trying to obtain space which should + // further space that can be reclaimed. The "texture" parameter + // indicates the texture that is trying to obtain space which should // not itself be reclaimed. bool reclaimSpace(GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data); + QGLTexture *data); - // Hibernate the image pool because the context is about to be + // Hibernate the texture pool because the context is about to be // destroyed. All textures left in the pool should be released. void hibernate(); protected: - // Helper functions for managing the LRU list of QGLPixmapData objects. - void moveToHeadOfLRU(QGLPixmapData *data); - void removeFromLRU(QGLPixmapData *data); - QGLPixmapData *pixmapLRU(); + // Helper functions for managing the LRU list of QGLTexture objects. + void moveToHeadOfLRU(QGLTexture *texture); + void removeFromLRU(QGLTexture *texture); + QGLTexture *textureLRU(); private: QScopedPointer<QGLTexturePoolPrivate> d_ptr; diff --git a/src/opengl/qgraphicssystem_gl.cpp b/src/opengl/qgraphicssystem_gl.cpp index 8530b52..265bf22 100644 --- a/src/opengl/qgraphicssystem_gl.cpp +++ b/src/opengl/qgraphicssystem_gl.cpp @@ -55,9 +55,6 @@ #if defined(Q_OS_SYMBIAN) #include <QtGui/private/qapplication_p.h> -#endif - -#ifdef QGL_USE_TEXTURE_POOL #include "private/qgltexturepool_p.h" #endif diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 909f264..bf1a303 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -70,12 +70,6 @@ class QGLFramebufferObject; class QGLFramebufferObjectFormat; class QGLPixmapData; -#ifdef QGL_USE_TEXTURE_POOL -void qt_gl_register_pixmap(QGLPixmapData *pd); -void qt_gl_unregister_pixmap(QGLPixmapData *pd); -void qt_gl_hibernate_pixmaps(); -#endif - #ifdef Q_OS_SYMBIAN class QNativeImageHandleProvider; #endif @@ -143,7 +137,7 @@ public: GLuint bind(bool copyBack = true) const; QGLTexture *texture() const; -#ifdef QGL_USE_TEXTURE_POOL +#ifdef Q_OS_SYMBIAN void destroyTexture(); // Detach this image from the image pool. void detachTextureFromPool(); @@ -158,9 +152,8 @@ public: // texture objects to reuse storage. void reclaimTexture(); void forceToImage(); -#endif -#ifdef Q_OS_SYMBIAN + QVolatileImage toVolatileImage() const { return m_source; } QImage::Format idealFormat(QImage &image, Qt::ImageConversionFlags flags); void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); @@ -218,23 +211,6 @@ private: mutable QGLPixmapGLPaintDevice m_glDevice; -#ifdef QGL_USE_TEXTURE_POOL - QGLPixmapData *nextLRU; - QGLPixmapData *prevLRU; - mutable bool inLRU; - mutable bool failedToAlloc; - mutable bool inTexturePool; - - QGLPixmapData *next; - QGLPixmapData *prev; - - friend class QGLTexturePool; - - friend void qt_gl_register_pixmap(QGLPixmapData *pd); - friend void qt_gl_unregister_pixmap(QGLPixmapData *pd); - friend void qt_gl_hibernate_pixmaps(); -#endif - friend class QGLPixmapGLPaintDevice; friend class QMeeGoPixmapData; friend class QMeeGoLivePixmapData; diff --git a/src/opengl/qpixmapdata_poolgl.cpp b/src/opengl/qpixmapdata_symbiangl.cpp index 5dd7b09..ab8a9e8 100644 --- a/src/opengl/qpixmapdata_poolgl.cpp +++ b/src/opengl/qpixmapdata_symbiangl.cpp @@ -248,43 +248,14 @@ QGLPixmapData::QGLPixmapData(PixelType type) , m_dirty(false) , m_hasFillColor(false) , m_hasAlpha(false) - , inLRU(false) - , failedToAlloc(false) - , inTexturePool(false) { setSerialNumber(++qt_gl_pixmap_serial); m_glDevice.setPixmapData(this); - - qt_gl_register_pixmap(this); } QGLPixmapData::~QGLPixmapData() { delete m_engine; - - destroyTexture(); - qt_gl_unregister_pixmap(this); -} - -void QGLPixmapData::destroyTexture() -{ - if (inTexturePool) { - QGLTexturePool *pool = QGLTexturePool::instance(); - if (m_texture.id) - pool->releaseTexture(this, m_texture.id); - } else { - if (m_texture.id) { - QGLWidget *shareWidget = qt_gl_share_widget(); - if (shareWidget) { - QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &m_texture.id); - } - } - } - m_texture.id = 0; - inTexturePool = false; - - releaseNativeImageHandle(); } QPixmapData *QGLPixmapData::createCompatiblePixmapData() const @@ -299,11 +270,13 @@ bool QGLPixmapData::isValid() const bool QGLPixmapData::isValidContext(const QGLContext *ctx) const { - if (ctx == m_ctx) - return true; - - const QGLContext *share_ctx = qt_gl_share_widget()->context(); - return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); + // On Symbian, we usually want to treat QGLPixmapData as + // raster pixmap data because that's well known and tested + // execution path which is used on other platforms as well. + // That's why if source pixels are valid we return false + // to simulate raster pixmaps. Only QPixmaps created from + // SgImage will enable usage of QGLPixmapData. + return false; } void QGLPixmapData::resize(int width, int height) @@ -354,27 +327,25 @@ void QGLPixmapData::ensureCreated() const if (!m_source.isNull() && m_source.format() == QImage::Format_RGB16) type = GL_UNSIGNED_SHORT_5_6_5; - m_texture.options &= ~QGLContext::MemoryManagedBindOption; - if (!m_texture.id) { - m_texture.id = QGLTexturePool::instance()->createTextureForPixmap( + m_texture.id = QGLTexturePool::instance()->createTexture( target, 0, internal_format, w, h, external_format, type, - const_cast<QGLPixmapData*>(this)); + &m_texture); if (!m_texture.id) { - failedToAlloc = true; + m_texture.failedToAlloc = true; return; } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - inTexturePool = true; - } else if (inTexturePool) { + m_texture.inTexturePool = true; + } else if (m_texture.inTexturePool) { glBindTexture(target, m_texture.id); - QGLTexturePool::instance()->useTexture(const_cast<QGLPixmapData*>(this)); + QGLTexturePool::instance()->useTexture(&m_texture); } if (!m_source.isNull() && m_texture.id) { @@ -754,15 +725,8 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const bool QGLPixmapData::useFramebufferObjects() const { -#ifdef Q_OS_SYMBIAN - // We don't want to use FBOs on Symbian + // We don't use FBOs on Symbian for now return false; -#else - return QGLFramebufferObject::hasOpenGLFramebufferObjects() - && QGLFramebufferObject::hasOpenGLFramebufferBlit() - && qt_gl_preferGL2Engine() - && (w * h > 32*32); // avoid overhead of FBOs for small pixmaps -#endif } QPaintEngine* QGLPixmapData::paintEngine() const @@ -846,39 +810,8 @@ QGLTexture* QGLPixmapData::texture() const return &m_texture; } -void QGLPixmapData::detachTextureFromPool() -{ - if (inTexturePool) { - QGLTexturePool::instance()->detachTexture(this); - inTexturePool = false; - } -} - -void QGLPixmapData::hibernate() -{ - // If the image was imported (e.g, from an SgImage under Symbian), then - // skip the hibernation, there is no sense in copying it back to main - // memory because the data is most likely shared between several processes. - bool skipHibernate = (m_texture.id && m_source.isNull()); -#if defined(Q_OS_SYMBIAN) - // However we have to proceed normally if the image was retrieved via - // a handle provider. - skipHibernate &= !nativeImageHandleProvider; -#endif - if (skipHibernate) - return; - - forceToImage(); - destroyTexture(); -} - -void QGLPixmapData::reclaimTexture() -{ - if (!inTexturePool) - return; - forceToImage(); - destroyTexture(); -} +Q_GUI_EXPORT int qt_defaultDpiX(); +Q_GUI_EXPORT int qt_defaultDpiY(); int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const { @@ -926,6 +859,31 @@ void QGLPixmapData::forceToImage() m_dirty = true; } +void QGLPixmapData::destroyTexture() +{ + // Destroy SgImage texture +} + +void QGLPixmapData::detachTextureFromPool() +{ + QGLTexturePool::instance()->detachTexture(&m_texture); +} + +void QGLPixmapData::hibernate() +{ + destroyTexture(); +} + +void QGLPixmapData::reclaimTexture() +{ + if (!m_texture.inTexturePool) + return; + + forceToImage(); + + destroyTexture(); +} + QGLPaintDevice *QGLPixmapData::glDevice() const { return &m_glDevice; diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index ff55142..9ad7f6a 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -184,7 +184,7 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) class QGLGlobalShareWidget { public: - QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) { + QGLGlobalShareWidget() : refCount(0), widget(0), initializing(false) { created = true; } @@ -227,8 +227,7 @@ public: static bool cleanedUp; static bool created; - QGLPixmapData *firstPixmap; - int widgetRefCount; + int refCount; private: QGLWidget *widget; @@ -271,43 +270,6 @@ const QGLContext *qt_gl_share_context() return 0; } -#ifdef QGL_USE_TEXTURE_POOL -void qt_gl_register_pixmap(QGLPixmapData *pd) -{ - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - pd->next = shared->firstPixmap; - pd->prev = 0; - if (shared->firstPixmap) - shared->firstPixmap->prev = pd; - shared->firstPixmap = pd; -} - -void qt_gl_unregister_pixmap(QGLPixmapData *pd) -{ - if (pd->next) - pd->next->prev = pd->prev; - if (pd->prev) { - pd->prev->next = pd->next; - } else { - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - if (shared) - shared->firstPixmap = pd->next; - } -} - -void qt_gl_hibernate_pixmaps() -{ - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - - // Scan all QGLPixmapData objects in the system and hibernate them. - QGLPixmapData *pd = shared->firstPixmap; - while (pd != 0) { - pd->hibernate(); - pd = pd->next; - } -} -#endif - struct QGLWindowSurfacePrivate { QGLFramebufferObject *fbo; @@ -407,18 +369,10 @@ QGLWindowSurface::~QGLWindowSurface() if (QGLGlobalShareWidget::cleanedUp) return; - --(_qt_gl_share_widget()->widgetRefCount); - -#ifdef QGL_USE_TEXTURE_POOL - if (_qt_gl_share_widget()->widgetRefCount <= 0) { - // All of the widget window surfaces have been destroyed - // but we still have GL pixmaps active. Ask them to hibernate - // to free up GPU resources until a widget is shown again. - // This may eventually cause the EGLContext to be destroyed - // because nothing in the system needs a context, which will - // free up even more GPU resources. - qt_gl_hibernate_pixmaps(); + --(_qt_gl_share_widget()->refCount); +#ifdef Q_OS_SYMBIAN + if (_qt_gl_share_widget()->refCount <= 0) { // Destroy the context if necessary. if (!qt_gl_share_widget()->context()->isSharing()) qt_destroy_gl_share_widget(); @@ -474,7 +428,7 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) ctx->create(qt_gl_share_context()); if (widget != qt_gl_share_widget()) - ++(_qt_gl_share_widget()->widgetRefCount); + ++(_qt_gl_share_widget()->refCount); #ifndef QT_NO_EGL static bool checkedForNOKSwapRegion = false; @@ -508,6 +462,7 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) voidPtrPtr = &widgetPrivate->extraData()->glContext; d_ptr->contexts << ctxPtrPtr; + #ifndef Q_OS_SYMBIAN qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size(); #endif @@ -902,7 +857,7 @@ void QGLWindowSurface::updateGeometry() { #ifdef Q_OS_SYMBIAN // Symbian needs to recreate the context when native window size changes if (d_ptr->size != geometry().size()) { if (window() != qt_gl_share_widget()) - --(_qt_gl_share_widget()->widgetRefCount); + --(_qt_gl_share_widget()->refCount); delete wd->extraData()->glContext; wd->extraData()->glContext = 0; diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h index 901bad9..18846f3 100644 --- a/src/openvg/qpixmapdata_vg_p.h +++ b/src/openvg/qpixmapdata_vg_p.h @@ -138,6 +138,7 @@ public: QSize size() const { return QSize(w, h); } #if defined(Q_OS_SYMBIAN) + QVolatileImage toVolatileImage() const { return source; } void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); bool initFromNativeImageHandle(void *handle, const QString &type); diff --git a/src/qt3support/other/q3process_unix.cpp b/src/qt3support/other/q3process_unix.cpp index af024bc..426d10f 100644 --- a/src/qt3support/other/q3process_unix.cpp +++ b/src/qt3support/other/q3process_unix.cpp @@ -213,7 +213,7 @@ static void q3process_cleanup() Q3ProcessPrivate::procManager = 0; } -#ifdef Q_OS_QNX6 +#ifdef Q_OS_QNX #define BAILOUT qt_safe_close(tmpSocket);qt_safe_close(socketFD[1]);return -1; int qnx6SocketPairReplacement (int socketFD[2]) { int tmpSocket; @@ -270,7 +270,7 @@ Q3ProcessManager::Q3ProcessManager() : sn(0) // The SIGCHLD handler writes to a socket to tell the manager that // something happened. This is done to get the processing in sync with the // event reporting. -#ifndef Q_OS_QNX6 +#ifndef Q_OS_QNX if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { #else if ( qnx6SocketPairReplacement (sigchldFd) ) { @@ -670,14 +670,14 @@ bool Q3Process::start( QStringList *env ) int sStderr[2]; // open sockets for piping -#ifndef Q_OS_QNX6 +#ifndef Q_OS_QNX if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) { #else if ( (comms & Stdin) && qnx6SocketPairReplacement(sStdin) == -1 ) { #endif return false; } -#ifndef Q_OS_QNX6 +#ifndef Q_OS_QNX if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) { #else if ( (comms & Stderr) && qnx6SocketPairReplacement(sStderr) == -1 ) { @@ -688,7 +688,7 @@ bool Q3Process::start( QStringList *env ) } return false; } -#ifndef Q_OS_QNX6 +#ifndef Q_OS_QNX if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) { #else if ( (comms & Stdout) && qnx6SocketPairReplacement(sStdout) == -1 ) { @@ -782,11 +782,7 @@ bool Q3Process::start( QStringList *env ) ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows success if ( env == 0 ) { // inherit environment and start process -#ifndef Q_OS_QNX4 ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice -#else - ::execvp( arglist[0], (char const*const*)arglist ); // ### cast not nice -#endif } else { // start process with environment settins as specified in env // construct the environment for exec int numEntries = env->count(); @@ -843,11 +839,7 @@ bool Q3Process::start( QStringList *env ) } } } -#ifndef Q_OS_QNX4 ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice -#else - ::execve( arglist[0], (char const*const*)arglist,(char const*const*)envlist ); // ### casts not nice -#endif } if ( fd[1] ) { char buf = 0; diff --git a/tests/auto/qdatetime/qdatetime.pro b/tests/auto/qdatetime/qdatetime.pro index a3f3091..72ca333 100644 --- a/tests/auto/qdatetime/qdatetime.pro +++ b/tests/auto/qdatetime/qdatetime.pro @@ -10,4 +10,3 @@ win32-msvc|win32-msvc9x { QMAKE_CXXFLAGS_RELEASE -= -O1 } CONFIG += parallel_test -HEADERS = tst_qdatetime.loc diff --git a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp index d5d56fc..cd91008 100644 --- a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp +++ b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp @@ -63,6 +63,14 @@ private slots: void automaticReparenting(); void verifyActivate(); void invalidate(); + void moveAndResize_data(); + void moveAndResize(); + void moveAndResizeWidgetInWidget_data(); + void moveAndResizeWidgetInWidget(); + void changingMinimumSize_data(); + void changingMinimumSize(); + void invalidateAndMove_data(); + void invalidateAndMove(); void constructors(); void alternativeLayoutItems(); void ownership(); @@ -443,7 +451,7 @@ void tst_QGraphicsLayout::invalidate() QCoreApplication::sendPostedEvents(); QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1); QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0); - QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1); + QCOMPARE(c->eventCount(QEvent::GraphicsSceneResize), 1); QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0); QCOMPARE(a->functionCount[SetGeometry], 1); @@ -479,30 +487,18 @@ void tst_QGraphicsLayout::invalidate() QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0); QCoreApplication::sendPostedEvents(); - QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1); + QCOMPARE(a->eventCount(QEvent::GraphicsSceneResize), 1); QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0); - QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1); + QCOMPARE(c->eventCount(QEvent::GraphicsSceneResize), 1); QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0); QCOMPARE(a->functionCount[SetGeometry], 1); - /* well, ideally one call to setGeometry(), but it will currently - * get two calls to setGeometry(): - * 1. The first LayoutRequest will call activate() - that will call - * setGeometry() on the layout. This geometry will be based on - * the widget geometry which is not correct at this moment. - * (it is still 150 wide) - * 2. Next, we check if the widget is top level, and then we call - * parentWidget->resize(parentWidget->size()); - * This will be adjusted to be minimum 200 pixels wide. - * The new size will then be propagated down to the layout - * - */ - QCOMPARE(alay->functionCount[SetGeometry], 2); - - QCOMPARE(b->functionCount[SetGeometry], 2); - QCOMPARE(c->functionCount[SetGeometry], 2); - QCOMPARE(d->functionCount[SetGeometry], 2); + QCOMPARE(alay->functionCount[SetGeometry], 1); + + QCOMPARE(b->functionCount[SetGeometry], 1); + QCOMPARE(c->functionCount[SetGeometry], 1); + QCOMPARE(d->functionCount[SetGeometry], 1); // f actually got wider, need to rearrange its siblings QCOMPARE(blay->functionCount[SetGeometry], 1); QCOMPARE(clay->functionCount[SetGeometry], 1); @@ -555,7 +551,236 @@ void tst_QGraphicsLayout::invalidate() QGraphicsLayout::setInstantInvalidatePropagation(false); } +void tst_QGraphicsLayout::changingMinimumSize_data() +{ + QTest::addColumn<bool>("instantInvalidatePropagation"); + QTest::newRow("Without instantInvalidatePropagation") << false; + QTest::newRow("With instantInvalidatePropagation") << true; +} +void tst_QGraphicsLayout::changingMinimumSize() +{ + QFETCH(bool, instantInvalidatePropagation); + QGraphicsLayout::setInstantInvalidatePropagation(instantInvalidatePropagation); + QGraphicsWidget *widget = new QGraphicsWidget; + qApp->processEvents(); + widget->setMinimumSize(300,300); + qApp->processEvents(); + QCOMPARE(widget->size(), QSizeF(300,300)); + QGraphicsLayout::setInstantInvalidatePropagation(false); +} + +struct WidgetToTestResizeEvents : public QGraphicsWidget +{ + virtual void resizeEvent ( QGraphicsSceneResizeEvent * event ) + { + QGraphicsWidget::resizeEvent(event); + resizeEventCalled = true; + } + + bool resizeEventCalled; +}; + +void tst_QGraphicsLayout::moveAndResizeWidgetInWidget_data() +{ + QTest::addColumn<bool>("instantInvalidatePropagation"); + + QTest::newRow("Without instantInvalidatePropagation") << false; + QTest::newRow("With instantInvalidatePropagation") << true; +} +void tst_QGraphicsLayout::moveAndResizeWidgetInWidget() +{ + QFETCH(bool, instantInvalidatePropagation); + QGraphicsLayout::setInstantInvalidatePropagation(instantInvalidatePropagation); + QGraphicsScene scene; + + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(widget); + layout->setContentsMargins(0,0,0,0); + WidgetToTestResizeEvents *innerWidget = new WidgetToTestResizeEvents; + QGraphicsLinearLayout *innerLayout = new QGraphicsLinearLayout(innerWidget); + innerLayout->setContentsMargins(0,0,0,0); + QCOMPARE(widget->maximumSize(), QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); + layout->addItem(innerWidget); + widget->setMinimumSize(1,1); + widget->setPreferredSize(1000,1000); + widget->setMaximumSize(2000,2000); + widget->resize(widget->preferredSize()); + innerWidget->setMinimumSize(1,1); + qApp->processEvents(); + innerWidget->resizeEventCalled = false; + + QCOMPARE(widget->size(), QSizeF(1000, 1000)); + QCOMPARE(layout->geometry().size(), QSizeF(1000, 1000)); + QCOMPARE(innerWidget->size(), QSizeF(1000, 1000)); + + innerLayout->invalidate(); + widget->setMaximumHeight(500); + widget->setX(1); + qApp->processEvents(); + QCOMPARE(widget->size(), QSizeF(1000, 500)); + QCOMPARE(innerWidget->size(), QSizeF(1000, 500)); + QVERIFY(innerWidget->resizeEventCalled); +} +void tst_QGraphicsLayout::moveAndResize_data() +{ + QTest::addColumn<bool>("instantInvalidatePropagation"); + QTest::addColumn<bool>("insideLayout"); + QTest::addColumn<bool>("insideLayoutInLayout"); + QTest::addColumn<bool>("insideWidget"); + QTest::newRow("Without instantInvalidatePropagation") << false << false << false << false; + QTest::newRow("With instantInvalidatePropagation") << true << false << false << false; + QTest::newRow("Without instantInvalidatePropagation, inside widget with no layout") << false << false << false << true; + QTest::newRow("With instantInvalidatePropagation, inside widget with no layout") << true << false << false << true; + QTest::newRow("Without instantInvalidatePropagation, inside widget with layout") << false << true << false << true; + QTest::newRow("With instantInvalidatePropagation, inside widget with layout") << true << true << false << true; + QTest::newRow("Without instantInvalidatePropagation, inside widget with layout in layout") << false << true << true << true; + QTest::newRow("With instantInvalidatePropagation, inside widget with layout in layout") << true << true << true << true; + +} +void tst_QGraphicsLayout::moveAndResize() +{ + QFETCH(bool, instantInvalidatePropagation); + QFETCH(bool, insideLayout); + QFETCH(bool, insideLayoutInLayout); + QFETCH(bool, insideWidget); + QGraphicsLayout::setInstantInvalidatePropagation(instantInvalidatePropagation); + QGraphicsScene scene; + + WidgetToTestResizeEvents *widget = new WidgetToTestResizeEvents; + + /* Setup its parent if we want them */ + QGraphicsWidget *parent = NULL; + if (insideWidget) + parent = new QGraphicsWidget; + if (insideLayout) { + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(parent); + QGraphicsLinearLayout *innerLayout = NULL; + if (insideLayoutInLayout) { + innerLayout = new QGraphicsLinearLayout; + layout->addItem(innerLayout); + innerLayout->addItem(widget); + } else + layout->addItem(widget); + } else if (insideWidget) { + widget->setParentItem(parent); + } + + new QGraphicsLinearLayout(widget); + widget->setGeometry(0,0,100,100); + qApp->processEvents(); + widget->resizeEventCalled = false; + + /* Force it grow by changing the minimum size */ + widget->setMinimumSize(200,200); + qApp->processEvents(); + qApp->processEvents(); + qApp->processEvents(); + QCOMPARE(widget->size(), QSizeF(200,200)); + QVERIFY(widget->resizeEventCalled); + widget->resizeEventCalled = false; + + /* Call setPos followed by a resize. We should get a resize event */ + widget->setPos(10,10); + widget->resize(300,300); + qApp->processEvents(); + QVERIFY(widget->resizeEventCalled); + widget->resizeEventCalled = false; + + /* Check that just calling setGeometry gives us a resize event */ + widget->setGeometry(10,10, 400, 400); + qApp->processEvents(); + QVERIFY(widget->resizeEventCalled); + widget->resizeEventCalled = false; + + /* Now call setPos followed by increasing the size using setGeometry,*/ + widget->setPos(30,30); + widget->setGeometry(10,10, 500, 500); + qApp->processEvents(); + QVERIFY(widget->resizeEventCalled); + widget->resizeEventCalled = false; + + /* Now call setPos followed by increasing the minimum size, to force it to grow */ + widget->setMinimumSize(600,600); + widget->setPos(30,30); + qApp->processEvents(); + QCOMPARE(widget->size(), QSizeF(600,600)); + QVERIFY(widget->resizeEventCalled); + widget->resizeEventCalled = false; + + QGraphicsLayout::setInstantInvalidatePropagation(false); +} +void tst_QGraphicsLayout::invalidateAndMove_data() +{ + QTest::addColumn<bool>("instantInvalidatePropagation"); + QTest::newRow("Without instantInvalidatePropagation") << false; + QTest::newRow("With instantInvalidatePropagation") << true; + +} +void tst_QGraphicsLayout::invalidateAndMove() +{ + // Check that if we set the position of an item and invalidate its layout at the same + // time, the widget keeps its correct size + QFETCH(bool, instantInvalidatePropagation); + QGraphicsLayout::setInstantInvalidatePropagation(instantInvalidatePropagation); + QGraphicsScene scene; + + QGraphicsWidget *widget = new QGraphicsWidget; + new QGraphicsLinearLayout(widget); + + widget->setMinimumSize(1,1); + widget->setPreferredSize(34,34); + widget->setMaximumSize(100,100); + widget->resize(widget->preferredSize()); + + scene.addItem(widget); + + qApp->processEvents(); + + /* Invalidate and reactivate. The size should not have changed */ + widget->layout()->invalidate(); + widget->layout()->activate(); + + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + qApp->processEvents(); + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + + widget->layout()->invalidate(); + widget->setX(1); //Change just the position using setX + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + qApp->processEvents(); + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + + widget->layout()->invalidate(); + widget->setGeometry(1,1,34,34); //Change just the position using setGeometry + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + qApp->processEvents(); + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + + widget->layout()->invalidate(); + widget->setGeometry(1,1,60,60); //Change just the size using setGeometry + QCOMPARE(widget->geometry().size(), QSizeF(60,60)); + QCOMPARE(widget->layout()->geometry().size(), QSizeF(60,60)); + qApp->processEvents(); + QCOMPARE(widget->geometry().size(), QSizeF(60,60)); + QCOMPARE(widget->layout()->geometry().size(), QSizeF(60,60)); + + widget->layout()->invalidate(); + widget->setGeometry(0,0,34,34); //Change the size and position using setGeometry + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + qApp->processEvents(); + QCOMPARE(widget->geometry().size(), widget->preferredSize()); + QCOMPARE(widget->layout()->geometry().size(), widget->preferredSize()); + + QGraphicsLayout::setInstantInvalidatePropagation(false); +} class Layout : public QGraphicsLayout { public: diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp index 3dc5e73..feb2552 100644 --- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp @@ -893,8 +893,8 @@ void tst_QLocalSocket::removeServer() QLocalServer server, server2; QVERIFY(QLocalServer::removeServer("cleanuptest")); QVERIFY(server.listen("cleanuptest")); -#ifndef Q_OS_WIN - // on Windows, there can be several sockets listening on the same pipe +#if !defined(Q_OS_WIN) && !defined(Q_OS_QNX) + // on Windows and QNX, there can be several sockets listening on the same pipe // on Unix, there can only be one socket instance QVERIFY(! server2.listen("cleanuptest")); #endif diff --git a/tests/auto/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/qnetworkcookiejar/tst_qnetworkcookiejar.cpp index 1b4256b..d1c376a 100644 --- a/tests/auto/qnetworkcookiejar/tst_qnetworkcookiejar.cpp +++ b/tests/auto/qnetworkcookiejar/tst_qnetworkcookiejar.cpp @@ -52,6 +52,7 @@ private slots: void getterSetter(); void setCookiesFromUrl_data(); void setCookiesFromUrl(); + void setCookiesFromUrl_50CookiesLimitPerDomain(); void cookiesForUrl_data(); void cookiesForUrl(); void effectiveTLDs_data(); @@ -251,6 +252,46 @@ void tst_QNetworkCookieJar::setCookiesFromUrl() QVERIFY2(result.isEmpty(), QTest::toString(result)); } +static bool findCookieName(const QList<QNetworkCookie> &cookieList, const QString &name) +{ + foreach(QNetworkCookie cookie, cookieList) + if (cookie.name() == name) + return true; + return false; +} + +void tst_QNetworkCookieJar::setCookiesFromUrl_50CookiesLimitPerDomain() +{ + QNetworkCookie cookie; + cookie.setValue("value"); + MyCookieJar jar; + QUrl url("http://a.b.c.com"); + + for (int i = 0; i < 20; ++i) { + // Add a list of 3 domain-matched cookies on each iteration for a total of 60 cookies. + QList<QNetworkCookie> cookieList; + cookie.setName(QString("CookieNo%1").arg(i*3+1).toAscii()); + cookie.setDomain("a.b.c.com"); + cookieList += cookie; + cookie.setName(QString("CookieNo%1").arg(i*3+2).toAscii()); + cookie.setDomain(".b.c.com"); + cookieList += cookie; + cookie.setName(QString("CookieNo%1").arg(i*3+3).toAscii()); + cookie.setDomain(".c.com"); + cookieList += cookie; + jar.setCookiesFromUrl(cookieList, url); + + int expectedNumCookies = std::min((i+1)*3, 50); + QCOMPARE(jar.allCookies().size(), expectedNumCookies); + } + + // Verify that the oldest cookies were the ones overwritten. + QVERIFY(!findCookieName(jar.allCookies(), "CookieNo1")); + QVERIFY(!findCookieName(jar.allCookies(), "CookieNo10")); + QVERIFY(findCookieName(jar.allCookies(), "CookieNo11")); + QVERIFY(findCookieName(jar.allCookies(), "CookieNo60")); +} + void tst_QNetworkCookieJar::cookiesForUrl_data() { QTest::addColumn<QList<QNetworkCookie> >("allCookies"); diff --git a/tests/auto/qpluginloader/tst_qpluginloader.cpp b/tests/auto/qpluginloader/tst_qpluginloader.cpp index 76dbd48..d2d92a5 100644 --- a/tests/auto/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/qpluginloader/tst_qpluginloader.cpp @@ -219,7 +219,7 @@ void tst_QPluginLoader::errorString() QVERIFY(loader.errorString() != unknown); } -#if !defined Q_OS_WIN && !defined Q_OS_MAC && !defined Q_OS_HPUX && !defined Q_OS_SYMBIAN +#if !defined Q_OS_WIN && !defined Q_OS_MAC && !defined Q_OS_HPUX && !defined Q_OS_SYMBIAN && !defined Q_OS_QNX { QPluginLoader loader( sys_qualifiedLibraryName("almostplugin")); //a plugin with unresolved symbols loader.setLoadHints(QLibrary::ResolveAllSymbolsHint); diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 5550fe8..86773ad 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -71,6 +71,7 @@ #include <QtGui/qpaintengine.h> #include <private/qbackingstore_p.h> #include <qmenubar.h> +#include <qtableview.h> #include <QtGui/QGraphicsView> #include <QtGui/QGraphicsProxyWidget> @@ -406,6 +407,7 @@ private slots: void childAt(); #ifdef Q_WS_MAC void childAt_unifiedToolBar(); + void taskQTBUG_17333_ResizeInfiniteRecursion(); #ifdef QT_MAC_USE_COCOA void taskQTBUG_11373(); #endif // QT_MAC_USE_COCOA @@ -10572,6 +10574,18 @@ void tst_QWidget::childAt_unifiedToolBar() QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label)); } +void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion() +{ + QTableView tb; + const char *s = "border: 1px solid;"; + tb.setStyleSheet(s); + tb.show(); + + QTest::qWaitForWindowShown(&tb); + tb.setGeometry(QRect(100, 100, 0, 100)); + // No crash, it works. +} + #ifdef QT_MAC_USE_COCOA void tst_QWidget::taskQTBUG_11373() { diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index f398358..403e3b6 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -66,6 +66,7 @@ #endif QString pluginImportPath; +bool verbose = false; void collectReachableMetaObjects(const QMetaObject *meta, QSet<const QMetaObject *> *metas) { @@ -88,13 +89,15 @@ void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *met return; const QMetaObject *meta = object->metaObject(); - qDebug() << "Processing object" << meta->className(); + if (verbose) + qDebug() << "Processing object" << meta->className(); collectReachableMetaObjects(meta, metas); for (int index = 0; index < meta->propertyCount(); ++index) { QMetaProperty prop = meta->property(index); if (QDeclarativeMetaType::isQObject(prop.userType())) { - qDebug() << " Processing property" << prop.name(); + if (verbose) + qDebug() << " Processing property" << prop.name(); currentProperty = QString("%1::%2").arg(meta->className(), prop.name()); // if the property was not initialized during construction, @@ -187,9 +190,15 @@ QSet<const QMetaObject *> collectReachableMetaObjects(const QString &importCode, foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) { if (ty->isExtendedType()) continue; + if (!ty->isCreatable()) + continue; + if (ty->typeName() == "QDeclarativeComponent") + continue; QByteArray tyName = ty->qmlTypeName(); tyName = tyName.mid(tyName.lastIndexOf('/') + 1); + if (tyName.isEmpty()) + continue; QByteArray code = importCode.toUtf8(); code += tyName; @@ -202,7 +211,7 @@ QSet<const QMetaObject *> collectReachableMetaObjects(const QString &importCode, if (object) collectReachableMetaObjects(object, &metas); else - qDebug() << "Could not create" << tyName << ":" << c.errorString(); + qWarning() << "Could not create" << tyName << ":" << c.errorString(); } return metas; @@ -424,9 +433,9 @@ void sigSegvHandler(int) { void printUsage(const QString &appName) { qWarning() << qPrintable(QString( - "Usage: %1 [-notrelocatable] module.uri version [module/import/path]\n" - " %1 -path path/to/qmldir/directory [version]\n" - " %1 -builtins\n" + "Usage: %1 [-v] [-notrelocatable] module.uri version [module/import/path]\n" + " %1 [-v] -path path/to/qmldir/directory [version]\n" + " %1 [-v] -builtins\n" "Example: %1 Qt.labs.particles 4.7 /home/user/dev/qt-install/imports").arg( appName)); } @@ -436,13 +445,13 @@ int main(int argc, char *argv[]) #ifdef Q_OS_UNIX // qmldump may crash, but we don't want any crash handlers to pop up // therefore we intercept the segfault and just exit() ourselves - struct sigaction action; + struct sigaction sigAction; - sigemptyset(&action.sa_mask); - action.sa_handler = &sigSegvHandler; - action.sa_flags = 0; + sigemptyset(&sigAction.sa_mask); + sigAction.sa_handler = &sigSegvHandler; + sigAction.sa_flags = 0; - sigaction(SIGSEGV, &action, 0); + sigaction(SIGSEGV, &sigAction, 0); #endif #ifdef QT_SIMULATOR @@ -452,10 +461,7 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); const QStringList args = app.arguments(); const QString appName = QFileInfo(app.applicationFilePath()).baseName(); - if (!(args.size() >= 3 - || (args.size() == 2 - && (args.at(1) == QLatin1String("--builtins") - || args.at(1) == QLatin1String("-builtins"))))) { + if (args.size() < 2) { printUsage(appName); return EXIT_INVALIDARGUMENTS; } @@ -463,8 +469,9 @@ int main(int argc, char *argv[]) QString pluginImportUri; QString pluginImportVersion; bool relocatable = true; - bool pathImport = false; - if (args.size() >= 3) { + enum Action { Uri, Path, Builtins }; + Action action = Uri; + { QStringList positionalArgs; foreach (const QString &arg, args) { if (!arg.startsWith(QLatin1Char('-'))) { @@ -477,14 +484,19 @@ int main(int argc, char *argv[]) relocatable = false; } else if (arg == QLatin1String("--path") || arg == QLatin1String("-path")) { - pathImport = true; + action = Path; + } else if (arg == QLatin1String("--builtins") + || arg == QLatin1String("-builtins")) { + action = Builtins; + } else if (arg == QLatin1String("-v")) { + verbose = true; } else { qWarning() << "Invalid argument: " << arg; return EXIT_INVALIDARGUMENTS; } } - if (!pathImport) { + if (action == Uri) { if (positionalArgs.size() != 3 && positionalArgs.size() != 4) { qWarning() << "Incorrect number of positional arguments"; return EXIT_INVALIDARGUMENTS; @@ -493,7 +505,7 @@ int main(int argc, char *argv[]) pluginImportVersion = positionalArgs[2]; if (positionalArgs.size() >= 4) pluginImportPath = positionalArgs[3]; - } else { + } else if (action == Path) { if (positionalArgs.size() != 2 && positionalArgs.size() != 3) { qWarning() << "Incorrect number of positional arguments"; return EXIT_INVALIDARGUMENTS; @@ -501,6 +513,11 @@ int main(int argc, char *argv[]) pluginImportPath = QDir::fromNativeSeparators(positionalArgs[1]); if (positionalArgs.size() == 3) pluginImportVersion = positionalArgs[2]; + } else if (action == Builtins) { + if (positionalArgs.size() != 1) { + qWarning() << "Incorrect number of positional arguments"; + return EXIT_INVALIDARGUMENTS; + } } } @@ -516,11 +533,11 @@ int main(int argc, char *argv[]) // this will hold the meta objects we want to dump information of QSet<const QMetaObject *> metas; - if (pluginImportUri.isEmpty() && !pathImport) { + if (action == Builtins) { metas = defaultReachable; } else { // find all QMetaObjects reachable when the specified module is imported - if (!pathImport) { + if (action != Path) { importCode += QString("import %0 %1\n").arg(pluginImportUri, pluginImportVersion).toAscii(); } else { // pluginImportVersion can be empty @@ -567,7 +584,7 @@ int main(int argc, char *argv[]) QmlStreamWriter qml(&bytes); qml.writeStartDocument(); - qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 0); + qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 1); qml.write("\n" "// This file describes the plugin-supplied types contained in the library.\n" "// It is used for QML tooling purposes only.\n" |