diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2011-03-10 13:54:31 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2011-03-10 13:54:31 (GMT) |
commit | 65e0fe383bba7b75e3ff5f8dd1bf3bb61a8bc589 (patch) | |
tree | 1da1a91756e396e134173caeb4772f3f466033a4 /src/gui | |
parent | ea0e4d2fad3622d37502d257ea5ae5c354ae6c5a (diff) | |
parent | 306d16002220b99ad386fb1255034b94861a8c9f (diff) | |
download | Qt-65e0fe383bba7b75e3ff5f8dd1bf3bb61a8bc589.zip Qt-65e0fe383bba7b75e3ff5f8dd1bf3bb61a8bc589.tar.gz Qt-65e0fe383bba7b75e3ff5f8dd1bf3bb61a8bc589.tar.bz2 |
Merge branch 'master' of git://scm.dev.nokia.troll.no/qt/qt-water-team
* 'master' of git://scm.dev.nokia.troll.no/qt/qt-water-team: (482 commits)
Refroze QtCore ARMV5 DEF files
Fix unstable qdeclarativeflickable test.
Fix warning about uninitialised variable use
Fix possible bearer management Crash with Panic E32USER-CBase, 69
Updated ARMV5 DEF files
Refroze WINSCW DEF files for Symbian
Update TextEdit's visible selection when only the anchor changes.
Fix a typo in an EXPECT_FAIL dataset name.
Fixed memory leak in GL texture cache with QRuntimePixmapData.
Invalidate the EGL surface of QMeeGoLivePixmapData when switching to Raster
QNetworkCookie: fix quoted values
Fix for QTBUG-17746. Quotes is retained in cookie value
Removed obsolete documentation from QPixmap.
Unsuccessful unlocking of QNetworkConfigurationPrivate mutex
Fixed auto-test failures caused by a3a79fefe65ec12.
Fix a test naming issue.
Improve Q_GLOBAL_STATIC macors.
Designer: Set dirty correctly in case resource paths were changed.
Set correct initial value for TextEdit and TextInput canPaste property
PinchArea example produced incorrect scaling.
...
Diffstat (limited to 'src/gui')
78 files changed, 2878 insertions, 207 deletions
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp index 12e77b1..b36b21e 100644 --- a/src/gui/dialogs/qfileinfogatherer.cpp +++ b/src/gui/dialogs/qfileinfogatherer.cpp @@ -78,11 +78,11 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) #endif m_resolveSymlinks(false), m_iconProvider(&defaultProvider) { -#ifndef Q_OS_WIN +#ifdef Q_OS_WIN + m_resolveSymlinks = true; +#elif !defined(Q_OS_INTEGRITY) userId = getuid(); groupId = getgid(); -#else - m_resolveSymlinks = true; #endif #ifndef QT_NO_FILESYSTEMWATCHER watcher = new QFileSystemWatcher(this); diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index dd27aff..cb8eb6a 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -1458,7 +1458,6 @@ void QFileSystemModel::setIconProvider(QFileIconProvider *provider) { Q_D(QFileSystemModel); d->fileInfoGatherer.setIconProvider(provider); - QApplication::processEvents(); d->root.updateIcon(provider, QString()); } diff --git a/src/gui/embedded/embedded.pri b/src/gui/embedded/embedded.pri index eb13d8d..31f0bc6 100644 --- a/src/gui/embedded/embedded.pri +++ b/src/gui/embedded/embedded.pri @@ -120,6 +120,12 @@ embedded { LIBS += -lgf } + contains( gfx-drivers, integrityfb ) { + HEADERS += embedded/qscreenintegrityfb_qws.h + SOURCES += embedded/qscreenintegrityfb_qws.cpp + LIBS += -lfbdev + } + contains( gfx-drivers, qvfb ) { HEADERS += embedded/qscreenvfb_qws.h SOURCES += embedded/qscreenvfb_qws.cpp @@ -174,6 +180,11 @@ embedded { SOURCES += embedded/qkbdqnx_qws.cpp } + contains( kbd-drivers, integrity ) { + HEADERS += embedded/qkbdintegrity_qws.h + SOURCES += embedded/qkbdintegrity_qws.cpp + } + # # Mouse drivers # @@ -207,4 +218,9 @@ embedded { HEADERS += embedded/qmouseqnx_qws.h SOURCES += embedded/qmouseqnx_qws.cpp } + + contains( mouse-drivers, integrity ) { + HEADERS += embedded/qmouseintegrity_qws.h + SOURCES += embedded/qmouseintegrity_qws.cpp + } } diff --git a/src/gui/embedded/qkbddriverfactory_qws.cpp b/src/gui/embedded/qkbddriverfactory_qws.cpp index 661b073..45825e5 100644 --- a/src/gui/embedded/qkbddriverfactory_qws.cpp +++ b/src/gui/embedded/qkbddriverfactory_qws.cpp @@ -49,6 +49,7 @@ #include "qkbdum_qws.h" #include "qkbdvfb_qws.h" #include "qkbdqnx_qws.h" +#include "qkbdintegrity_qws.h" #include <stdlib.h> #include "private/qfactoryloader_p.h" #include "qkbddriverplugin_qws.h" @@ -106,6 +107,10 @@ QWSKeyboardHandler *QKbdDriverFactory::create(const QString& key, const QString& if (driver == QLatin1String("qnx") || driver.isEmpty()) return new QWSQnxKeyboardHandler(device); #endif +#if defined(Q_OS_INTEGRITY) + if (driver == QLatin1String("integrity") || driver.isEmpty()) + return new QWSIntKeyboardHandler(device); +#endif #ifndef QT_NO_QWS_KEYBOARD # ifndef QT_NO_QWS_KBD_TTY if (driver == QLatin1String("tty") || driver.isEmpty()) @@ -151,6 +156,9 @@ QStringList QKbdDriverFactory::keys() #if defined(Q_OS_QNX) && !defined(QT_NO_QWS_KBD_QNX) list << QLatin1String("QNX"); #endif +#if defined(Q_OS_INTEGRITY) && !defined(QT_NO_QWS_KBD_INTEGRITY) + list << QLatin1String("INTEGRITY"); +#endif #ifndef QT_NO_QWS_KBD_TTY list << QLatin1String("TTY"); #endif diff --git a/src/gui/embedded/qkbdintegrity_qws.cpp b/src/gui/embedded/qkbdintegrity_qws.cpp new file mode 100644 index 0000000..b2df422 --- /dev/null +++ b/src/gui/embedded/qkbdintegrity_qws.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_INTEGRITY) + +#include "qkbdintegrity_qws.h" +#include <qwindowsystem_qws.h> +#include <qapplication.h> +#include <qtimer.h> +#include <qthread.h> + +#include <INTEGRITY.h> + + +//=========================================================================== + +QT_BEGIN_NAMESPACE + +// +// INTEGRITY keyboard +// + +class QIntKeyboardListenThread; + +class QWSIntKbPrivate : public QObject +{ + Q_OBJECT + friend class QIntKeyboardListenThread; +public: + QWSIntKbPrivate(QWSKeyboardHandler *, const QString &device); + ~QWSIntKbPrivate(); + void dataReady(int amount) { emit kbdDataAvailable(amount); } + uint8_t scancodebuf[32 /* USB_SCANCODE_BUF_LEN */ ]; + uint8_t rxpost; + uint8_t rxack; + +Q_SIGNALS: + void kbdDataAvailable(int amount); + +private Q_SLOTS: + void readKeyboardData(int amount); + +private: + QWSKeyboardHandler *handler; + QIntKeyboardListenThread *kbdthread; +}; +class QIntKeyboardListenThread : public QThread +{ +protected: + QWSIntKbPrivate *imp; + bool loop; +public: + QIntKeyboardListenThread(QWSIntKbPrivate *im) : QThread(), imp(im) {}; + ~QIntKeyboardListenThread() {}; + void run(); + void stoploop() { loop = false; }; +}; + + +QWSIntKeyboardHandler::QWSIntKeyboardHandler(const QString &device) + : QWSKeyboardHandler(device) +{ + d = new QWSIntKbPrivate(this, device); +} + +QWSIntKeyboardHandler::~QWSIntKeyboardHandler() +{ + delete d; +} + +//void QWSIntKeyboardHandler::processKeyEvent(int keycode, bool isPress, +// bool autoRepeat) +//{ +// QWSKeyboardHandler::processKeyEvent(keycode, isPress, autoRepeat); +//} + +void QIntKeyboardListenThread::run(void) +{ + Error E; + Buffer b; + Connection kbdc; + bool waitforresource = true; + do { + E = RequestResource((Object*)&kbdc, + "USBKeyboardClient", "!systempassword"); + if (E == Success) { + loop = false; + } else { + E = RequestResource((Object*)&kbdc, + "KeyboardClient", "!systempassword"); + if (E == Success) { + waitforresource = false; + } + } + if (waitforresource) + ::sleep(1); + } while (loop && waitforresource); + if (!loop) + return; + b.BufferType = DataBuffer | LastBuffer; + b.Length = sizeof(imp->scancodebuf); + b.TheAddress = (Address)imp->scancodebuf; + do { + b.Transferred = 0; + b.TheAddress = (Address)imp->scancodebuf + imp->rxpost; + CheckSuccess(SynchronousReceive(kbdc, &b)); + imp->rxpost += b.Transferred; + if (imp->rxpost >= 32 /* USB_SCANCODE_BUF_LEN */) + imp->rxpost = 0; + if (imp->rxpost == (imp->rxack + b.Transferred) % 32 /* USB_SCANCODE_BUF_LEN */) { + imp->kbdDataAvailable(b.Transferred); + } + } while (loop); +} + +void QWSIntKbPrivate::readKeyboardData(int amount) +{ + uint16_t keycode; + do { + if (scancodebuf[rxack] == 0xe0) { + keycode = scancodebuf[rxack] << 8; + rxack++; + if (rxack >= 32 /* USB_SCANCODE_BUF_LEN */) + rxack = 0; + } else { + keycode = 0; + } + + handler->processKeycode(keycode + (scancodebuf[rxack] & 0x7f), + (scancodebuf[rxack] & 0x80) == 0, + scancodebuf[rxack] == 2); + rxack++; + if (rxack >= 32 /* USB_SCANCODE_BUF_LEN */) + rxack = 0; + } while (rxack != rxpost); +} + +QWSIntKbPrivate::QWSIntKbPrivate(QWSKeyboardHandler *h, const QString &device) : handler(h) +{ + connect(this, SIGNAL(kbdDataAvailable(int)), this, SLOT(readKeyboardData(int))); + this->handler = handler; + rxack = rxpost = 0; + kbdthread = new QIntKeyboardListenThread(this); + kbdthread->start(); +} + +QWSIntKbPrivate::~QWSIntKbPrivate() +{ + kbdthread->stoploop(); + kbdthread->wait(); + delete kbdthread; +} + + +QT_END_NAMESPACE + +#include "qkbdintegrity_qws.moc" + +#endif // QT_NO_QWS_KEYBOARD || QT_NO_QWS_KBD_TTY diff --git a/src/gui/embedded/qkbdintegrity_qws.h b/src/gui/embedded/qkbdintegrity_qws.h new file mode 100644 index 0000000..f9ae4e3 --- /dev/null +++ b/src/gui/embedded/qkbdintegrity_qws.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QKBDINTEGRITY_QWS_H +#define QKBDINTEGRITY_QWS_H + +#include <QtGui/qkbd_qws.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_QWS_KEYBOARD + +#ifndef QT_NO_QWS_KBD_INTEGRITY + +class QSocketNotifier; +class QWSIntKbPrivate; + +class QWSIntKeyboardHandler : public QWSKeyboardHandler +{ +public: + explicit QWSIntKeyboardHandler(const QString&); + virtual ~QWSIntKeyboardHandler(); + +//protected: +// virtual void processKeyEvent(int keycode, bool isPress, bool autoRepeat); + +private: + QWSIntKbPrivate *d; +}; + +#endif // QT_NO_QWS_KBD_INTEGRITY + +#endif // QT_NO_QWS_KEYBOARD + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QKBDINTEGRITY_QWS_H diff --git a/src/gui/embedded/qmousedriverfactory_qws.cpp b/src/gui/embedded/qmousedriverfactory_qws.cpp index 81e6552..f67284d 100644 --- a/src/gui/embedded/qmousedriverfactory_qws.cpp +++ b/src/gui/embedded/qmousedriverfactory_qws.cpp @@ -48,6 +48,7 @@ #include "qmousevfb_qws.h" #include "qmousetslib_qws.h" #include "qmouseqnx_qws.h" +#include "qmouseintegrity_qws.h" #include <stdlib.h> #include "private/qfactoryloader_p.h" #include "qmousedriverplugin_qws.h" @@ -107,6 +108,10 @@ QWSMouseHandler *QMouseDriverFactory::create(const QString& key, const QString & if (driver == QLatin1String("qnx") || driver.isEmpty()) return new QQnxMouseHandler(key, device); #endif +#if defined(Q_OS_INTEGRITY) && !defined(QT_NO_MOUSE_INTEGRITY) + if (driver == QLatin1String("integrity") || driver.isEmpty()) + return new QIntMouseHandler(key, device); +#endif #ifndef QT_NO_QWS_MOUSE_LINUXTP if (driver == QLatin1String("linuxtp") || driver.isEmpty()) return new QWSLinuxTPMouseHandler(key, device); @@ -157,6 +162,9 @@ QStringList QMouseDriverFactory::keys() #if defined(Q_OS_QNX) && !defined(QT_NO_QWS_MOUSE_QNX) list << QLatin1String("QNX"); #endif +#if defined(Q_OS_INTEGRITY) && !defined(QT_NO_QWS_MOUSE_INTEGRITY) + list << QLatin1String("INTEGRITY"); +#endif #ifndef QT_NO_QWS_MOUSE_LINUXTP list << QLatin1String("LinuxTP"); #endif diff --git a/src/gui/embedded/qmouseintegrity_qws.cpp b/src/gui/embedded/qmouseintegrity_qws.cpp new file mode 100644 index 0000000..78a8c1b --- /dev/null +++ b/src/gui/embedded/qmouseintegrity_qws.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT_NO_QWS_MOUSE_INTEGRITY + +#include "qmouseintegrity_qws.h" +#include <qwindowsystem_qws.h> +#include <qapplication.h> +#include <qtimer.h> +#include <qthread.h> + +#include <INTEGRITY.h> + + +typedef Address MOUSEHandler; +typedef struct MOUSEMessageStruct +{ + Value x; + Value y; + Value z; + Value buttons; +} MOUSEMessage; + +static Error MOUSE_Init(MOUSEHandler *handler, Boolean *isabsolute); +static Error MOUSE_SynchronousGetPosition(MOUSEHandler handler, MOUSEMessage *msg, + Boolean absolute); +static Error MOUSE_ShouldFilter(MOUSEHandler handler, Boolean *filter); + +QT_BEGIN_NAMESPACE + +class QIntMouseListenThread; + +class QIntMousePrivate : public QObject +{ + Q_OBJECT + friend class QIntMouseListenTaskThread; +Q_SIGNALS: + void mouseDataAvailable(int x, int y, int buttons); +public: + QIntMousePrivate(QIntMouseHandler *handler); + ~QIntMousePrivate(); + void dataReady(int x, int y, int buttons) { emit mouseDataAvailable(x, y, buttons); } + bool calibrated; + bool waitforread; + bool suspended; + QIntMouseListenThread *mousethread; + +private: + QIntMouseHandler *handler; +}; + +class QIntMouseListenThread : public QThread +{ +protected: + QIntMousePrivate *imp; + bool loop; +public: + QIntMouseListenThread(QIntMousePrivate *im) : QThread(), imp(im) {}; + ~QIntMouseListenThread() {}; + void run(); + void stoploop() { loop = false; }; +}; + + +QIntMouseHandler::QIntMouseHandler(const QString &driver, const QString &device) + : QObject(), QWSCalibratedMouseHandler(driver, device) +{ + QPoint test(1,1); + d = new QIntMousePrivate(this); + connect(d, SIGNAL(mouseDataAvailable(int, int, int)), this, SLOT(readMouseData(int, int, int))); + + d->calibrated = (test != transform(test)); + + d->mousethread->start(); +} + +QIntMouseHandler::~QIntMouseHandler() +{ + disconnect(d, SIGNAL(mouseDataAvailable(int, int, int)), this, SLOT(readMouseData(int, int, int))); + delete d; +} + +void QIntMouseHandler::resume() +{ + d->suspended = true; +} + +void QIntMouseHandler::suspend() +{ + d->suspended = false; +} + +void QIntMouseHandler::readMouseData(int x, int y, int buttons) +{ + d->waitforread = false; + if (d->suspended) + return; + if (d->calibrated) { + sendFiltered(QPoint(x, y), buttons); + } else { + QPoint pos; + pos = transform(QPoint(x, y)); + limitToScreen(pos); + mouseChanged(pos, buttons, 0); + } +} + +void QIntMouseHandler::clearCalibration() +{ + QWSCalibratedMouseHandler::clearCalibration(); +} + +void QIntMouseHandler::calibrate(const QWSPointerCalibrationData *data) +{ + QWSCalibratedMouseHandler::calibrate(data); +} + +void QIntMouseListenThread::run(void) +{ + MOUSEHandler handler; + MOUSEMessage msg; + Boolean filter; + Boolean isabsolute; + loop = true; + CheckSuccess(MOUSE_Init(&handler, &isabsolute)); + CheckSuccess(MOUSE_ShouldFilter(handler, &filter)); + if (!filter) + imp->calibrated = false; + imp->waitforread = false; + do { + MOUSE_SynchronousGetPosition(handler, &msg, isabsolute); + imp->dataReady(msg.x, msg.y, msg.buttons); + } while (loop); + QThread::exit(0); +} + +QIntMousePrivate::QIntMousePrivate(QIntMouseHandler *handler) + : QObject() +{ + this->handler = handler; + suspended = false; + mousethread = new QIntMouseListenThread(this); +} + +QIntMousePrivate::~QIntMousePrivate() +{ + mousethread->stoploop(); + mousethread->wait(); + delete mousethread; +} + +QT_END_NAMESPACE + +#include "qmouseintegrity_qws.moc" + +typedef struct USBMouseStruct +{ + Connection mouseconn; + Buffer mousemsg[2]; + Value x; + Value y; +} USBMouse; + +USBMouse mousedev; + +Error MOUSE_Init(MOUSEHandler *handler, Boolean *isabsolute) +{ + Error E; + bool loop = true; + memset((void*)&mousedev, 0, sizeof(USBMouse)); + mousedev.mousemsg[0].BufferType = DataImmediate; + mousedev.mousemsg[1].BufferType = DataImmediate | LastBuffer; + do { + E = RequestResource((Object*)&mousedev.mouseconn, + "MouseClient", "!systempassword"); + if (E == Success) { + *isabsolute = true; + loop = false; + } else { + E = RequestResource((Object*)&mousedev.mouseconn, + "USBMouseClient", "!systempassword"); + if (E == Success) { + *isabsolute = false; + loop = false; + } + } + if (loop) + sleep(1); + } while (loop); + *handler = (MOUSEHandler)&mousedev; + return Success; +} + +Error MOUSE_SynchronousGetPosition(MOUSEHandler handler, MOUSEMessage *msg, + Boolean isabsolute) +{ + signed long x; + signed long y; + USBMouse *mdev = (USBMouse *)handler; + mdev->mousemsg[0].Transferred = 0; + mdev->mousemsg[1].Transferred = 0; + SynchronousReceive(mdev->mouseconn, mdev->mousemsg); + if (isabsolute) { + x = (signed long)mdev->mousemsg[0].Length; + y = (signed long)mdev->mousemsg[1].TheAddress; + } else { + x = mdev->x + (signed long)mdev->mousemsg[0].Length; + y = mdev->y + (signed long)mdev->mousemsg[1].TheAddress; + } + if (x < 0) + mdev->x = 0; + else + mdev->x = x; + if (y < 0) + mdev->y = 0; + else + mdev->y = y; + msg->x = mdev->x; + msg->y = mdev->y; + msg->buttons = mdev->mousemsg[0].TheAddress; + return Success; +} + +Error MOUSE_ShouldFilter(MOUSEHandler handler, Boolean *filter) +{ + if (filter == NULL) + return Failure; + *filter = false; + return Success; +} + +#endif // QT_NO_QWS_MOUSE_INTEGRITY + diff --git a/src/gui/embedded/qmouseintegrity_qws.h b/src/gui/embedded/qmouseintegrity_qws.h new file mode 100644 index 0000000..46d27a3 --- /dev/null +++ b/src/gui/embedded/qmouseintegrity_qws.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMOUSEINTEGRITY_QWS_H +#define QMOUSEINTEGRITY_QWS_H + +#include <QtGui/qmouse_qws.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_QWS_MOUSE_INTEGRITY + +class QSocketNotifier; +class QIntMousePrivate; + +class QIntMouseHandler : public QObject, public QWSCalibratedMouseHandler { + Q_OBJECT +public: + QIntMouseHandler(const QString &driver = QString(), + const QString &device = QString()); + ~QIntMouseHandler(); + + void resume(); + void suspend(); + + void calibrate(const QWSPointerCalibrationData *data); + void clearCalibration(); + +private: + QIntMousePrivate *d; +private Q_SLOTS: + void readMouseData(int x, int y, int buttons); +}; +#endif // QT_NO_QWS_MOUSE_INTEGRITY + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMOUSEINTEGRITY_QWS_H diff --git a/src/gui/embedded/qscreen_qws.h b/src/gui/embedded/qscreen_qws.h index d237dd8..17ffbbb 100644 --- a/src/gui/embedded/qscreen_qws.h +++ b/src/gui/embedded/qscreen_qws.h @@ -193,7 +193,7 @@ class Q_GUI_EXPORT QScreen { public: enum ClassId { LinuxFBClass, TransformedClass, VNCClass, MultiClass, VFbClass, DirectFBClass, SvgalibClass, ProxyClass, - GLClass, CustomClass = 1024 }; + GLClass, IntfbClass, CustomClass = 1024 }; QScreen(int display_id, ClassId classId); explicit QScreen(int display_id); @@ -358,6 +358,7 @@ private: friend class QLinuxFbScreen; friend class QVFbScreen; friend class QProxyScreen; + friend class QIntfbScreen; #endif friend void qt_solidFill_setup(QScreen*, const QColor&, const QRegion&); friend void qt_blit_setup(QScreen *screen, const QImage &image, diff --git a/src/gui/embedded/qscreendriverfactory_qws.cpp b/src/gui/embedded/qscreendriverfactory_qws.cpp index c0ae214..ea194e5 100644 --- a/src/gui/embedded/qscreendriverfactory_qws.cpp +++ b/src/gui/embedded/qscreendriverfactory_qws.cpp @@ -48,6 +48,7 @@ #include "qscreenvfb_qws.h" #include "qscreenmulti_qws_p.h" #include "qscreenqnx_qws.h" +#include "qscreenintegrityfb_qws.h" #include <stdlib.h> #include "private/qfactoryloader_p.h" #include "qscreendriverplugin_qws.h" @@ -112,6 +113,10 @@ QScreen *QScreenDriverFactory::create(const QString& key, int displayId) if (driver == QLatin1String("qnx") || driver.isEmpty()) return new QQnxScreen(displayId); #endif +#if defined(Q_OS_INTEGRITY) && !defined(QT_NO_QWS_INTEGRITY) + if (driver == QLatin1String("integrityfb") || driver.isEmpty()) + return new QIntfbScreen(displayId); +#endif #ifndef QT_NO_QWS_QVFB if (driver == QLatin1String("qvfb") || driver.isEmpty()) return new QVFbScreen(displayId); @@ -159,6 +164,9 @@ QStringList QScreenDriverFactory::keys() #if defined(Q_OS_QNX) && !defined(QT_NO_QWS_QNX) list << QLatin1String("QNX"); #endif +#if defined(Q_OS_INTEGRITY) && !defined(QT_NO_QWS_INTEGRITY) + list << QLatin1String("INTEGRITYFB"); +#endif #ifndef QT_NO_QWS_QVFB list << QLatin1String("QVFb"); #endif diff --git a/src/gui/embedded/qscreenintegrityfb_qws.cpp b/src/gui/embedded/qscreenintegrityfb_qws.cpp new file mode 100644 index 0000000..7b24490 --- /dev/null +++ b/src/gui/embedded/qscreenintegrityfb_qws.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT_NO_QWS_INTEGRITYFB + +#include <qscreenintegrityfb_qws.h> +#include <qwindowsystem_qws.h> +#include <qsocketnotifier.h> +#include <qapplication.h> +#include <qscreen_qws.h> +#include "qmouseintegrity_qws.h" +#include "qkbdintegrity_qws.h" +#include <qmousedriverfactory_qws.h> +#include <qkbddriverfactory_qws.h> +#include <qdebug.h> + +#include <INTEGRITY.h> +#include <device/fbdriver.h> + +QT_BEGIN_NAMESPACE + +class QIntfbScreenPrivate +{ +public: + QIntfbScreenPrivate(); + ~QIntfbScreenPrivate(); + + FBHandle handle; + struct FBInfoStruct fbinfo; + + QWSMouseHandler *mouse; +#ifndef QT_NO_QWS_KEYBOARD + QWSKeyboardHandler *keyboard; +#endif +}; + +QIntfbScreenPrivate::QIntfbScreenPrivate() + : mouse(0) + +{ +#ifndef QT_NO_QWS_KEYBOARD + keyboard = 0; +#endif +} + +QIntfbScreenPrivate::~QIntfbScreenPrivate() +{ + delete mouse; +#ifndef QT_NO_QWS_KEYBOARD + delete keyboard; +#endif +} + +/*! + \internal + + \class QIntfbScreen + \ingroup qws + + \brief The QIntfbScreen class implements a screen driver for the + INTEGRITY framebuffer drivers. + + Note that this class is only available in \l{Qt for INTEGRITY}. + Custom screen drivers can be added by subclassing the + QScreenDriverPlugin class, using the QScreenDriverFactory class to + dynamically load the driver into the application, but there should + only be one screen object per application. + + \sa QScreen, QScreenDriverPlugin, {Running Applications} +*/ + +/*! + \fn bool QIntfbScreen::connect(const QString & displaySpec) + \reimp +*/ + +/*! + \fn void QIntfbScreen::disconnect() + \reimp +*/ + +/*! + \fn bool QIntfbScreen::initDevice() + \reimp +*/ + +/*! + \fn void QIntfbScreen::restore() + \reimp +*/ + +/*! + \fn void QIntfbScreen::save() + \reimp +*/ + +/*! + \fn void QIntfbScreen::setDirty(const QRect & r) + \reimp +*/ + +/*! + \fn void QIntfbScreen::setMode(int nw, int nh, int nd) + \reimp +*/ + +/*! + \fn void QIntfbScreen::shutdownDevice() + \reimp +*/ + +/*! + \fn QIntfbScreen::QIntfbScreen(int displayId) + + Constructs a QVNCScreen object. The \a displayId argument + identifies the Qt for Embedded Linux server to connect to. +*/ +QIntfbScreen::QIntfbScreen(int display_id) + : QScreen(display_id, IntfbClass), d_ptr(new QIntfbScreenPrivate) +{ + d_ptr->handle = 0; + data = 0; +} + +/*! + Destroys this QIntfbScreen object. +*/ +QIntfbScreen::~QIntfbScreen() +{ + delete d_ptr; +} + +static QIntfbScreen *connected = 0; + +bool QIntfbScreen::connect(const QString &displaySpec) +{ + FBDriver *fbdev; + + CheckSuccess(gh_FB_get_driver(0, &fbdev)); + CheckSuccess(gh_FB_init_device(fbdev, 0, &d_ptr->handle)); + CheckSuccess(gh_FB_get_info(d_ptr->handle, &d_ptr->fbinfo)); + + data = (uchar *)d_ptr->fbinfo.start; + + d = d_ptr->fbinfo.bitsperpixel; + switch (d) { + case 1: + setPixelFormat(QImage::Format_Mono); + break; + case 8: + setPixelFormat(QImage::Format_Indexed8); + break; + case 12: + setPixelFormat(QImage::Format_RGB444); + break; + case 15: + setPixelFormat(QImage::Format_RGB555); + break; + case 16: + setPixelFormat(QImage::Format_RGB16); + break; + case 18: + setPixelFormat(QImage::Format_RGB666); + break; + case 24: + setPixelFormat(QImage::Format_RGB888); +#ifdef QT_QWS_DEPTH_GENERIC +#if Q_BYTE_ORDER != Q_BIG_ENDIAN + qt_set_generic_blit(this, 24, + d_ptr->fbinfo.redbits, + d_ptr->fbinfo.greenbits, + d_ptr->fbinfo.bluebits, + d_ptr->fbinfo.alphabits, + d_ptr->fbinfo.redoffset, + d_ptr->fbinfo.greenoffset, + d_ptr->fbinfo.blueoffset, + d_ptr->fbinfo.alphaoffset); +#else + qt_set_generic_blit(this, 24, + d_ptr->fbinfo.redbits, + d_ptr->fbinfo.greenbits, + d_ptr->fbinfo.bluebits, + d_ptr->fbinfo.alphabits, + 16 - d_ptr->fbinfo.redoffset, + 16 - d_ptr->fbinfo.greenoffset, + 16 - d_ptr->fbinfo.blueoffset, + d_ptr->fbinfo.alphaoffset); +#endif +#endif + break; + case 32: + setPixelFormat(QImage::Format_ARGB32_Premultiplied); +#ifdef QT_QWS_DEPTH_GENERIC +#if Q_BYTE_ORDER != Q_BIG_ENDIAN + qt_set_generic_blit(this, 32, + d_ptr->fbinfo.redbits, + d_ptr->fbinfo.greenbits, + d_ptr->fbinfo.bluebits, + d_ptr->fbinfo.alphabits, + d_ptr->fbinfo.redoffset, + d_ptr->fbinfo.greenoffset, + d_ptr->fbinfo.blueoffset, + d_ptr->fbinfo.alphaoffset); +#else + qt_set_generic_blit(this, 32, + d_ptr->fbinfo.redbits, + d_ptr->fbinfo.greenbits, + d_ptr->fbinfo.bluebits, + d_ptr->fbinfo.alphabits, + 24 - d_ptr->fbinfo.redoffset, + 24 - d_ptr->fbinfo.greenoffset, + 24 - d_ptr->fbinfo.blueoffset, + d_ptr->fbinfo.alphaoffset ? 24 - d_ptr->fbinfo.alphaoffset : 0); +#endif +#endif + break; + } + + dw = w = d_ptr->fbinfo.width; + dh = h = d_ptr->fbinfo.height; + + /* assumes no padding */ + lstep = w * ((d + 7) >> 3); + + mapsize = size = h * lstep; + + /* default values */ + int dpi = 72; + physWidth = qRound(dw * 25.4 / dpi); + physHeight = qRound(dh * 25.4 / dpi); + + qDebug("Connected to INTEGRITYfb server: %d x %d x %d %dx%dmm (%dx%ddpi)", + w, h, d, physWidth, physHeight, qRound(dw*25.4/physWidth), qRound(dh*25.4/physHeight) ); + + + QWSServer::setDefaultMouse("integrity"); + QWSServer::setDefaultKeyboard("integrity"); + + connected = this; + + return true; +} + +void QIntfbScreen::disconnect() +{ + connected = 0; +} + +bool QIntfbScreen::initDevice() +{ + + CheckSuccess(gh_FB_set_info(d_ptr->handle, &d_ptr->fbinfo, false)); + CheckSuccess(gh_FB_get_info(d_ptr->handle, &d_ptr->fbinfo)); + data = (uchar *)d_ptr->fbinfo.start; + d = d_ptr->fbinfo.bitsperpixel; + dw = w = d_ptr->fbinfo.width; + dh = h = d_ptr->fbinfo.height; + mapsize = d_ptr->fbinfo.length; + /* assumes no padding */ + lstep = w * ((d + 7) >> 3); + + mapsize = size = h * lstep; + + data = (uchar *)d_ptr->fbinfo.start; + + d = d_ptr->fbinfo.bitsperpixel; + switch (d) { + case 1: + setPixelFormat(QImage::Format_Mono); + break; + case 8: + setPixelFormat(QImage::Format_Indexed8); + break; + case 12: + setPixelFormat(QImage::Format_RGB444); + break; + case 15: + setPixelFormat(QImage::Format_RGB555); + break; + case 16: + setPixelFormat(QImage::Format_RGB16); + break; + case 18: + setPixelFormat(QImage::Format_RGB666); + break; + case 24: + setPixelFormat(QImage::Format_RGB888); + break; + case 32: + setPixelFormat(QImage::Format_ARGB32_Premultiplied); + break; + } +#ifdef QT_QWS_DEPTH_GENERIC +#if defined(__BIG_ENDIAN__) + qt_set_generic_blit(this, d, + d_ptr->fbinfo.redbits, + d_ptr->fbinfo.greenbits, + d_ptr->fbinfo.bluebits, + d_ptr->fbinfo.alphabits, + 24 - d_ptr->fbinfo.redoffset, + 24 - d_ptr->fbinfo.greenoffset, + 24 - d_ptr->fbinfo.blueoffset, + d_ptr->fbinfo.alphaoffset ? 24 - d_ptr->fbinfo.alphaoffset : 0); +#else + qt_set_generic_blit(this, d, + d_ptr->fbinfo.redbits, + d_ptr->fbinfo.greenbits, + d_ptr->fbinfo.bluebits, + d_ptr->fbinfo.alphabits, + d_ptr->fbinfo.redoffset, + d_ptr->fbinfo.greenoffset, + d_ptr->fbinfo.blueoffset, + d_ptr->fbinfo.alphaoffset); +#endif +#endif + +#ifndef QT_NO_QWS_CURSOR + QScreenCursor::initSoftwareCursor(); +#endif + return true; +} + +void QIntfbScreen::shutdownDevice() +{ + gh_FB_close(d_ptr->handle); +} + +void QIntfbScreen::setMode(int ,int ,int) +{ +} + +// save the state of the graphics card +// This is needed so that e.g. we can restore the palette when switching +// between linux virtual consoles. +void QIntfbScreen::save() +{ + // nothing to do. +} + +// restore the state of the graphics card. +void QIntfbScreen::restore() +{ +} +void QIntfbScreen::setDirty(const QRect& rect) +{ + FBRect fbrect; + fbrect.dx = rect.x(); + fbrect.dy = rect.y(); + fbrect.width = rect.width(); + fbrect.height = rect.height(); + gh_FB_expose(d_ptr->handle, &fbrect); +} + +void QIntfbScreen::setBrightness(int b) +{ + if (connected) { + } +} + +void QIntfbScreen::blank(bool on) +{ +} + +#endif // QT_NO_QWS_INTEGRITYFB + +QT_END_NAMESPACE + diff --git a/src/gui/embedded/qscreenintegrityfb_qws.h b/src/gui/embedded/qscreenintegrityfb_qws.h new file mode 100644 index 0000000..06b3967 --- /dev/null +++ b/src/gui/embedded/qscreenintegrityfb_qws.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCREENINTEGRITYFB_QWS_H +#define QSCREENINTEGRITYFB_QWS_H + +#include <QtGui/qscreen_qws.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_QWS_INTEGRITYFB + +class QIntfbScreenPrivate; + +class Q_GUI_EXPORT QIntfbScreen : public QScreen +{ +public: + explicit QIntfbScreen(int display_id); + virtual ~QIntfbScreen(); + virtual bool initDevice(); + virtual bool connect(const QString &displaySpec); + virtual void disconnect(); + virtual void shutdownDevice(); + virtual void save(); + virtual void restore(); + virtual void setMode(int nw,int nh,int nd); + virtual void setDirty(const QRect& r); + virtual void blank(bool); + static void setBrightness(int b); + +private: + QIntfbScreenPrivate *d_ptr; +}; + +#endif // QT_NO_QWS_INTEGRITYFB + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSCREENINTEGRITYFB_QWS_H diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 92ea397..a5e37f3 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -29,7 +29,9 @@ HEADERS += \ image/qpixmapdata_p.h \ image/qpixmapdatafactory_p.h \ image/qpixmapfilter_p.h \ - image/qimagepixmapcleanuphooks_p.h + image/qimagepixmapcleanuphooks_p.h \ + image/qvolatileimage_p.h \ + image/qvolatileimagedata_p.h SOURCES += \ image/qbitmap.cpp \ @@ -53,7 +55,8 @@ SOURCES += \ image/qpixmap_raster.cpp \ image/qpixmap_blitter.cpp \ image/qnativeimage.cpp \ - image/qimagepixmapcleanuphooks.cpp + image/qimagepixmapcleanuphooks.cpp \ + image/qvolatileimage.cpp win32 { SOURCES += image/qpixmap_win.cpp @@ -77,6 +80,13 @@ else:symbian { SOURCES += image/qpixmap_s60.cpp } +!symbian|contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2) { + SOURCES += image/qvolatileimagedata.cpp +} +else { + SOURCES += image/qvolatileimagedata_symbian.cpp +} + # Built-in image format support HEADERS += \ image/qbmphandler_p.h \ diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index f896572..6e13324 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -112,8 +112,16 @@ void QPixmap::init(int w, int h, Type type) init(w, h, int(type)); } +extern QApplication::Type qt_appType; + void QPixmap::init(int w, int h, int type) { + if (qt_appType == QApplication::Tty) { + qWarning("QPixmap: Cannot create a QPixmap when no GUI is being used"); + data = 0; + return; + } + if ((w > 0 && h > 0) || type == QPixmapData::BitmapType) data = QPixmapData::create(w, h, (QPixmapData::PixelType) type); else @@ -1636,16 +1644,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) {Implicit Data Sharing} documentation. QPixmap objects can also be streamed. - Depending on the system, QPixmap is stored using a RGB32 or a - premultiplied alpha format. If the image has an alpha channel, and - if the system allows, the preferred format is premultiplied alpha. - Note also that QPixmap, unlike QImage, may be hardware dependent. - On X11, Mac and Symbian, a QPixmap is stored on the server side while - a QImage is stored on the client side (on Windows, these two classes - have an equivalent internal representation, i.e. both QImage and - QPixmap are stored on the client side and don't use any GDI - resources). - Note that the pixel data in a pixmap is internal and is managed by the underlying window system. Because QPixmap is a QPaintDevice subclass, QPainter can be used to draw directly onto pixmaps. @@ -2012,7 +2010,7 @@ void QPixmap::detach() } if (data->is_cached && data->ref == 1) - QImagePixmapCleanupHooks::executePixmapDataModificationHooks(pd); + QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data()); #if defined(Q_WS_MAC) QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(pd) : 0; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 1e7ff04..a5f42c1 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -386,6 +386,9 @@ int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const void QRasterPixmapData::createPixmapForImage(QImage &sourceImage, Qt::ImageConversionFlags flags, bool inPlace) { QImage::Format format; + if (flags & Qt::NoFormatConversion) + format = sourceImage.format(); + else #ifdef Q_WS_QWS if (pixelType() == BitmapType) { format = QImage::Format_Mono; diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 5c05c28..db5ff4a 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -71,7 +71,8 @@ public: #if defined(Q_OS_SYMBIAN) enum NativeType { FbsBitmap, - SgImage + SgImage, + VolatileImage }; #endif enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass, diff --git a/src/gui/image/qvolatileimage.cpp b/src/gui/image/qvolatileimage.cpp new file mode 100644 index 0000000..098e9a1 --- /dev/null +++ b/src/gui/image/qvolatileimage.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvolatileimage_p.h" +#include "qvolatileimagedata_p.h" +#include <QtGui/private/qpaintengine_raster_p.h> +#include <QtGui/private/qpixmapdata_p.h> + +QT_BEGIN_NAMESPACE + +class QVolatileImagePaintEnginePrivate : public QRasterPaintEnginePrivate +{ +public: + QVolatileImagePaintEnginePrivate() { } + QVolatileImage *img; +}; + +class QVolatileImagePaintEngine : public QRasterPaintEngine +{ + Q_DECLARE_PRIVATE(QVolatileImagePaintEngine) + +public: + QVolatileImagePaintEngine(QPaintDevice *device, QVolatileImage *img); + bool begin(QPaintDevice *device); + bool end(); + void drawPixmap(const QPointF &p, const QPixmap &pm); + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); +}; + +QVolatileImage::QVolatileImage() + : d(new QVolatileImageData) +{ +} + +QVolatileImage::QVolatileImage(int w, int h, QImage::Format format) + : d(new QVolatileImageData(w, h, format)) +{ +} + +QVolatileImage::QVolatileImage(const QImage &sourceImage) + : d(new QVolatileImageData(sourceImage)) +{ +} + +QVolatileImage::QVolatileImage(void *nativeImage, void *nativeMask) + : d(new QVolatileImageData(nativeImage, nativeMask)) +{ +} + +// Need non-inline, non-autogenerated copy ctor, dtor, op= to keep the +// fwd declared QSharedData working. + +QVolatileImage::QVolatileImage(const QVolatileImage &other) + : d(other.d) +{ +} + +QVolatileImage::~QVolatileImage() +{ +} + +QVolatileImage &QVolatileImage::operator=(const QVolatileImage &rhs) +{ + d = rhs.d; + return *this; +} + +bool QVolatileImage::isNull() const +{ + return d->image.isNull(); +} + +QImage::Format QVolatileImage::format() const +{ + return d->image.format(); +} + +int QVolatileImage::width() const +{ + return d->image.width(); +} + +int QVolatileImage::height() const +{ + return d->image.height(); +} + +int QVolatileImage::bytesPerLine() const +{ + return d->image.bytesPerLine(); +} + +int QVolatileImage::byteCount() const +{ + return d->image.byteCount(); +} + +int QVolatileImage::depth() const +{ + return d->image.depth(); +} + +bool QVolatileImage::hasAlphaChannel() const +{ + return d->image.hasAlphaChannel(); +} + +void QVolatileImage::beginDataAccess() const +{ + d->beginDataAccess(); +} + +void QVolatileImage::endDataAccess(bool readOnly) const +{ + d->endDataAccess(readOnly); +} + +/*! + Access to pixel data via bits() or constBits() should be guarded by + begin/endDataAccess(). + */ +uchar *QVolatileImage::bits() +{ + return d->image.bits(); +} + +const uchar *QVolatileImage::constBits() const +{ + return d->image.constBits(); +} + +bool QVolatileImage::ensureFormat(QImage::Format format) +{ + return d->ensureFormat(format); +} + +/*! + This will always perform a copy of the pixel data. + */ +QImage QVolatileImage::toImage() const +{ + d->beginDataAccess(); + QImage newImage = d->image.copy(); // no sharing allowed + d->endDataAccess(true); + return newImage; +} + +/*! + Returns a reference to the image that is potentially using some native + buffer internally. Access to the image's pixel data should be guarded by + begin/endDataAccess(). Use it when there is a need for QImage APIs not provided + by this class. The returned QImage must never be shared or assigned to. + */ +QImage &QVolatileImage::imageRef() // non-const, in order to cause a detach +{ + d->ensureImage(); + return d->image; +} + +void *QVolatileImage::duplicateNativeImage() const +{ + return d->duplicateNativeImage(); +} + +void QVolatileImage::setAlphaChannel(const QPixmap &alphaChannel) +{ + ensureFormat(QImage::Format_ARGB32_Premultiplied); + beginDataAccess(); + imageRef().setAlphaChannel(alphaChannel.toImage()); + endDataAccess(); + d->ensureImage(); +} + +void QVolatileImage::fill(uint pixelValue) +{ + beginDataAccess(); + imageRef().fill(pixelValue); + endDataAccess(); + d->ensureImage(); +} + +void QVolatileImage::copyFrom(QVolatileImage *source, const QRect &rect) +{ + if (source->isNull()) { + return; + } + QRect r = rect; + if (rect.isNull()) { + r = QRect(0, 0, source->width(), source->height()); + } + source->beginDataAccess(); + QImage &srcImgRef(source->imageRef()); + int srcbpl = srcImgRef.bytesPerLine(); + int srcbpp = srcImgRef.depth() / 8; + const uchar *sptr = srcImgRef.constBits() + r.y() * srcbpl; + beginDataAccess(); + QImage &dstImgRef(imageRef()); + int dstbpl = dstImgRef.bytesPerLine(); + uchar *dptr = dstImgRef.bits(); + for (int y = 0; y < r.height(); ++y) { + qMemCopy(dptr, sptr + r.x() * srcbpp, r.width() * srcbpp); + sptr += srcbpl; + dptr += dstbpl; + } + endDataAccess(); + source->endDataAccess(true); +} + +/*! + To be called from the PixmapData's paintEngine(). + */ +QPaintEngine *QVolatileImage::paintEngine() +{ + if (!d->pengine) { + d->pengine = new QVolatileImagePaintEngine(&imageRef(), this); + } + return d->pengine; +} + +QVolatileImagePaintEngine::QVolatileImagePaintEngine(QPaintDevice *device, + QVolatileImage *img) + : QRasterPaintEngine(*(new QVolatileImagePaintEnginePrivate), device) +{ + Q_D(QVolatileImagePaintEngine); + d->img = img; +} + +bool QVolatileImagePaintEngine::begin(QPaintDevice *device) +{ + Q_D(QVolatileImagePaintEngine); + d->img->beginDataAccess(); + return QRasterPaintEngine::begin(device); +} + +bool QVolatileImagePaintEngine::end() +{ + Q_D(QVolatileImagePaintEngine); + bool ret = QRasterPaintEngine::end(); + d->img->endDataAccess(); + return ret; +} + +// For non-RasterClass pixmaps drawPixmap() would call toImage() which is slow in +// our case. Therefore drawPixmap() is rerouted to drawImage(). + +void QVolatileImagePaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) +{ +#ifdef Q_OS_SYMBIAN + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(p, img->imageRef()); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(p, pm); + } +#else + QRasterPaintEngine::drawPixmap(p, pm); +#endif +} + +void QVolatileImagePaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ +#ifdef Q_OS_SYMBIAN + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(r, img->imageRef(), sr); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(r, pm, sr); + } +#else + QRasterPaintEngine::drawPixmap(r, pm, sr); +#endif +} + +QT_END_NAMESPACE diff --git a/src/gui/image/qvolatileimage_p.h b/src/gui/image/qvolatileimage_p.h new file mode 100644 index 0000000..fc5d6b1 --- /dev/null +++ b/src/gui/image/qvolatileimage_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVOLATILEIMAGE_P_H +#define QVOLATILEIMAGE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qimage.h> +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE + +class QVolatileImageData; + +class Q_GUI_EXPORT QVolatileImage +{ +public: + QVolatileImage(); + QVolatileImage(int w, int h, QImage::Format format); + explicit QVolatileImage(const QImage &sourceImage); + explicit QVolatileImage(void *nativeImage, void *nativeMask = 0); + QVolatileImage(const QVolatileImage &other); + ~QVolatileImage(); + QVolatileImage &operator=(const QVolatileImage &rhs); + + bool isNull() const; + QImage::Format format() const; + int width() const; + int height() const; + int bytesPerLine() const; + int byteCount() const; + int depth() const; + bool hasAlphaChannel() const; + void beginDataAccess() const; + void endDataAccess(bool readOnly = false) const; + uchar *bits(); + const uchar *constBits() const; + bool ensureFormat(QImage::Format format); + QImage toImage() const; + QImage &imageRef(); + QPaintEngine *paintEngine(); + void setAlphaChannel(const QPixmap &alphaChannel); + void fill(uint pixelValue); + void *duplicateNativeImage() const; + void copyFrom(QVolatileImage *source, const QRect &rect); + +private: + QSharedDataPointer<QVolatileImageData> d; +}; + +QT_END_NAMESPACE + +#endif // QVOLATILEIMAGE_P_H diff --git a/src/gui/image/qvolatileimagedata.cpp b/src/gui/image/qvolatileimagedata.cpp new file mode 100644 index 0000000..51b5995 --- /dev/null +++ b/src/gui/image/qvolatileimagedata.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvolatileimagedata_p.h" +#include <QtGui/qpaintengine.h> + +QT_BEGIN_NAMESPACE + +QVolatileImageData::QVolatileImageData() + : pengine(0) +{ +} + +QVolatileImageData::QVolatileImageData(int w, int h, QImage::Format format) + : pengine(0) +{ + image = QImage(w, h, format); +} + +QVolatileImageData::QVolatileImageData(const QImage &sourceImage) + : pengine(0) +{ + image = sourceImage; +} + +QVolatileImageData::QVolatileImageData(void *, void *) + : pengine(0) +{ + // Not supported. +} + +QVolatileImageData::QVolatileImageData(const QVolatileImageData &other) +{ + image = other.image; + // The detach is not mandatory here but we do it nonetheless in order to + // keep the behavior consistent with other platforms. + image.detach(); + pengine = 0; +} + +QVolatileImageData::~QVolatileImageData() +{ + delete pengine; +} + +void QVolatileImageData::beginDataAccess() const +{ + // nothing to do here +} + +void QVolatileImageData::endDataAccess(bool readOnly) const +{ + Q_UNUSED(readOnly); + // nothing to do here +} + +bool QVolatileImageData::ensureFormat(QImage::Format format) +{ + if (image.format() != format) { + image = image.convertToFormat(format); + } + return true; +} + +void *QVolatileImageData::duplicateNativeImage() const +{ + return 0; +} + +void QVolatileImageData::ensureImage() +{ + // nothing to do here +} + +QT_END_NAMESPACE diff --git a/src/gui/image/qvolatileimagedata_p.h b/src/gui/image/qvolatileimagedata_p.h new file mode 100644 index 0000000..dab1685 --- /dev/null +++ b/src/gui/image/qvolatileimagedata_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVOLATILEIMAGEDATA_P_H +#define QVOLATILEIMAGEDATA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qimage.h> +#include <QtCore/qshareddata.h> + +#ifdef Q_OS_SYMBIAN +class CFbsBitmap; +#endif + +QT_BEGIN_NAMESPACE + +class QVolatileImageData : public QSharedData +{ +public: + QVolatileImageData(); + QVolatileImageData(int w, int h, QImage::Format format); + QVolatileImageData(const QImage &sourceImage); + QVolatileImageData(void *nativeImage, void *nativeMask); + QVolatileImageData(const QVolatileImageData &other); + ~QVolatileImageData(); + + void beginDataAccess() const; + void endDataAccess(bool readOnly = false) const; + bool ensureFormat(QImage::Format format); + void *duplicateNativeImage() const; + void ensureImage(); + +#ifdef Q_OS_SYMBIAN + void updateImage(); + void initWithBitmap(CFbsBitmap *source); + void applyMask(CFbsBitmap *mask); + void ensureBitmap(); + void release(); + QVolatileImageData *next; + QVolatileImageData *prev; + CFbsBitmap *bitmap; +#endif + QImage image; + QPaintEngine *pengine; +}; + +QT_END_NAMESPACE + +#endif // QVOLATILEIMAGEDATA_P_H diff --git a/src/gui/image/qvolatileimagedata_symbian.cpp b/src/gui/image/qvolatileimagedata_symbian.cpp new file mode 100644 index 0000000..474d0ef --- /dev/null +++ b/src/gui/image/qvolatileimagedata_symbian.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvolatileimagedata_p.h" +#include <fbs.h> +#include <QtGui/private/qt_s60_p.h> +#include <QtGui/qpaintengine.h> +#include <QtGui/private/qimage_p.h> + +QT_BEGIN_NAMESPACE + +static CFbsBitmap *rasterizeBitmap(CFbsBitmap *bitmap, TDisplayMode newMode) +{ + if (!bitmap) { + return 0; + } + QScopedPointer<CFbsBitmap> newBitmap(new CFbsBitmap); + if (newBitmap->Create(bitmap->SizeInPixels(), newMode) != KErrNone) { + qWarning("QVolatileImage: Failed to create new bitmap"); + return 0; + } + CFbsBitmapDevice *bitmapDevice = 0; + CFbsBitGc *bitmapGc = 0; + QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(newBitmap.data())); + QScopedPointer<CFbsBitmapDevice> bitmapDevicePtr(bitmapDevice); + QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); + bitmapGc->Activate(bitmapDevice); + bitmapGc->BitBlt(TPoint(), bitmap); + delete bitmapGc; + return newBitmap.take(); +} + +static inline TDisplayMode format2TDisplayMode(QImage::Format format) +{ + TDisplayMode mode; + switch (format) { + case QImage::Format_MonoLSB: + mode = EGray2; + break; + case QImage::Format_Indexed8: + mode = EColor256; + break; + case QImage::Format_RGB444: + mode = EColor4K; + break; + case QImage::Format_RGB16: + mode = EColor64K; + break; + case QImage::Format_RGB888: + mode = EColor16M; + break; + case QImage::Format_RGB32: + mode = EColor16MU; + break; + case QImage::Format_ARGB32: + mode = EColor16MA; + break; + case QImage::Format_ARGB32_Premultiplied: + mode = Q_SYMBIAN_ECOLOR16MAP; + break; + default: + mode = ENone; + break; + } + return mode; +} + +static CFbsBitmap *imageToBitmap(const QImage &image) +{ + if (image.isNull()) { + return 0; + } + CFbsBitmap *bitmap = new CFbsBitmap; + if (bitmap->Create(TSize(image.width(), image.height()), + format2TDisplayMode(image.format())) == KErrNone) { + bitmap->BeginDataAccess(); + uchar *dptr = reinterpret_cast<uchar *>(bitmap->DataAddress()); + int bmpLineLen = bitmap->DataStride(); + int imgLineLen = image.bytesPerLine(); + if (bmpLineLen == imgLineLen) { + qMemCopy(dptr, image.constBits(), image.byteCount()); + } else { + int len = qMin(bmpLineLen, imgLineLen); + const uchar *sptr = image.constBits(); + for (int y = 0; y < image.height(); ++y) { + qMemCopy(dptr, sptr, len); + dptr += bmpLineLen; + sptr += imgLineLen; + } + } + bitmap->EndDataAccess(); + } else { + qWarning("QVolatileImage: Failed to create source bitmap"); + delete bitmap; + bitmap = 0; + } + return bitmap; +} + +static CFbsBitmap *copyData(const QVolatileImageData &source) +{ + source.beginDataAccess(); + CFbsBitmap *bmp = imageToBitmap(source.image); + source.endDataAccess(); + return bmp; +} + +static CFbsBitmap *convertData(const QVolatileImageData &source, QImage::Format newFormat) +{ + source.beginDataAccess(); + QImage img = source.image.convertToFormat(newFormat); + CFbsBitmap *bmp = imageToBitmap(img); + source.endDataAccess(); + return bmp; +} + +static CFbsBitmap *duplicateBitmap(const CFbsBitmap &sourceBitmap) +{ + CFbsBitmap *bitmap = new CFbsBitmap; + if (bitmap->Duplicate(sourceBitmap.Handle()) != KErrNone) { + qWarning("QVolatileImage: Failed to duplicate source bitmap"); + delete bitmap; + bitmap = 0; + } + return bitmap; +} + +static CFbsBitmap *createBitmap(int w, int h, QImage::Format format) +{ + CFbsBitmap *bitmap = new CFbsBitmap; + if (bitmap->Create(TSize(w, h), format2TDisplayMode(format)) != KErrNone) { + qWarning("QVolatileImage: Failed to create source bitmap %d,%d (%d)", w, h, format); + delete bitmap; + bitmap = 0; + } + return bitmap; +} + +static inline bool bitmapNeedsCopy(CFbsBitmap *bitmap) +{ + bool needsCopy = bitmap->IsCompressedInRAM(); +#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE + needsCopy |= (bitmap->ExtendedBitmapType() != KNullUid); +#endif + return needsCopy; +} + +static bool cleanup_function_registered = false; +static QVolatileImageData *firstImageData = 0; + +static void cleanup() +{ + if (RFbsSession::GetSession()) { + QVolatileImageData *imageData = firstImageData; + while (imageData) { + imageData->release(); + imageData = imageData->next; + } + } +} + +static void ensureCleanup() +{ + // Destroy all underlying bitmaps in a post routine to prevent panics. + // This is a must because CFbsBitmap destructor needs the fbs session, + // that was used to create the bitmap, to be open still. + if (!cleanup_function_registered) { + qAddPostRoutine(cleanup); + cleanup_function_registered = true; + } +} + +static void registerImageData(QVolatileImageData *imageData) +{ + ensureCleanup(); + imageData->next = firstImageData; + if (firstImageData) { + firstImageData->prev = imageData; + } + firstImageData = imageData; +} + +static void unregisterImageData(QVolatileImageData *imageData) +{ + if (imageData->prev) { + imageData->prev->next = imageData->next; + } else { + firstImageData = imageData->next; + } + if (imageData->next) { + imageData->next->prev = imageData->prev; + } +} + +QVolatileImageData::QVolatileImageData() + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); +} + +QVolatileImageData::QVolatileImageData(int w, int h, QImage::Format format) + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); + bitmap = createBitmap(w, h, format); + updateImage(); +} + +QVolatileImageData::QVolatileImageData(const QImage &sourceImage) + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); + image = sourceImage; + // The following is not mandatory, but we do it here to have a bitmap + // created always in order to reduce local heap usage. + ensureBitmap(); +} + +QVolatileImageData::QVolatileImageData(void *nativeImage, void *nativeMask) + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); + if (nativeImage) { + CFbsBitmap *source = static_cast<CFbsBitmap *>(nativeImage); + CFbsBitmap *mask = static_cast<CFbsBitmap *>(nativeMask); + initWithBitmap(source); + if (mask) { + applyMask(mask); + } + } +} + +QVolatileImageData::QVolatileImageData(const QVolatileImageData &other) +{ + bitmap = 0; + pengine = 0; + next = prev = 0; + registerImageData(this); + if (!other.image.isNull()) { + bitmap = copyData(other); + updateImage(); + } +} + +QVolatileImageData::~QVolatileImageData() +{ + release(); + unregisterImageData(this); +} + +void QVolatileImageData::release() +{ + delete bitmap; + bitmap = 0; + delete pengine; + pengine = 0; +} + +void QVolatileImageData::beginDataAccess() const +{ + if (bitmap) { + bitmap->BeginDataAccess(); + } +} + +void QVolatileImageData::endDataAccess(bool readOnly) const +{ + if (bitmap) { + bitmap->EndDataAccess(readOnly); + } +} + +bool QVolatileImageData::ensureFormat(QImage::Format format) +{ + if (image.isNull()) { + return false; + } + if (image.format() != format) { + CFbsBitmap *newBitmap = convertData(*this, format); + if (newBitmap && newBitmap != bitmap) { + delete bitmap; + bitmap = newBitmap; + updateImage(); + } else { + return false; + } + } + return true; +} + +void *QVolatileImageData::duplicateNativeImage() const +{ + const_cast<QVolatileImageData *>(this)->ensureBitmap(); + if (bitmap) { + if (bitmap->DisplayMode() == EColor16M) { + // slow path: needs rgb swapping + beginDataAccess(); + QImage tmp = image.rgbSwapped(); + endDataAccess(true); + return imageToBitmap(tmp); + } else if (bitmap->DisplayMode() == EGray2) { + // slow path: needs inverting pixels + beginDataAccess(); + QImage tmp = image.copy(); + endDataAccess(true); + tmp.invertPixels(); + return imageToBitmap(tmp); + } else { + // fast path: just duplicate the bitmap + return duplicateBitmap(*bitmap); + } + } + return 0; +} + +void QVolatileImageData::updateImage() +{ + if (bitmap) { + TSize size = bitmap->SizeInPixels(); + beginDataAccess(); + // Use existing buffer, no copy. The data address never changes so it + // is enough to do this whenever we have a new CFbsBitmap. N.B. never + // use const uchar* here, that would create a read-only image data which + // would make a copy in detach() even when refcount is 1. + image = QImage(reinterpret_cast<uchar *>(bitmap->DataAddress()), + size.iWidth, size.iHeight, bitmap->DataStride(), + qt_TDisplayMode2Format(bitmap->DisplayMode())); + endDataAccess(true); + } else { + image = QImage(); + } +} + +void QVolatileImageData::initWithBitmap(CFbsBitmap *source) +{ + bool needsCopy = bitmapNeedsCopy(source); + if (source->DisplayMode() == EColor16M) { + // EColor16M is BGR + CFbsBitmap *unswappedBmp = source; + if (needsCopy) { + unswappedBmp = rasterizeBitmap(source, source->DisplayMode()); + } + unswappedBmp->BeginDataAccess(); + TSize sourceSize = unswappedBmp->SizeInPixels(); + QImage img((uchar *) unswappedBmp->DataAddress(), + sourceSize.iWidth, sourceSize.iHeight, unswappedBmp->DataStride(), + qt_TDisplayMode2Format(unswappedBmp->DisplayMode())); + img = img.rgbSwapped(); + unswappedBmp->EndDataAccess(true); + bitmap = imageToBitmap(img); + if (needsCopy) { + delete unswappedBmp; + } + } else if (needsCopy) { + // Rasterize extended and compressed bitmaps. + bitmap = rasterizeBitmap(source, EColor16MAP); + } else { + // Efficient path: no pixel data copying. Just duplicate. This of course + // means the original bitmap's data may get modified, but that's fine + // and is in accordance with the QPixmap::fromSymbianCFbsBitmap() docs. + bitmap = duplicateBitmap(*source); + } + updateImage(); + if (bitmap && bitmap->DisplayMode() == EGray2) { + // Symbian thinks set pixels are white/transparent, Qt thinks they are + // foreground/solid. Invert mono bitmaps so that masks work correctly. + beginDataAccess(); + image.invertPixels(); + endDataAccess(); + } +} + +void QVolatileImageData::applyMask(CFbsBitmap *mask) +{ + ensureFormat(QImage::Format_ARGB32_Premultiplied); + bool destroyMask = false; + if (bitmapNeedsCopy(mask)) { + mask = rasterizeBitmap(mask, EColor16MU); + if (!mask) { + return; + } + destroyMask = true; + } + mask->BeginDataAccess(); + TSize maskSize = mask->SizeInPixels(); + QImage maskImg((const uchar *) mask->DataAddress(), maskSize.iWidth, maskSize.iHeight, + mask->DataStride(), qt_TDisplayMode2Format(mask->DisplayMode())); + if (mask->DisplayMode() == EGray2) { + maskImg = maskImg.copy(); + maskImg.invertPixels(); + } + beginDataAccess(); + image.setAlphaChannel(maskImg); + endDataAccess(); + mask->EndDataAccess(true); + ensureImage(); + if (destroyMask) { + delete mask; + } +} + +void QVolatileImageData::ensureImage() +{ + if (bitmap && !image.isNull()) { + QImageData *imaged = image.data_ptr(); + if (imaged->ref != 1 || imaged->ro_data) { + // This is bad, the imagedata got shared somehow. Detach, in order to + // have the next check fail and thus have 'image' recreated. + beginDataAccess(); + image.detach(); + endDataAccess(true); + } + } + if (bitmap && image.constBits() != reinterpret_cast<const uchar *>(bitmap->DataAddress())) { + // Should not ever get here. If we do it means that either 'image' has + // been replaced with a copy (e.g. because some QImage API assigned a + // new, regular QImage to *this) or the bitmap's data address changed + // unexpectedly. + qWarning("QVolatileImageData: Ptr mismatch"); + // Recover by recreating the image so that it uses the bitmap as its buffer. + updateImage(); + } +} + +void QVolatileImageData::ensureBitmap() +{ + if (!bitmap && !image.isNull()) { + bitmap = imageToBitmap(image); + updateImage(); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index ffad75b..075d5da 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -864,7 +864,7 @@ static bool read_xpm_body( QByteArray buf(200, 0); int i; - if (cpp > 15) + if (cpp < 0 || cpp > 15) return false; // For > 256 colors, we delay creation of the image until diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 3196ba5..eb56f56 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -227,7 +227,7 @@ public: void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end); - void clear_mapping(); + void _q_clearMapping(); void sort(); bool update_source_sort_column(); @@ -281,7 +281,7 @@ typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap; void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed() { QAbstractProxyModelPrivate::_q_sourceModelDestroyed(); - clear_mapping(); + _q_clearMapping(); } void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent) @@ -293,7 +293,7 @@ void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source } } -void QSortFilterProxyModelPrivate::clear_mapping() +void QSortFilterProxyModelPrivate::_q_clearMapping() { // store the persistent indexes QModelIndexPairList source_indexes = store_persistent_indexes(); @@ -1225,7 +1225,7 @@ void QSortFilterProxyModelPrivate::_q_sourceReset() { Q_Q(QSortFilterProxyModel); invalidatePersistentIndexes(); - clear_mapping(); + _q_clearMapping(); // All internal structures are deleted in clear() q->endResetModel(); update_source_sort_column(); @@ -1521,6 +1521,7 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent) d->filter_column = 0; d->filter_role = Qt::DisplayRole; d->dynamic_sortfilter = false; + connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping())); } /*! @@ -1622,7 +1623,7 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset())); connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset())); - d->clear_mapping(); + d->_q_clearMapping(); endResetModel(); if (d->update_source_sort_column() && d->dynamic_sortfilter) d->sort(); @@ -2313,7 +2314,7 @@ void QSortFilterProxyModel::clear() { Q_D(QSortFilterProxyModel); emit layoutAboutToBeChanged(); - d->clear_mapping(); + d->_q_clearMapping(); emit layoutChanged(); } @@ -2328,7 +2329,7 @@ void QSortFilterProxyModel::invalidate() { Q_D(QSortFilterProxyModel); emit layoutAboutToBeChanged(); - d->clear_mapping(); + d->_q_clearMapping(); emit layoutChanged(); } diff --git a/src/gui/itemviews/qsortfilterproxymodel.h b/src/gui/itemviews/qsortfilterproxymodel.h index 09fd20f..afeaa69 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.h +++ b/src/gui/itemviews/qsortfilterproxymodel.h @@ -189,6 +189,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(const QModelIndex &source_parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_clearMapping()) }; QT_END_NAMESPACE diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index d03babb..21c9d3b 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2744,6 +2744,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const int start = -1; int end = -1; + int indexRow = index.row(); int count = d->header->count(); bool emptyHeader = (count == 0); QModelIndex parent = index.parent(); @@ -2780,7 +2781,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const int logicalColumn = emptyHeader ? column : d->header->logicalIndex(column); if (d->header->isSectionHidden(logicalColumn)) continue; - QModelIndex idx = d->model->index(index.row(), logicalColumn, parent); + QModelIndex idx = d->model->index(indexRow, logicalColumn, parent); if (idx.isValid()) { QWidget *editor = d->editorForIndex(idx).widget.data(); if (editor && d->persistent.contains(editor)) { @@ -3215,14 +3216,14 @@ int QTreeViewPrivate::itemHeight(int item) const if (viewItems.isEmpty()) return 0; const QModelIndex &index = viewItems.at(item).index; + if (!index.isValid()) + return 0; int height = viewItems.at(item).height; - if (height <= 0 && index.isValid()) { + if (height <= 0) { height = q_func()->indexRowSizeHint(index); viewItems[item].height = height; } - if (!index.isValid() || height < 0) - return 0; - return height; + return qMax(height, 0); } diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp index f0801e3..642d3e6 100644 --- a/src/gui/kernel/qapplication_qws.cpp +++ b/src/gui/kernel/qapplication_qws.cpp @@ -204,6 +204,11 @@ QString qws_dataDir() result = QT_VFB_DATADIR(qws_display_id); QByteArray dataDir = result.toLocal8Bit(); +#if defined(Q_OS_INTEGRITY) + /* ensure filesystem is ready before starting requests */ + WaitForFileSystemInitialization(); +#endif + if (QT_MKDIR(dataDir, 0700)) { if (errno != EEXIST) { qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData()); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index eb9c7ed..586869a 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -87,7 +87,7 @@ #include <hal.h> #include <hal_data.h> -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS #include <graphics/wstfxconst.h> #endif @@ -432,7 +432,7 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) DrawableWindow()->SetPointerGrab(ETrue); } -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS if (OwnsWindow()) { TTfxWindowPurpose windowPurpose(ETfxPurposeNone); switch (qwidget->windowType()) { @@ -1547,6 +1547,8 @@ void qt_init(QApplicationPrivate * /* priv */, int) repository = 0; #endif + qt_keymapper_private()->updateInputLanguage(); + #ifdef QT_KEYPAD_NAVIGATION if (touch) { QApplicationPrivate::navigationMode = Qt::NavigationModeNone; @@ -1586,7 +1588,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) systemFont.setFamily(systemFont.defaultFamily()); QApplicationPrivate::setSystemFont(systemFont); -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit())); #endif @@ -1693,7 +1695,7 @@ bool QApplicationPrivate::modalState() void QApplicationPrivate::enterModal_sys(QWidget *widget) { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeEnter); #endif if (widget) { @@ -1711,7 +1713,7 @@ void QApplicationPrivate::enterModal_sys(QWidget *widget) void QApplicationPrivate::leaveModal_sys(QWidget *widget) { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeExit); #endif if (widget) { @@ -2094,6 +2096,13 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent } break; #endif + +#ifdef Q_WS_S60 + case KEikInputLanguageChange: + qt_keymapper_private()->updateInputLanguage(); + break; +#endif + default: break; } @@ -2392,7 +2401,7 @@ void QApplication::restoreOverrideCursor() void QApplicationPrivate::_q_aboutToQuit() { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS // Send the shutdown tfx command S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown); #endif diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index fbb4920..589b12e 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -5227,14 +5227,15 @@ bool QETWidget::translateConfigEvent(const XEvent *event) bool trust = isVisible() && (d->topData()->parentWinId == XNone || d->topData()->parentWinId == QX11Info::appRootWindow()); + bool isCPos = false; if (event->xconfigure.send_event || trust) { // if a ConfigureNotify comes from a real sendevent request, we can // trust its values. newCPos.rx() = event->xconfigure.x + event->xconfigure.border_width; newCPos.ry() = event->xconfigure.y + event->xconfigure.border_width; + isCPos = true; } - if (isVisible()) QApplication::syncX(); @@ -5260,6 +5261,7 @@ bool QETWidget::translateConfigEvent(const XEvent *event) otherEvent.xconfigure.border_width; newCPos.ry() = otherEvent.xconfigure.y + otherEvent.xconfigure.border_width; + isCPos = true; } } #ifndef QT_NO_XSYNC @@ -5272,6 +5274,19 @@ bool QETWidget::translateConfigEvent(const XEvent *event) #endif // QT_NO_XSYNC } + if (!isCPos) { + // we didn't get an updated position of the toplevel. + // either we haven't moved or there is a bug in the window manager. + // anyway, let's query the position to be certain. + int x, y; + Window child; + XTranslateCoordinates(X11->display, internalWinId(), + QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(), + 0, 0, &x, &y, &child); + newCPos.rx() = x; + newCPos.ry() = y; + } + QRect cr (geometry()); if (newCPos != cr.topLeft()) { // compare with cpos (exluding frame) QPoint oldPos = geometry().topLeft(); @@ -5314,18 +5329,6 @@ bool QETWidget::translateConfigEvent(const XEvent *event) } if (wasResize) { - static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); - if (d->extra->compress_events && !slowResize && !data->in_show && isVisible()) { - QApplication::syncX(); - XEvent otherEvent; - while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify, &otherEvent) - && !qt_x11EventFilter(&otherEvent) && !x11Event(&otherEvent) - && otherEvent.xconfigure.event == otherEvent.xconfigure.window) { - data->crect.setWidth(otherEvent.xconfigure.width); - data->crect.setHeight(otherEvent.xconfigure.height); - } - } - if (isVisible() && data->crect.size() != oldSize) { Q_ASSERT(d->extra->topextra); QWidgetBackingStore *bs = d->extra->topextra->backingStore.data(); @@ -5334,7 +5337,7 @@ bool QETWidget::translateConfigEvent(const XEvent *event) // resize optimization in order to get invalidated regions for resized widgets. // The optimization discards all invalidateBuffer() calls since we're going to // repaint everything anyways, but that's not the case with static contents. - if (!slowResize && !hasStaticContents) + if (!hasStaticContents) d->extra->topextra->inTopLevelResize = true; QResizeEvent e(data->crect.size(), oldSize); QApplication::sendSpontaneousEvent(this, &e); diff --git a/src/gui/kernel/qcocoapanel_mac_p.h b/src/gui/kernel/qcocoapanel_mac_p.h index b41a4b5..5426159 100644 --- a/src/gui/kernel/qcocoapanel_mac_p.h +++ b/src/gui/kernel/qcocoapanel_mac_p.h @@ -60,6 +60,13 @@ QT_FORWARD_DECLARE_CLASS(QStringList); QT_FORWARD_DECLARE_CLASS(QCocoaDropData); +@interface NSPanel (QtIntegration) +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender; +- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender; +- (void)draggingExited:(id <NSDraggingInfo>)sender; +- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender; +@end + @interface QT_MANGLE_NAMESPACE(QCocoaPanel) : NSPanel { QStringList *currentCustomDragTypes; QCocoaDropData *dropData; diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 1c9258a..c4b74c6 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -88,6 +88,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if (QApplicationPrivate::isBlockedByModal(widget)) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); @@ -99,6 +101,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if ([self isSheet]) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 3d87a9e..5e8b37e 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -797,7 +797,7 @@ static int qCocoaViewCount = 0; - (BOOL)resignFirstResponder { if (!qwidget) - return NO; + return YES; // Seems like the following test only triggers if this // view is inside a QMacNativeWidget: @@ -983,7 +983,7 @@ static int qCocoaViewCount = 0; QString qtText; // Cursor position is retrived from the range. QList<QInputMethodEvent::Attribute> attrs; - attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selRange.location, 1, QVariant()); + attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selRange.location + selRange.length, 1, QVariant()); if ([aString isKindOfClass:[NSAttributedString class]]) { qtText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); composingLength = qtText.length(); diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h index e6b50f5..d567cab 100644 --- a/src/gui/kernel/qcocoawindow_mac_p.h +++ b/src/gui/kernel/qcocoawindow_mac_p.h @@ -74,6 +74,13 @@ QT_FORWARD_DECLARE_CLASS(QCocoaDropData); - (QWidget *)QT_MANGLE_NAMESPACE(qt_qwidget); @end +@interface NSWindow (QtIntegration) +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender; +- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender; +- (void)draggingExited:(id <NSDraggingInfo>)sender; +- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender; +@end + @interface QT_MANGLE_NAMESPACE(QCocoaWindow) : NSWindow { QStringList *currentCustomDragTypes; QCocoaDropData *dropData; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e7abb47..698c94b 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -53,6 +53,10 @@ #include "qgesture.h" #include "qgesture_p.h" +#ifdef Q_OS_SYMBIAN +#include "private/qcore_symbian_p.h" +#endif + QT_BEGIN_NAMESPACE /*! @@ -724,12 +728,12 @@ QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta, The \a type parameter must be QEvent::KeyPress, QEvent::KeyRelease, or QEvent::ShortcutOverride. - Int \a key is the code for the Qt::Key that the event loop should listen - for. If \a key is 0, the event is not a result of a known key; for + Int \a key is the code for the Qt::Key that the event loop should listen + for. If \a key is 0, the event is not a result of a known key; for example, it may be the result of a compose sequence or keyboard macro. - The \a modifiers holds the keyboard modifiers, and the given \a text - is the Unicode text that the key generated. If \a autorep is true, - isAutoRepeat() will be true. \a count is the number of keys involved + The \a modifiers holds the keyboard modifiers, and the given \a text + is the Unicode text that the key generated. If \a autorep is true, + isAutoRepeat() will be true. \a count is the number of keys involved in the event. */ QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text, @@ -1658,7 +1662,7 @@ Qt::ButtonState QContextMenuEvent::state() const string is controlled by the widget only). The AttributeType enum describes the different attributes that can be set. - A class implementing QWidget::inputMethodEvent() or + A class implementing QWidget::inputMethodEvent() or QGraphicsItem::inputMethodEvent() should at least understand and honor the \l TextFormat and \l Cursor attributes. @@ -3023,9 +3027,16 @@ QShowEvent::~QShowEvent() This event is only used to notify the application of a request. It may be safely ignored. - \note This class is currently supported for Mac OS X only. + \note This class is currently supported for Mac OS X and Symbian only. */ +QFileOpenEventPrivate::~QFileOpenEventPrivate() +{ +#ifdef Q_OS_SYMBIAN + file.Close(); +#endif +} + /*! \internal @@ -3049,6 +3060,22 @@ QFileOpenEvent::QFileOpenEvent(const QUrl &url) f = url.toLocalFile(); } +#ifdef Q_OS_SYMBIAN +/*! \internal +*/ +QFileOpenEvent::QFileOpenEvent(const RFile &fileHandle) + : QEvent(FileOpen) +{ + TFileName fullName; + fileHandle.FullName(fullName); + f = qt_TDesC2QString(fullName); + QScopedPointer<QFileOpenEventPrivate> priv(new QFileOpenEventPrivate(QUrl::fromLocalFile(f))); + // Duplicate here allows the file handle to be valid after S60 app construction is complete. + qt_symbian_throwIfError(priv->file.Duplicate(fileHandle)); + d = reinterpret_cast<QEventPrivate *>(priv.take()); +} +#endif + /*! \internal */ QFileOpenEvent::~QFileOpenEvent() @@ -3074,6 +3101,39 @@ QUrl QFileOpenEvent::url() const return reinterpret_cast<const QFileOpenEventPrivate *>(d)->url; } +/*! + \fn bool openFile(QFile &file, QIODevice::OpenMode flags) const + + Opens a QFile on the file referenced by this event. + Returns true if successful; otherwise returns false. + + This is necessary as some files cannot be opened by name, but require specific + information stored in this event. + For example, if this QFileOpenEvent contains a request to open a Symbian data caged file, + the QFile could only be opened from the Symbian RFile used in the construction of this event. + + \since 4.8 +*/ +bool QFileOpenEvent::openFile(QFile &file, QIODevice::OpenMode flags) const +{ + file.setFileName(f); +#ifdef Q_OS_SYMBIAN + const QFileOpenEventPrivate *priv = reinterpret_cast<const QFileOpenEventPrivate *>(d); + if (priv->file.SubSessionHandle()) { + RFile dup; + // Duplicate here means that the opened QFile will continue to be valid beyond the lifetime of this QFileOpenEvent. + // It also allows openFile to be used in threads other than the thread in which the QFileOpenEvent was created. + if (dup.Duplicate(priv->file) == KErrNone) { + QScopedPointer<RFile, QScopedPointerRCloser<RFile> > dupCloser(&dup); + bool open = file.open(dup, flags, QFile::AutoCloseHandle); + dupCloser.take(); + return open; + } + } +#endif + return file.open(flags); +} + #ifndef QT_NO_TOOLBAR /*! \internal @@ -3622,7 +3682,7 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif -/*! +/*! \class QTouchEvent \brief The QTouchEvent class contains parameters that describe a touch event. \since 4.6 diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index a7b06f4..93c2bc5 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -54,6 +54,11 @@ #include <QtCore/qvariant.h> #include <QtCore/qmap.h> #include <QtCore/qset.h> +#include <QtCore/qfile.h> + +#ifdef Q_OS_SYMBIAN +class RFile; +#endif QT_BEGIN_HEADER @@ -641,10 +646,14 @@ class Q_GUI_EXPORT QFileOpenEvent : public QEvent public: QFileOpenEvent(const QString &file); QFileOpenEvent(const QUrl &url); +#ifdef Q_OS_SYMBIAN + QFileOpenEvent(const RFile &fileHandle); +#endif ~QFileOpenEvent(); inline QString file() const { return f; } QUrl url() const; + bool openFile(QFile &file, QIODevice::OpenMode flags) const; private: QString f; }; diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 3a27023..b79f372 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -46,6 +46,10 @@ #include <QtCore/qurl.h> #include <QtGui/qevent.h> +#ifdef Q_OS_SYMBIAN +#include <f32file.h> +#endif + QT_BEGIN_NAMESPACE // @@ -174,8 +178,12 @@ public: : url(url) { } + ~QFileOpenEventPrivate(); QUrl url; +#ifdef Q_OS_SYMBIAN + RFile file; +#endif }; diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h index 7a7c6a5..ec2d849 100644 --- a/src/gui/kernel/qkeymapper_p.h +++ b/src/gui/kernel/qkeymapper_p.h @@ -213,6 +213,7 @@ public: int mapS60ScanCodesToQt(TUint s60key); int mapQtToS60Key(int qtKey); int mapQtToS60ScanCodes(int qtKey); + void updateInputLanguage(); #endif }; diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp index f0b17ac..bcf32a5 100644 --- a/src/gui/kernel/qkeymapper_s60.cpp +++ b/src/gui/kernel/qkeymapper_s60.cpp @@ -40,7 +40,11 @@ ****************************************************************************/ #include "private/qkeymapper_p.h" +#include <private/qcore_symbian_p.h> #include <e32keys.h> +#include <e32cmn.h> +#include <centralrepository.h> +#include <biditext.h> QT_BEGIN_NAMESPACE @@ -214,4 +218,32 @@ int QKeyMapperPrivate::mapQtToS60ScanCodes(int qtKey) } return res; } + +void QKeyMapperPrivate::updateInputLanguage() +{ +#ifdef Q_WS_S60 + TInt err; + CRepository *repo; + const TUid KCRUidAknFep = TUid::Uid(0x101F876D); + const TUint32 KAknFepInputTxtLang = 0x00000005; + TRAP(err, repo = CRepository::NewL(KCRUidAknFep)); + if (err != KErrNone) + return; + + TInt symbianLang; + err = repo->Get(KAknFepInputTxtLang, symbianLang); + delete repo; + if (err != KErrNone) + return; + + QString qtLang = QString::fromAscii(qt_symbianLocaleName(symbianLang)); + keyboardInputLocale = QLocale(qtLang); + keyboardInputDirection = (TBidiText::ScriptDirectionality(TLanguage(symbianLang)) == TBidiText::ERightToLeft) + ? Qt::RightToLeft : Qt::LeftToRight; +#else + keyboardInputLocale = QLocale(); + keyboardInputDirection = Qt::LeftToRight; +#endif +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index af8692d..f4a1ea5 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -184,7 +184,7 @@ struct dndenum_mapper bool Qt2Mac; }; -#ifdef QT_MAC_USE_COCOA && __OBJC__ +#if defined(QT_MAC_USE_COCOA) && defined(__OBJC__) static dndenum_mapper dnd_enums[] = { { NSDragOperationLink, Qt::LinkAction, true }, @@ -1627,6 +1627,7 @@ void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayI #ifdef QT_MAC_USE_COCOA void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse) { + QMacCocoaAutoReleasePool pool; OSMenuRef menu = static_cast<OSMenuRef>(theMenu); if (collapse) { bool previousIsSeparator = true; // setting to true kills all the separators placed at the top. diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 475d4da..bf9f6f9 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -403,11 +403,24 @@ void QWidgetPrivate::scrollChildren(int dx, int dy) } } +QInputContext *QWidgetPrivate::assignedInputContext() const +{ +#ifndef QT_NO_IM + const QWidget *widget = q_func(); + while (widget) { + if (QInputContext *qic = widget->d_func()->ic) + return qic; + widget = widget->parentWidget(); + } +#endif + return 0; +} + QInputContext *QWidgetPrivate::inputContext() const { #ifndef QT_NO_IM - if (ic) - return ic; + if (QInputContext *qic = assignedInputContext()) + return qic; return qApp->inputContext(); #else return 0; @@ -10782,7 +10795,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) case Qt::WA_InputMethodEnabled: { #ifndef QT_NO_IM QWidget *focusWidget = d->effectiveFocusWidget(); - QInputContext *ic = focusWidget->d_func()->ic; + QInputContext *ic = focusWidget->d_func()->assignedInputContext(); if (!ic && (!on || hasFocus())) ic = focusWidget->d_func()->inputContext(); if (ic) { @@ -11269,7 +11282,7 @@ void QWidget::updateMicroFocus() #if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) Q_D(QWidget); // and optimization to update input context only it has already been created. - if (d->ic || qApp->d_func()->inputContext) { + if (d->assignedInputContext() || qApp->d_func()->inputContext) { QInputContext *ic = inputContext(); if (ic) ic->update(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 0ac66cb..1083a1f 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -568,6 +568,7 @@ public: // sub-classes that their internals are about to be released. virtual void aboutToDestroy() {} + QInputContext *assignedInputContext() const; QInputContext *inputContext() const; inline QWidget *effectiveFocusWidget() { QWidget *w = q_func(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index d8779c8..85164d2 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -54,7 +54,6 @@ #ifdef Q_WS_S60 #include <aknappui.h> -#include <akntoolbar.h> #include <eikbtgpc.h> #endif @@ -64,6 +63,19 @@ // CCoeControl objects until after the CONE event handler has finished running. Q_DECLARE_METATYPE(WId) +// Workaround for the fact that S60 SDKs 3.x do not contain the akntoolbar.h +// header, even though the documentation says that it should be there, and indeed +// it is present in the library. +class CAknToolbar : public CAknControl, + public MCoeControlObserver, + public MCoeControlBackground, + public MEikCommandObserver, + public MAknFadedComponent +{ +public: + IMPORT_C void SetToolbarVisibility(const TBool visible); +}; + QT_BEGIN_NAMESPACE extern bool qt_nograb(); diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index b378b78..4bff5ac 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -1496,7 +1496,7 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) || !QX11Info::appDefaultColormap(xinfo.screen())) { // unknown DE or non-default visual/colormap, use 1bpp bitmap if (!forceReset || !topData->iconPixmap) - topData->iconPixmap = new QBitmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64)))); + topData->iconPixmap = new QPixmap(qt_toX11Pixmap(QBitmap(icon.pixmap(QSize(64,64))))); pixmap_handle = topData->iconPixmap->handle(); } else { // default depth, use a normal pixmap (even though this diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index d9aef20..181eda8 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -79,9 +79,9 @@ public: void copyDataTo(T *values) const; - T *data() { return m[0]; } - const T *data() const { return m[0]; } - const T *constData() const { return m[0]; } + T *data() { return *m; } + const T *data() const { return *m; } + const T *constData() const { return *m; } #if !defined(Q_NO_TEMPLATE_FRIENDS) template<int NN, int MM, typename TT> diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 706450a..ad05116 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -173,8 +173,8 @@ public: QGenericMatrix<N, M, qreal> toGenericMatrix() const; inline qreal *data(); - inline const qreal *data() const { return m[0]; } - inline const qreal *constData() const { return m[0]; } + inline const qreal *data() const { return *m; } + inline const qreal *constData() const { return *m; } void optimize(); @@ -974,7 +974,7 @@ inline qreal *QMatrix4x4::data() // We have to assume that the caller will modify the matrix elements, // so we flip it over to "General" mode. flagBits = General; - return m[0]; + return *m; } #ifndef QT_NO_DEBUG_STREAM diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h index e2b21c3..47387ab 100644 --- a/src/gui/painting/qbackingstore_p.h +++ b/src/gui/painting/qbackingstore_p.h @@ -209,8 +209,9 @@ private: { #ifdef Q_WS_QWS return tlw->frameGeometry(); -#endif +#else return tlw->data->crect; +#endif } inline void appendDirtyOnScreenWidget(QWidget *widget) diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index dc90003..10674f8 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -309,7 +309,7 @@ template <typename T> void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl, const uchar *src = srcPixels + y * sbpl; const uchar *srcEnd = src + srcOffset; while (src < srcEnd) { -#if defined(QT_ARCH_ARMV5) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) || (defined(QT_ARCH_SPARC) && defined(Q_CC_GNU)) +#if defined(QT_ARCH_ARMV5) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) || (defined(QT_ARCH_SPARC) && defined(Q_CC_GNU)) || (defined(QT_ARCH_INTEGRITY) && !defined(_X86_)) // non-16-bit aligned memory access is not possible on PowerPC, // ARM <v6 (QT_ARCH_ARMV5) & SH & AVR32 & SPARC w/GCC quint16 spix = (quint16(src[2])<<8) + src[1]; diff --git a/src/gui/painting/qdrawhelper_arm_simd.cpp b/src/gui/painting/qdrawhelper_arm_simd.cpp index 806df29..af9854c 100644 --- a/src/gui/painting/qdrawhelper_arm_simd.cpp +++ b/src/gui/painting/qdrawhelper_arm_simd.cpp @@ -201,8 +201,8 @@ argb32constalpha_next_pixel uxtb16 r10, r9 uxtb16 r6, r9, ror #8 - // Negate r11 and extract src alpha - mvn r9, r11 // bitwise not + // Negate r8 and extract src alpha + mvn r9, r8 // bitwise not uxtb r9, r9, ror #24 mla r10, r9, r10, r14 diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index 8d39b59..171ef46 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -89,4 +89,9 @@ QPixmapData *QGraphicsSystem::createPixmapData(QPixmapData *origin) return createPixmapData(origin->pixelType()); } +void QGraphicsSystem::releaseCachedResources() +{ + // Do nothing here +} + QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h index 1aa3aa0..0f99a31 100644 --- a/src/gui/painting/qgraphicssystem_p.h +++ b/src/gui/painting/qgraphicssystem_p.h @@ -76,6 +76,8 @@ public: //### Remove this & change qpixmap.cpp & qbitmap.cpp once every platform is gaurenteed // to have a graphics system. static QPixmapData *createDefaultPixmapData(QPixmapData::PixelType type); + + virtual void releaseCachedResources(); }; QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp index 0294c4b..5841d40 100644 --- a/src/gui/painting/qgraphicssystem_runtime.cpp +++ b/src/gui/painting/qgraphicssystem_runtime.cpp @@ -285,6 +285,7 @@ void QRuntimeWindowSurface::flush(QWidget *widget, const QRegion ®ion, void QRuntimeWindowSurface::setGeometry(const QRect &rect) { + QWindowSurface::setGeometry(rect); m_windowSurface->setGeometry(rect); } diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 47caa9f..9242fb6 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -662,19 +662,19 @@ QRasterPaintEngineState::QRasterPaintEngineState() QRasterPaintEngineState::QRasterPaintEngineState(QRasterPaintEngineState &s) : QPainterState(s) + , lastPen(s.lastPen) + , penData(s.penData) , stroker(s.stroker) + , strokeFlags(s.strokeFlags) , lastBrush(s.lastBrush) , brushData(s.brushData) - , lastPen(s.lastPen) - , penData(s.penData) , fillFlags(s.fillFlags) - , strokeFlags(s.strokeFlags) , pixmapFlags(s.pixmapFlags) , intOpacity(s.intOpacity) , txscale(s.txscale) - , flag_bits(s.flag_bits) , clip(s.clip) , dirty(s.dirty) + , flag_bits(s.flag_bits) { brushData.tempImage = 0; penData.tempImage = 0; @@ -3716,6 +3716,13 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line, const bool squareCap = (pen.capStyle() == Qt::SquareCap); const QVector<qreal> pattern = pen.dashPattern(); + qreal patternLength = 0; + for (int i = 0; i < pattern.size(); ++i) + patternLength += pattern.at(i); + + if (patternLength <= 0) + return; + qreal length = line.length(); Q_ASSERT(length > 0); while (length > 0) { diff --git a/src/gui/painting/qpaintengine_s60.cpp b/src/gui/painting/qpaintengine_s60.cpp index 1bc7799..ca303be 100644 --- a/src/gui/painting/qpaintengine_s60.cpp +++ b/src/gui/painting/qpaintengine_s60.cpp @@ -41,6 +41,7 @@ #include <private/qpaintengine_s60_p.h> #include <private/qpixmap_s60_p.h> #include <private/qt_s60_p.h> +#include <private/qvolatileimage_p.h> QT_BEGIN_NAMESPACE @@ -90,7 +91,15 @@ void QS60PaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) QRasterPaintEngine::drawPixmap(p, pm); srcData->endDataAccess(); } else { - QRasterPaintEngine::drawPixmap(p, pm); + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(p, img->imageRef()); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(p, pm); + } } } @@ -102,7 +111,15 @@ void QS60PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRect QRasterPaintEngine::drawPixmap(r, pm, sr); srcData->endDataAccess(); } else { - QRasterPaintEngine::drawPixmap(r, pm, sr); + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(r, img->imageRef(), sr); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(r, pm, sr); + } } } diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 81ca40f..8bff021 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -874,7 +874,7 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength); #endif - if (!qt_is_finite(rect.x()) && !qt_is_finite(rect.y()) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) + if ((!qt_is_finite(rect.x()) && !qt_is_finite(rect.y())) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) { #ifndef QT_NO_DEBUG qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call"); diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index 80353bc..fca46b4 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -668,26 +668,28 @@ template <class Iterator> bool qt_stroke_side(Iterator *it, #endif QLineF line(qt_fixed_to_real(prev.x), qt_fixed_to_real(prev.y), qt_fixed_to_real(e.x), qt_fixed_to_real(e.y)); - QLineF normal = line.normalVector(); - normal.setLength(offset); - line.translate(normal.dx(), normal.dy()); - - // If we are starting a new subpath, move to correct starting point. - if (first) { - if (capFirst) - stroker->joinPoints(prev.x, prev.y, line, stroker->capStyleMode()); - else - stroker->emitMoveTo(qt_real_to_fixed(line.x1()), qt_real_to_fixed(line.y1())); - *startTangent = line; - first = false; - } else { - stroker->joinPoints(prev.x, prev.y, line, stroker->joinStyleMode()); - } + if (line.p1() != line.p2()) { + QLineF normal = line.normalVector(); + normal.setLength(offset); + line.translate(normal.dx(), normal.dy()); + + // If we are starting a new subpath, move to correct starting point. + if (first) { + if (capFirst) + stroker->joinPoints(prev.x, prev.y, line, stroker->capStyleMode()); + else + stroker->emitMoveTo(qt_real_to_fixed(line.x1()), qt_real_to_fixed(line.y1())); + *startTangent = line; + first = false; + } else { + stroker->joinPoints(prev.x, prev.y, line, stroker->joinStyleMode()); + } - // Add the stroke for this line. - stroker->emitLineTo(qt_real_to_fixed(line.x2()), - qt_real_to_fixed(line.y2())); - prev = e; + // Add the stroke for this line. + stroker->emitLineTo(qt_real_to_fixed(line.x2()), + qt_real_to_fixed(line.y2())); + prev = e; + } // CurveToElement } else if (e.isCurveTo()) { diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index b5b8b81..0c99f80 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -49,6 +49,7 @@ #include <avkon.rsg> #endif #include <barsread.h> +#include <coeutils.h> #include <qconfig.h> #include "qs60mainappui.h" @@ -401,6 +402,16 @@ void QS60MainAppUi::HandleForegroundEventL(TBool aForeground) QS60MainAppUiBase::HandleForegroundEventL(aForeground); } +/*! + \internal +*/ +TBool QS60MainAppUi::ProcessCommandParametersL(TApaCommand /*aCommand*/, TFileName &/*aDocumentName*/, const TDesC8 &/*aTail*/) +{ + // bypass CEikAppUi::ProcessCommandParametersL(..) which modifies aDocumentName, preventing apparc document opening from working. + // The return value is effectively unused in Qt apps (see QS60MainDocument::OpenFileL) + return EFalse; +} + #ifndef Q_WS_S60 void QS60StubAknAppUi::HandleViewDeactivation(const TVwsViewId &, const TVwsViewId &) {} diff --git a/src/gui/s60framework/qs60mainappui.h b/src/gui/s60framework/qs60mainappui.h index ce3b5b0..bf118ff 100644 --- a/src/gui/s60framework/qs60mainappui.h +++ b/src/gui/s60framework/qs60mainappui.h @@ -131,6 +131,7 @@ public: virtual void HandleViewDeactivation(const TVwsViewId &aViewIdToBeDeactivated, const TVwsViewId &aNewlyActivatedViewId); virtual void PrepareToExit(); virtual void HandleTouchPaneSizeChange(); + virtual TBool ProcessCommandParametersL(TApaCommand aCommand, TFileName &aDocumentName, const TDesC8 &aTail); protected: virtual void HandleScreenDeviceChangedL(); diff --git a/src/gui/s60framework/qs60maindocument.cpp b/src/gui/s60framework/qs60maindocument.cpp index a8886ac..37bd55f 100644 --- a/src/gui/s60framework/qs60maindocument.cpp +++ b/src/gui/s60framework/qs60maindocument.cpp @@ -41,6 +41,9 @@ #include "qs60mainappui.h" #include "qs60maindocument.h" +#include "qcoreapplication.h" +#include "qevent.h" +#include "private/qcore_symbian_p.h" #include <exception> @@ -108,9 +111,15 @@ CEikAppUi *QS60MainDocument::CreateAppUiL() /*! \internal */ -CFileStore *QS60MainDocument::OpenFileL(TBool aDoOpen, const TDesC &aFilename, RFs &aFs) +CFileStore *QS60MainDocument::OpenFileL(TBool /*aDoOpen*/, const TDesC &aFilename, RFs &/*aFs*/) { - return QS60MainDocumentBase::OpenFileL(aDoOpen, aFilename, aFs); + QT_TRYCATCH_LEAVING( { + QCoreApplication* app = QCoreApplication::instance(); + QString qname = qt_TDesC2QString(aFilename); + QFileOpenEvent* event = new QFileOpenEvent(qname); + app->postEvent(app, event); + }) + return 0; } /*! @@ -118,7 +127,12 @@ CFileStore *QS60MainDocument::OpenFileL(TBool aDoOpen, const TDesC &aFilename, R */ void QS60MainDocument::OpenFileL(CFileStore *&aFileStore, RFile &aFile) { - QS60MainDocumentBase::OpenFileL(aFileStore, aFile); + QT_TRYCATCH_LEAVING( { + QCoreApplication* app = QCoreApplication::instance(); + QFileOpenEvent* event = new QFileOpenEvent(aFile); + app->postEvent(app, event); + aFileStore = 0; + }) } QT_END_NAMESPACE diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp index eadb8ff..2a0de3c 100644 --- a/src/gui/statemachine/qguistatemachine.cpp +++ b/src/gui/statemachine/qguistatemachine.cpp @@ -404,6 +404,7 @@ static QEvent *cloneEvent(QEvent *e) we2->setButtons(we->buttons()); we2->setModifiers(we->modifiers()); we2->setOrientation(we->orientation()); + we2->setDelta(we->delta()); return we2; } #endif diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index ac05789..64722c7 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -4621,6 +4621,13 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex tdi.attributes &= ~kThemeTrackShowThumb; if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy)) tdi.enableState = kThemeTrackNothingToScroll; + } else { + if (!(slider->subControls & SC_SliderHandle)) + tdi.attributes &= ~kThemeTrackShowThumb; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (!(slider->subControls & SC_SliderGroove)) + tdi.attributes |= kThemeTrackHideTrack; +#endif } HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 605872e..600c631 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -47,6 +47,7 @@ #include "private/qt_s60_p.h" #include "private/qpixmap_s60_p.h" #include "private/qcore_symbian_p.h" +#include "private/qvolatileimage_p.h" #include "qapplication.h" #include "qsettings.h" @@ -637,9 +638,22 @@ QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask if (error) return QPixmap(); - QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(icon); - if (mask) - pixmap.setAlphaChannel(QPixmap::fromSymbianCFbsBitmap(mask)); + QPixmap pixmap; + QScopedPointer<QPixmapData> pd(QPixmapData::create(0, 0, QPixmapData::PixmapType)); + bool nativeMaskSupported = (pd->toNativeType(QPixmapData::VolatileImage) != 0); + if (mask && nativeMaskSupported) { + // Efficient path, less copying and conversion. + QVolatileImage img(icon, mask); + pd->fromNativeType(&img, QPixmapData::VolatileImage); + pixmap = QPixmap(pd.take()); + } else { + // Potentially more expensive path. + pd->fromNativeType(icon, QPixmapData::FbsBitmap); + pixmap = QPixmap(pd.take()); + if (mask) { + pixmap.setAlphaChannel(QPixmap::fromSymbianCFbsBitmap(mask)); + } + } if ((flags & QS60StylePrivate::SF_PointEast) || (flags & QS60StylePrivate::SF_PointSouth) || @@ -795,6 +809,8 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size); MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + static const TDisplayMode displayMode = S60->supportsPremultipliedAlpha ? Q_SYMBIAN_ECOLOR16MAP : EColor16MA; + static const TInt drawParam = S60->supportsPremultipliedAlpha ? KAknsDrawParamDefault : KAknsDrawParamRGBOnly; QPixmap result; @@ -833,7 +849,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( // QS60WindowSurface::unlockBitmapHeap(); CFbsBitmap *background = new (ELeave) CFbsBitmap(); //offscreen CleanupStack::PushL(background); - User::LeaveIfError(background->Create(targetSize, EColor16MA)); + User::LeaveIfError(background->Create(targetSize, displayMode)); CFbsBitmapDevice *dev = CFbsBitmapDevice::NewL(background); CleanupStack::PushL(dev); @@ -854,7 +870,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( *gc, TPoint(), targetSize, - KAknsDrawParamDefault | KAknsDrawParamRGBOnly); + drawParam); if (drawn) result = fromFbsBitmap(background, NULL, flags, targetSize); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 4b591e2..ecf924c 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -4238,7 +4238,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op return; case PE_Widget: - if (!rule.hasDrawable()) { + if (w && !rule.hasDrawable()) { QWidget *container = containerWidget(w); if (styleSheetCaches->autoFillDisabledWidgets.contains(container) && (container == w || !renderRule(container, opt).hasBackground())) { diff --git a/src/gui/styles/qstylesheetstyle_default.cpp b/src/gui/styles/qstylesheetstyle_default.cpp index 002dcff..76ffac8 100644 --- a/src/gui/styles/qstylesheetstyle_default.cpp +++ b/src/gui/styles/qstylesheetstyle_default.cpp @@ -151,7 +151,7 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const BasicSelector bSelector; Selector selector; Declaration decl; - Value value; + QCss::Value value; Pseudo pseudo; AttributeSelector attr; diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 54ca7cc..052dc72 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -649,7 +649,7 @@ bool ValueExtractor::extractOutline(int *borders, QBrush *colors, BorderStyle *s return hit; } -static Qt::Alignment parseAlignment(const Value *values, int count) +static Qt::Alignment parseAlignment(const QCss::Value *values, int count) { Qt::Alignment a[2] = { 0, 0 }; for (int i = 0; i < qMin(2, count); i++) { @@ -672,7 +672,7 @@ static Qt::Alignment parseAlignment(const Value *values, int count) return a[0] | a[1]; } -static ColorData parseColorValue(Value v) +static ColorData parseColorValue(QCss::Value v) { if (v.type == Value::Identifier || v.type == Value::String) { v.variant.convert(QVariant::Color); @@ -706,7 +706,7 @@ static ColorData parseColorValue(Value v) if (!p.testExpr()) return ColorData(); - QVector<Value> colorDigits; + QVector<QCss::Value> colorDigits; if (!p.parseExpr(&colorDigits)) return ColorData(); @@ -738,7 +738,7 @@ static QColor colorFromData(const ColorData& c, const QPalette &pal) return QColor(); } -static BrushData parseBrushValue(const Value &v, const QPalette &pal) +static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal) { ColorData c = parseColorValue(v); if (c.type == ColorData::Color) { @@ -780,7 +780,7 @@ static BrushData parseBrushValue(const Value &v, const QPalette &pal) return BrushData(); parser.skipSpace(); if (attr.compare(QLatin1String("stop"), Qt::CaseInsensitive) == 0) { - Value stop, color; + QCss::Value stop, color; parser.next(); if (!parser.parseTerm(&stop)) return BrushData(); parser.skipSpace(); @@ -792,7 +792,7 @@ static BrushData parseBrushValue(const Value &v, const QPalette &pal) stops.append(QGradientStop(stop.variant.toReal(), colorFromData(cd, pal))); } else { parser.next(); - Value value; + QCss::Value value; (void)parser.parseTerm(&value); if (attr.compare(QLatin1String("spread"), Qt::CaseInsensitive) == 0) { spread = spreads.indexOf(value.variant.toString()); @@ -856,7 +856,7 @@ static QBrush brushFromData(const BrushData& c, const QPalette &pal) } } -static BorderStyle parseStyleValue(Value v) +static BorderStyle parseStyleValue(QCss::Value v) { if (v.type == Value::KnownIdentifier) { switch (v.variant.toInt()) { @@ -941,7 +941,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord decl.d->parsed = QVariant::fromValue<BorderData>(data); } -static void parseShorthandBackgroundProperty(const QVector<Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal) +static void parseShorthandBackgroundProperty(const QVector<QCss::Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal) { *brush = BrushData(); *image = QString(); @@ -949,7 +949,7 @@ static void parseShorthandBackgroundProperty(const QVector<Value> &values, Brush *alignment = Qt::AlignTop | Qt::AlignLeft; for (int i = 0; i < values.count(); ++i) { - const Value &v = values.at(i); + const QCss::Value &v = values.at(i); if (v.type == Value::Uri) { *image = v.variant.toString(); continue; @@ -996,7 +996,7 @@ bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *re const Declaration &decl = declarations.at(i); if (decl.d->values.isEmpty()) continue; - const Value &val = decl.d->values.at(0); + const QCss::Value &val = decl.d->values.at(0); switch (decl.d->propertyId) { case BackgroundColor: *brush = decl.brushValue(); @@ -1050,7 +1050,7 @@ bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *re return hit; } -static bool setFontSizeFromValue(Value value, QFont *font, int *fontSizeAdjustment) +static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAdjustment) { if (value.type == Value::KnownIdentifier) { bool valid = true; @@ -1087,7 +1087,7 @@ static bool setFontSizeFromValue(Value value, QFont *font, int *fontSizeAdjustme return valid; } -static bool setFontStyleFromValue(const Value &value, QFont *font) +static bool setFontStyleFromValue(const QCss::Value &value, QFont *font) { if (value.type != Value::KnownIdentifier) return false ; @@ -1100,7 +1100,7 @@ static bool setFontStyleFromValue(const Value &value, QFont *font) return false; } -static bool setFontWeightFromValue(const Value &value, QFont *font) +static bool setFontWeightFromValue(const QCss::Value &value, QFont *font) { if (value.type == Value::KnownIdentifier) { switch (value.variant.toInt()) { @@ -1121,12 +1121,12 @@ static bool setFontWeightFromValue(const Value &value, QFont *font) * and set it the \a font * \returns true if a family was extracted. */ -static bool setFontFamilyFromValues(const QVector<Value> &values, QFont *font, int start = 0) +static bool setFontFamilyFromValues(const QVector<QCss::Value> &values, QFont *font, int start = 0) { QString family; bool shouldAddSpace = false; for (int i = start; i < values.count(); ++i) { - const Value &v = values.at(i); + const QCss::Value &v = values.at(i); if (v.type == Value::TermOperatorComma) { family += QLatin1Char(','); shouldAddSpace = false; @@ -1146,7 +1146,7 @@ static bool setFontFamilyFromValues(const QVector<Value> &values, QFont *font, i return true; } -static void setTextDecorationFromValues(const QVector<Value> &values, QFont *font) +static void setTextDecorationFromValues(const QVector<QCss::Value> &values, QFont *font) { for (int i = 0; i < values.count(); ++i) { if (values.at(i).type != Value::KnownIdentifier) @@ -1165,7 +1165,7 @@ static void setTextDecorationFromValues(const QVector<Value> &values, QFont *fon } } -static void parseShorthandFontProperty(const QVector<Value> &values, QFont *font, int *fontSizeAdjustment) +static void parseShorthandFontProperty(const QVector<QCss::Value> &values, QFont *font, int *fontSizeAdjustment) { font->setStyle(QFont::StyleNormal); font->setWeight(QFont::Normal); @@ -1190,7 +1190,7 @@ static void parseShorthandFontProperty(const QVector<Value> &values, QFont *font } } -static void setFontVariantFromValue(const Value &value, QFont *font) +static void setFontVariantFromValue(const QCss::Value &value, QFont *font) { if (value.type == Value::KnownIdentifier) { switch (value.variant.toInt()) { @@ -1201,7 +1201,7 @@ static void setFontVariantFromValue(const Value &value, QFont *font) } } -static void setTextTransformFromValue(const Value &value, QFont *font) +static void setTextTransformFromValue(const QCss::Value &value, QFont *font) { if (value.type == Value::KnownIdentifier) { switch (value.variant.toInt()) { @@ -1226,7 +1226,7 @@ bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment) const Declaration &decl = declarations.at(i); if (decl.d->values.isEmpty()) continue; - const Value &val = decl.d->values.at(0); + const QCss::Value &val = decl.d->values.at(0); switch (decl.d->propertyId) { case FontSize: setFontSizeFromValue(val, font, fontSizeAdjustment); break; case FontStyle: setFontStyleFromValue(val, font); break; @@ -1411,7 +1411,7 @@ bool Declaration::realValue(qreal *real, const char *unit) const return ok; } -static bool intValueHelper(const Value &v, int *i, const char *unit) +static bool intValueHelper(const QCss::Value &v, int *i, const char *unit) { if (unit && v.type != Value::Length) return false; @@ -1460,7 +1460,7 @@ QRect Declaration::rectValue() const if (d->parsed.isValid()) return qvariant_cast<QRect>(d->parsed); - const Value &v = d->values.at(0); + const QCss::Value &v = d->values.at(0); if (v.type != Value::Function) return QRect(); QStringList func = v.variant.toStringList(); diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index 79c46b3..86bafc9 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -71,6 +71,9 @@ #if defined(Q_OS_VXWORKS) && defined(NONE) # undef NONE #endif +#if defined(Q_OS_INTEGRITY) +# undef Value +#endif QT_BEGIN_NAMESPACE diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 084b7ac..64eb27a 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -139,6 +139,9 @@ bool QFontDef::exactMatch(const QFontDef &other) const QFontDatabase::parseFontName(family, this_foundry, this_family); QFontDatabase::parseFontName(other.family, other_foundry, other_family); + this_family = QFontDatabase::resolveFontFamilyAlias(this_family); + other_family = QFontDatabase::resolveFontFamilyAlias(other_family); + return (styleHint == other.styleHint && styleStrategy == other.styleStrategy && weight == other.weight diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 8e92b1a..1e94bf5 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -1087,6 +1087,12 @@ QT_BEGIN_INCLUDE_NAMESPACE #elif defined(Q_OS_SYMBIAN) # include "qfontdatabase_s60.cpp" #endif +#if !defined(Q_WS_X11) +QString QFontDatabase::resolveFontFamilyAlias(const QString &family) +{ + return family; +} +#endif QT_END_INCLUDE_NAMESPACE static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey) diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 3e9483b..ae1130e 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -152,6 +152,7 @@ public: private: static void createDatabase(); static void parseFontName(const QString &name, QString &foundry, QString &family); + static QString resolveFontFamilyAlias(const QString &family); #if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request); #endif diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp index 2186058..02b0148 100644 --- a/src/gui/text/qfontdatabase_x11.cpp +++ b/src/gui/text/qfontdatabase_x11.cpp @@ -1972,17 +1972,6 @@ void QFontDatabase::load(const QFontPrivate *d, int script) #ifndef QT_NO_FONTCONFIG } else if (X11->has_fontconfig) { fe = loadFc(d, script, req); - if (fe != 0 && fe->fontDef.pixelSize != req.pixelSize && mainThread && qt_is_gui_used) { - QFontEngine *xlfdFontEngine = loadXlfd(d->screen, script, req); - if (xlfdFontEngine->fontDef.family == fe->fontDef.family) { - delete fe; - fe = xlfdFontEngine; - } else { - delete xlfdFontEngine; - } - } - - #endif } else if (mainThread && qt_is_gui_used) { fe = loadXlfd(d->screen, script, req); @@ -2131,4 +2120,26 @@ bool QFontDatabase::supportsThreadedFontRendering() #endif } +QString QFontDatabase::resolveFontFamilyAlias(const QString &family) +{ +#if defined(QT_NO_FONTCONFIG) + return family; +#else + FcPattern *pattern = FcPatternCreate(); + if (!pattern) + return family; + + FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) family.toUtf8().data()); + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + FcChar8 *familyAfterSubstitution; + FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); + QString resolved = QString::fromUtf8((const char *) familyAfterSubstitution); + FcPatternDestroy(pattern); + + return resolved; +#endif +} + QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp index 4802b94..b71c4a7 100644 --- a/src/gui/text/qfontengine_qws.cpp +++ b/src/gui/text/qfontengine_qws.cpp @@ -288,13 +288,16 @@ private: #else void readNode(QIODevice& f) { - uchar rw = f.getch(); - uchar cl = f.getch(); + char rw; + char cl; + f.getChar(&rw); + f.getChar(&cl); min = (rw << 8) | cl; - rw = f.getch(); - cl = f.getch(); + f.getChar(&rw); + f.getChar(&cl); max = (rw << 8) | cl; - int flags = f.getch(); + char flags; + f.getChar(&flags); if ( flags & 1 ) less = new QPFGlyphTree; else @@ -332,7 +335,7 @@ private: int n = max-min+1; for (int i=0; i<n; i++) { glyph[i].metrics = new QPFGlyphMetrics; - f.readBlock((char*)glyph[i].metrics, sizeof(QPFGlyphMetrics)); + f.read((char*)glyph[i].metrics, sizeof(QPFGlyphMetrics)); } if ( less ) less->readMetrics(f); @@ -365,7 +368,7 @@ private: //############### s = qt_screen->mapToDevice( s ); uint datasize = glyph[i].metrics->linestep * s.height(); glyph[i].data = new uchar[datasize]; // ### deleted? - f.readBlock((char*)glyph[i].data, datasize); + f.read((char*)glyph[i].data, datasize); } if ( less ) less->readData(f); @@ -385,6 +388,32 @@ public: size_t mmapLength; }; +#if defined(Q_OS_INTEGRITY) +static void *qt_mmap(void *start, size_t length, int /*prot*/, int /*flags*/, int fd, off_t offset) +{ + // INTEGRITY cannot mmap local files - load it into a local buffer + if (::lseek(fd, offset, SEEK_SET) == -1) { +# if defined(DEBUG_FONTENGINE) + perror("lseek failed"); +# endif + } + void *buf = malloc(length); + if (::read(fd, buf, length) != (ssize_t)length) { +# if defined(DEBUG_FONTENGINE) + perror("read failed"); +# endif + } + + return buf; +} +#else +static inline void *qt_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + return mmap(start, length, prot, flags, fd, offset); +} +#endif + + QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn) { @@ -395,16 +424,18 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn) QT_STATBUF st; if ( QT_FSTAT( f, &st ) ) qFatal("Failed to stat %s",QFile::encodeName(fn).data()); - uchar* data = (uchar*)mmap( 0, // any address + uchar* data = (uchar*)qt_mmap( 0, // any address st.st_size, // whole file PROT_READ, // read-only memory -#if !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) +#if defined(Q_OS_INTEGRITY) + 0, +#elif !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(Q_OS_VXWORKS) MAP_FILE | MAP_PRIVATE, // swap-backed map from file #else MAP_PRIVATE, #endif f, 0 ); // from offset 0 of f -#if defined(Q_OS_QNX4) && !defined(MAP_FAILED) +#if !defined(MAP_FAILED) && (defined(Q_OS_QNX4) || defined(Q_OS_INTEGRITY)) #define MAP_FAILED ((void *)-1) #endif if ( !data || data == (uchar*)MAP_FAILED ) diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index e15c06d..c847bb5 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -285,7 +285,7 @@ bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) if (cursor.position() != oldCursorPos) emit q->cursorPositionChanged(); emit q->microFocusChanged(); - } else if (ignoreNavigationEvents && isNavigationEvent) { + } else if (ignoreNavigationEvents && isNavigationEvent && oldSelection.anchor() == cursor.anchor()) { return false; } @@ -933,15 +933,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::MouseMove: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonRelease: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonDblClick: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::InputMethod: d->inputMethodEvent(static_cast<QInputMethodEvent *>(e)); @@ -1001,15 +1004,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::GraphicsSceneMouseMove: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseRelease: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseDoubleClick: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneContextMenu: { QGraphicsSceneContextMenuEvent *ev = static_cast<QGraphicsSceneContextMenuEvent *>(e); @@ -1018,7 +1024,8 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte case QEvent::GraphicsSceneHoverMove: { QGraphicsSceneHoverEvent *ev = static_cast<QGraphicsSceneHoverEvent *>(e); - d->mouseMoveEvent(Qt::NoButton, matrix.map(ev->pos())); + d->mouseMoveEvent(ev, Qt::NoButton, matrix.map(ev->pos()), ev->modifiers(),Qt::NoButton, + ev->screenPos()); break; } case QEvent::GraphicsSceneDragEnter: { @@ -1488,6 +1495,11 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { anchorOnMousePress = q->anchorAt(pos); @@ -1530,22 +1542,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { - QInputContext *ctx = inputContext(); - if (ctx) { - QMouseEvent ev(QEvent::MouseButtonPress, contextWidget->mapFromGlobal(globalPos), globalPos, - button, buttons, modifiers); - ctx->mouseHandler(cursorPos - cursor.position(), &ev); - } - if (!layout->preeditAreaText().isEmpty()) { - e->ignore(); - return; - } - } -#endif - if (modifiers == Qt::ShiftModifier) { + if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) { if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { selectedWordOnDoubleClick = cursor; selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); @@ -1590,10 +1587,16 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con hadSelectionOnMousePress = cursor.hasSelection(); } -void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &mousePos) +void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &mousePos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { QString anchor = q->anchorAt(mousePos); if (anchor != highlightedAnchor) { @@ -1623,12 +1626,6 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF } const qreal mouseX = qreal(mousePos.x()); -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif - int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit); if (newCursorPos == -1) return; @@ -1642,7 +1639,7 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF extendBlockwiseSelection(newCursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(newCursorPos, mouseX); - else + else if (interactionFlags & Qt::TextSelectableByMouse) setCursorPosition(newCursorPos, QTextCursor::KeepAnchor); if (interactionFlags & Qt::TextEditable) { @@ -1653,8 +1650,10 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF emit q->cursorPositionChanged(); _q_updateCurrentCharFormatAndSelection(); #ifndef QT_NO_IM - if (QInputContext *ic = inputContext()) { - ic->update(); + if (contextWidget) { + if (QInputContext *ic = inputContext()) { + ic->update(); + } } #endif //QT_NO_IM } else { @@ -1666,10 +1665,16 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF repaintOldAndNewSelection(oldSelection); } -void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) { + return; + } + const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); @@ -1727,19 +1732,21 @@ void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPoint } } -void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonDblClick, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (button != Qt::LeftButton || !(interactionFlags & Qt::TextSelectableByMouse)) { e->ignore(); return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif #ifndef QT_NO_DRAGANDDROP mightStartDrag = false; @@ -1768,6 +1775,45 @@ void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton butto } } +bool QTextControlPrivate::sendMouseEventToInputContext( + QEvent *e, QEvent::Type eventType, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos) +{ +#if !defined(QT_NO_IM) + Q_Q(QTextControl); + + QTextLayout *layout = cursor.block().layout(); + if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { + QInputContext *ctx = inputContext(); + int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position(); + + if (cursorPos < 0 || cursorPos > layout->preeditAreaText().length()) { + cursorPos = -1; + // don't send move events outside the preedit area + if (eventType == QEvent::MouseMove) + return true; + } + if (ctx) { + QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos, + button, buttons, modifiers); + ctx->mouseHandler(cursorPos, &ev); + e->setAccepted(ev.isAccepted()); + } + if (!layout->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(e); + Q_UNUSED(eventType); + Q_UNUSED(button); + Q_UNUSED(pos); + Q_UNUSED(modifiers); + Q_UNUSED(buttons); + Q_UNUSED(globalPos); +#endif + return false; +} + void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget) { #ifdef QT_NO_CONTEXTMENU diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index ecd13ea..94670e2 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -135,9 +135,23 @@ public: Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos); - void mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &pos); - void mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos); - void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos); + void mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + bool sendMouseEventToInputContext(QEvent *e, QEvent::Type eventType, Qt::MouseButton button, + const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); void contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget); void focusEvent(QFocusEvent *e); #ifdef QT_KEYPAD_NAVIGATION diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 415fa4b..a63fdbf 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1385,6 +1385,15 @@ void QTextEngine::shape(int item) const } } +static inline void releaseCachedFontEngine(QFontEngine *fontEngine) +{ + if (fontEngine) { + fontEngine->ref.deref(); + if (fontEngine->cache_count == 0 && fontEngine->ref == 0) + delete fontEngine; + } +} + void QTextEngine::invalidate() { freeMemory(); @@ -1392,6 +1401,9 @@ void QTextEngine::invalidate() maxWidth = 0; if (specialData) specialData->resolvedFormatIndices.clear(); + + releaseCachedFontEngine(feCache.prevFontEngine); + releaseCachedFontEngine(feCache.prevScaledFontEngine); feCache.reset(); } @@ -1824,7 +1836,11 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix scaledEngine = font.d->engineForScript(script); } feCache.prevFontEngine = engine; + if (engine) + engine->ref.ref(); feCache.prevScaledFontEngine = scaledEngine; + if (scaledEngine) + scaledEngine->ref.ref(); feCache.prevScript = script; feCache.prevPosition = si.position; feCache.prevLength = length(&si); @@ -1835,6 +1851,8 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix else { engine = font.d->engineForScript(script); feCache.prevFontEngine = engine; + if (engine) + engine->ref.ref(); feCache.prevScript = script; feCache.prevPosition = -1; feCache.prevLength = -1; diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp index c0a1e64..97e8c5b 100644 --- a/src/gui/text/qtextengine_mac.cpp +++ b/src/gui/text/qtextengine_mac.cpp @@ -607,8 +607,9 @@ void QTextEngine::shapeTextMac(int item) const bool stringToCMapFailed = false; if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes())) { ensureSpace(num_glyphs); - stringToCMapFailed = fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, - attributes()); + g = availableGlyphs(&si); + stringToCMapFailed = !fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, + attributes()); } if (!stringToCMapFailed) { diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 4b95000..f20e018 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -420,7 +420,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) int c = m_cursor; // cursor position after insertion of commit string if (event->replacementStart() <= 0) - c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); + c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength()); m_cursor += event->replacementStart(); @@ -456,6 +456,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) #ifndef QT_NO_IM setPreeditArea(m_cursor, event->preeditString()); #endif //QT_NO_IM + const int oldPreeditCursor = m_preeditCursor; m_preeditCursor = event->preeditString().length(); m_hideCursor = false; QList<QTextLayout::FormatRange> formats; @@ -479,6 +480,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) updateDisplayText(/*force*/ true); if (cursorPositionChanged) emitCursorPositionChanged(); + else if (m_preeditCursor != oldPreeditCursor) + emit updateMicroFocus(); if (isGettingInput) finishChange(priorState); } diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index bfe50fe..3c505c8 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -425,6 +425,7 @@ Q_SIGNALS: void textEdited(const QString &); void resetInputContext(); + void updateMicroFocus(); void accepted(); void editingFinished(); diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index d3af9e1..7435691 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -967,7 +967,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() ++lineNumber; } if (lineNumber < layoutLineCount) - visibleFromBottom += (layoutLineCount - lineNumber - 1); + visibleFromBottom += (layoutLineCount - lineNumber); break; } diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp index f2ea1bf..630aecf 100644 --- a/src/gui/widgets/qsizegrip.cpp +++ b/src/gui/widgets/qsizegrip.cpp @@ -309,6 +309,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) #ifdef Q_WS_X11 // Use a native X11 sizegrip for "real" top-level windows if supported. if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) + && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint) && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { XEvent xev; xev.xclient.type = ClientMessage; @@ -420,7 +421,8 @@ void QSizeGrip::mouseMoveEvent(QMouseEvent * e) #ifdef Q_WS_X11 if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) - && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) + && tlw->isTopLevel() && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint) + && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) return; #endif #ifdef Q_WS_WIN |