diff options
author | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2010-04-28 09:49:37 (GMT) |
---|---|---|
committer | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2010-04-28 09:49:37 (GMT) |
commit | e393f03cb89c795e4a638f84b002cb16fd1613a7 (patch) | |
tree | 1f9272e1dcf9f162682e9c3571ffb0e6aded1618 /src/gui | |
parent | 1f00130097f81bc78aebb3c055f38c066221bc98 (diff) | |
parent | 3eded761167af317bab4f4d8c1ac0a12433eb03a (diff) | |
download | Qt-e393f03cb89c795e4a638f84b002cb16fd1613a7.zip Qt-e393f03cb89c795e4a638f84b002cb16fd1613a7.tar.gz Qt-e393f03cb89c795e4a638f84b002cb16fd1613a7.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7
Diffstat (limited to 'src/gui')
107 files changed, 1848 insertions, 1336 deletions
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index c9129c1..a6bd78a 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -905,26 +905,33 @@ bool QDialog::s60AdjustedPosition() } else { cbaHeight = qt_TSize2QSize(bgContainer->Size()).height(); } - p.setY(S60->screenHeightInPixels-height()-cbaHeight); + p.setY(S60->screenHeightInPixels - height() - cbaHeight); p.setX(0); } else { const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent); - TRect cbaRect = TRect(); - AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect); - AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation(); - switch (cbaLocation) { - case AknLayoutUtils::EAknCbaLocationBottom: - p.setY(S60->screenHeightInPixels - height()-cbaRect.Height()); - p.setX((S60->screenWidthInPixels - width())>>1); - break; - case AknLayoutUtils::EAknCbaLocationRight: - p.setY((S60->screenHeightInPixels - height())>>1); - p.setX(qMax(0,S60->screenWidthInPixels-width()-scrollbarWidth-cbaRect.Width())); - break; - case AknLayoutUtils::EAknCbaLocationLeft: - p.setY((S60->screenHeightInPixels - height())>>1); - p.setX(qMax(0,scrollbarWidth+cbaRect.Width())); - break; + TRect staConTopRect = TRect(); + AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EStaconTop, staConTopRect); + if (staConTopRect.IsEmpty()) { + TRect cbaRect = TRect(); + AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect); + AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation(); + switch (cbaLocation) { + case AknLayoutUtils::EAknCbaLocationBottom: + p.setY(S60->screenHeightInPixels - height() - cbaRect.Height()); + p.setX((S60->screenWidthInPixels - width()) >> 1); + break; + case AknLayoutUtils::EAknCbaLocationRight: + p.setY((S60->screenHeightInPixels - height()) >> 1); + p.setX(qMax(0,S60->screenWidthInPixels - width() - scrollbarWidth - cbaRect.Width())); + break; + case AknLayoutUtils::EAknCbaLocationLeft: + p.setY((S60->screenHeightInPixels - height()) >> 1); + p.setX(qMax(0,scrollbarWidth + cbaRect.Width())); + break; + } + } else { + p.setY((S60->screenHeightInPixels - height()) >> 1); + p.setX(qMax(0,S60->screenWidthInPixels - width())); } } move(p); diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm index 14a5f15..28acf24 100644 --- a/src/gui/dialogs/qfiledialog_mac.mm +++ b/src/gui/dialogs/qfiledialog_mac.mm @@ -493,7 +493,7 @@ QT_USE_NAMESPACE for (int i=0; i<mNameFilterDropDownList->size(); ++i) { QString filter = hideDetails ? [self removeExtensions:filters->at(i)] : filters->at(i); [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)]; - if (filters->at(i) == selectedFilter) + if (filters->at(i).startsWith(selectedFilter)) [mPopUpButton selectItemAtIndex:i]; } } diff --git a/src/gui/dialogs/qpagesetupdialog_mac.mm b/src/gui/dialogs/qpagesetupdialog_mac.mm index 13ffa05..cfcde0f 100644 --- a/src/gui/dialogs/qpagesetupdialog_mac.mm +++ b/src/gui/dialogs/qpagesetupdialog_mac.mm @@ -232,6 +232,11 @@ void QPageSetupDialogPrivate::openCocoaPageLayout(Qt::WindowModality modality) void QPageSetupDialogPrivate::closeCocoaPageLayout() { + // NSPageLayout can change the session behind our back and then our + // d->ep->session object will become a dangling pointer. Update it + // based on the "current" session + ep->session = static_cast<PMPrintSession>([ep->printInfo PMPrintSession]); + [pageLayout release]; pageLayout = 0; } diff --git a/src/gui/dialogs/qwizard_win.cpp b/src/gui/dialogs/qwizard_win.cpp index ff13585..1390b21 100644 --- a/src/gui/dialogs/qwizard_win.cpp +++ b/src/gui/dialogs/qwizard_win.cpp @@ -51,11 +51,17 @@ #include <QtGui/QDesktopWidget> // Note, these tests are duplicates in qwindowsxpstyle_p.h. -// minimum version for Windows XP is 0x501 -#if _WIN32_WINNT < 0x0501 -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 +#ifdef Q_CC_GNU +# include <w32api.h> +# if (__W32API_MAJOR_VERSION >= 3 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION >= 5)) +# ifdef _WIN32_WINNT +# undef _WIN32_WINNT +# endif +# define _WIN32_WINNT 0x0501 +# include <commctrl.h> +# endif #endif + #include <uxtheme.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri index b90b9b0..c6c020d 100644 --- a/src/gui/egl/egl.pri +++ b/src/gui/egl/egl.pri @@ -1,24 +1,30 @@ -CONFIG += egl +contains(QT_CONFIG, egl): { + CONFIG += egl -HEADERS += \ - egl/qegl_p.h \ - egl/qeglcontext_p.h \ - egl/qeglproperties_p.h + HEADERS += \ + egl/qegl_p.h \ + egl/qeglcontext_p.h \ + egl/qeglproperties_p.h -SOURCES += \ - egl/qegl.cpp \ - egl/qeglproperties.cpp + SOURCES += \ + egl/qegl.cpp \ + egl/qeglproperties.cpp -wince*: SOURCES += egl/qegl_wince.cpp + wince*: SOURCES += egl/qegl_wince.cpp -unix { - embedded { - SOURCES += egl/qegl_qws.cpp - } else { - symbian { - SOURCES += egl/qegl_symbian.cpp - } else { - SOURCES += egl/qegl_x11.cpp - } - } + unix { + embedded { + SOURCES += egl/qegl_qws.cpp + } else { + symbian { + SOURCES += egl/qegl_symbian.cpp + } else { + SOURCES += egl/qegl_x11.cpp + } + } + } +} else:symbian { + DEFINES += QT_NO_EGL + SOURCES += egl/qegl_stub.cpp + SOURCES += egl/qeglproperties_stub.cpp } diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 6f215cc..bf9f530 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -326,10 +326,17 @@ EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) { // We need to select the correct API before calling eglCreateContext(). +#ifdef QT_OPENGL_ES #ifdef EGL_OPENGL_ES_API if (apiType == QEgl::OpenGL) eglBindAPI(EGL_OPENGL_ES_API); #endif +#else +#ifdef EGL_OPENGL_API + if (apiType == QEgl::OpenGL) + eglBindAPI(EGL_OPENGL_API); +#endif +#endif //defined(QT_OPENGL_ES) #ifdef EGL_OPENVG_API if (apiType == QEgl::OpenVG) eglBindAPI(EGL_OPENVG_API); @@ -339,7 +346,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties QEglProperties contextProps; if (properties) contextProps = *properties; -#if defined(QT_OPENGL_ES_2) +#ifdef QT_OPENGL_ES_2 if (apiType == QEgl::OpenGL) contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); #endif @@ -477,42 +484,6 @@ bool QEglContext::swapBuffers(EGLSurface surface) return ok; } -// Wait for native rendering operations to complete before starting -// to use OpenGL/OpenVG operations. -void QEglContext::waitNative() -{ -#ifdef EGL_CORE_NATIVE_ENGINE - eglWaitNative(EGL_CORE_NATIVE_ENGINE); -#endif -} - -// Wait for client OpenGL/OpenVG operations to complete before -// using native rendering operations. -void QEglContext::waitClient() -{ -#ifdef EGL_OPENGL_ES_API - if (apiType == QEgl::OpenGL) { - eglBindAPI(EGL_OPENGL_ES_API); - eglWaitClient(); - } -#else - if (apiType == QEgl::OpenGL) - eglWaitGL(); -#endif -#ifdef EGL_OPENVG_API - if (apiType == QEgl::OpenVG) { - eglBindAPI(EGL_OPENVG_API); - eglWaitClient(); - } -#endif -} - -// Query the value of a configuration attribute. -bool QEglContext::configAttrib(int name, EGLint *value) const -{ - return eglGetConfigAttrib(QEgl::display(), cfg, name, value); -} - int QEglContext::configAttrib(int name) const { EGLint value; @@ -523,15 +494,13 @@ int QEglContext::configAttrib(int name) const return EGL_DONT_CARE; } -QEglProperties QEglContext::configProperties() const -{ - return QEglProperties(config()); -} +typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*); +typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); + +// Defined in qegl.cpp: +static _eglCreateImageKHR qt_eglCreateImageKHR = 0; +static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0; -#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES) -_eglCreateImageKHR eglCreateImageKHR = 0; -_eglDestroyImageKHR eglDestroyImageKHR = 0; -#endif EGLDisplay QEgl::display() { @@ -558,8 +527,8 @@ EGLDisplay QEgl::display() // Resolve the egl extension function pointers: #if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES) if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) { - eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); - eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); + qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); + qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); } #endif } @@ -567,6 +536,33 @@ EGLDisplay QEgl::display() return dpy; } +EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) +{ + if (qt_eglCreateImageKHR) + return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); + + QEgl::display(); // Initialises function pointers + if (qt_eglCreateImageKHR) + return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); + + qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present"); + return 0; +} + +EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) +{ + if (qt_eglDestroyImageKHR) + return qt_eglDestroyImageKHR(dpy, img); + + QEgl::display(); // Initialises function pointers + if (qt_eglDestroyImageKHR) + return qt_eglDestroyImageKHR(dpy, img); + + qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present"); + return 0; +} + + #ifndef Q_WS_X11 EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties) { @@ -635,22 +631,6 @@ QString QEgl::errorString(EGLint code) } } -QString QEgl::errorString() -{ - return errorString(error()); -} - -void QEgl::clearError() -{ - eglGetError(); -} - -EGLint QEgl::error() -{ - return eglGetError(); -} - - // Dump all of the EGL configurations supported by the system. void QEgl::dumpAllConfigs() { diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index f81add6..6c562ef 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -55,6 +55,7 @@ QT_BEGIN_INCLUDE_NAMESPACE +#ifndef QT_NO_EGL #if defined(QT_OPENGL_ES_2) # include <GLES2/gl2.h> #endif @@ -64,6 +65,23 @@ QT_BEGIN_INCLUDE_NAMESPACE #else # include <EGL/egl.h> #endif +#else + +//types from egltypes.h for compiling stub without EGL headers +typedef int EGLBoolean; +typedef int EGLint; +typedef int EGLenum; +typedef int NativeDisplayType; +typedef void* NativeWindowType; +typedef void* NativePixmapType; +typedef int EGLDisplay; +typedef int EGLConfig; +typedef int EGLSurface; +typedef int EGLContext; +typedef int EGLClientBuffer; +#define EGL_NONE 0x3038 /* Attrib list terminator */ + +#endif #if defined(Q_WS_X11) // If <EGL/egl.h> included <X11/Xlib.h>, then the global namespace @@ -147,20 +165,6 @@ typedef void *EGLImageKHR; #define EGL_KHR_image_pixmap #endif -// It is possible that something has included eglext.h (like Symbian 10.1's broken egl.h), in -// which case, EGL_KHR_image/EGL_KHR_image_base will be defined. They may have also defined -// the actual function prototypes, but generally EGL_EGLEXT_PROTOTYPES will be defined in that -// case and we shouldn't re-define them here. -#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES) -typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*); -typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); - -// Defined in qegl.cpp: -extern Q_GUI_EXPORT _eglCreateImageKHR eglCreateImageKHR; -extern Q_GUI_EXPORT _eglDestroyImageKHR eglDestroyImageKHR; -#endif // (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES) - - class QEglProperties; @@ -183,7 +187,7 @@ namespace QEgl { Translucent = 0x01, Renderable = 0x02 // Config will be compatable with the paint engines (VG or GL) }; - Q_DECLARE_FLAGS(ConfigOptions, ConfigOption); + Q_DECLARE_FLAGS(ConfigOptions, ConfigOption) // Most of the time we use the same config for things like widgets & pixmaps, so rather than // go through the eglChooseConfig loop every time, we use defaultConfig, which will return @@ -196,10 +200,11 @@ namespace QEgl { Q_GUI_EXPORT void dumpAllConfigs(); - Q_GUI_EXPORT void clearError(); - Q_GUI_EXPORT EGLint error(); - Q_GUI_EXPORT QString errorString(EGLint code); - Q_GUI_EXPORT QString errorString(); +#ifdef QT_NO_EGL + Q_GUI_EXPORT QString errorString(EGLint code = 0); +#else + Q_GUI_EXPORT QString errorString(EGLint code = eglGetError()); +#endif Q_GUI_EXPORT QString extensions(); Q_GUI_EXPORT bool hasExtension(const char* extensionName); @@ -210,12 +215,16 @@ namespace QEgl { Q_GUI_EXPORT EGLNativeWindowType nativeWindow(QWidget*); Q_GUI_EXPORT EGLNativePixmapType nativePixmap(QPixmap*); + // Extension functions + Q_GUI_EXPORT EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); + Q_GUI_EXPORT EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img); + #ifdef Q_WS_X11 Q_GUI_EXPORT VisualID getCompatibleVisualId(EGLConfig config); #endif -}; +} -Q_DECLARE_OPERATORS_FOR_FLAGS(QEgl::ConfigOptions); +Q_DECLARE_OPERATORS_FOR_FLAGS(QEgl::ConfigOptions) QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_stub.cpp b/src/gui/egl/qegl_stub.cpp new file mode 100644 index 0000000..0bd3451 --- /dev/null +++ b/src/gui/egl/qegl_stub.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the 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 <QtGui/qpaintdevice.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qwidget.h> +#include <QtCore/qdebug.h> + +#include "qegl_p.h" +#include "qeglcontext_p.h" + + +QT_BEGIN_NAMESPACE + +static void noegl(const char *fn) +{ + qWarning() << fn << " called, but Qt configured without EGL" << endl; +} + +#define NOEGL noegl(__FUNCTION__); + +QEglContext::QEglContext() + : apiType(QEgl::OpenGL) + , ctx(0) + , cfg(QEGL_NO_CONFIG) + , currentSurface(0) + , current(false) + , ownsContext(true) + , sharing(false) +{ + NOEGL +} + +QEglContext::~QEglContext() +{ + NOEGL +} + +bool QEglContext::isValid() const +{ + NOEGL + return false; +} + +bool QEglContext::isCurrent() const +{ + NOEGL + return false; +} + +EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options) +{ + Q_UNUSED(devType) + Q_UNUSED(api) + Q_UNUSED(options) + NOEGL + return QEGL_NO_CONFIG; +} + + +// Choose a configuration that matches "properties". +EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match) +{ + Q_UNUSED(properties) + Q_UNUSED(match) + NOEGL + return QEGL_NO_CONFIG; +} + +bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match) +{ + Q_UNUSED(properties) + Q_UNUSED(match) + NOEGL + return false; +} + +EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties) +{ + Q_UNUSED(device) + Q_UNUSED(properties) + NOEGL + return 0; +} + + +// Create the EGLContext. +bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) +{ + Q_UNUSED(shareContext) + Q_UNUSED(properties) + NOEGL + return false; +} + +// Destroy an EGL surface object. If it was current on this context +// then call doneCurrent() for it first. +void QEglContext::destroySurface(EGLSurface surface) +{ + Q_UNUSED(surface) + NOEGL +} + +// Destroy the context. Note: this does not destroy the surface. +void QEglContext::destroyContext() +{ + NOEGL +} + +bool QEglContext::makeCurrent(EGLSurface surface) +{ + Q_UNUSED(surface) + NOEGL + return false; +} + +bool QEglContext::doneCurrent() +{ + NOEGL + return false; +} + +// Act as though doneCurrent() was called, but keep the context +// and the surface active for the moment. This allows makeCurrent() +// to skip a call to eglMakeCurrent() if we are using the same +// surface as the last set of painting operations. We leave the +// currentContext() pointer as-is for now. +bool QEglContext::lazyDoneCurrent() +{ + NOEGL + return false; +} + +bool QEglContext::swapBuffers(EGLSurface surface) +{ + Q_UNUSED(surface) + NOEGL + return false; +} + +int QEglContext::configAttrib(int name) const +{ + Q_UNUSED(name) + NOEGL + return 0; +} + +typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*); +typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); + +// Defined in qegl.cpp: +static _eglCreateImageKHR qt_eglCreateImageKHR = 0; +static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0; + + +EGLDisplay QEgl::display() +{ + NOEGL + return 0; +} + +EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) +{ + Q_UNUSED(dpy) + Q_UNUSED(ctx) + Q_UNUSED(target) + Q_UNUSED(buffer) + Q_UNUSED(attrib_list) + NOEGL + return 0; +} + +EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) +{ + Q_UNUSED(dpy) + Q_UNUSED(img) + NOEGL + return 0; +} + + +#ifndef Q_WS_X11 +EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties) +{ + Q_UNUSED(device) + Q_UNUSED(cfg) + Q_UNUSED(properties) + NOEGL + return 0; +} +#endif + + +// Return the error string associated with a specific code. +QString QEgl::errorString(EGLint code) +{ + Q_UNUSED(code) + NOEGL + return QString(); +} + +// Dump all of the EGL configurations supported by the system. +void QEgl::dumpAllConfigs() +{ + NOEGL +} + +QString QEgl::extensions() +{ + NOEGL + return QString(); +} + +bool QEgl::hasExtension(const char* extensionName) +{ + Q_UNUSED(extensionName) + NOEGL + return false; +} + +QEglContext *QEglContext::currentContext(QEgl::API api) +{ + Q_UNUSED(api) + NOEGL + return false; +} + +void QEglContext::setCurrentContext(QEgl::API api, QEglContext *context) +{ + Q_UNUSED(api) + Q_UNUSED(context) + NOEGL +} + +EGLNativeDisplayType QEgl::nativeDisplay() +{ + NOEGL + return 0; +} + +EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) +{ + Q_UNUSED(widget) + NOEGL + return (EGLNativeWindowType)0; +} + +EGLNativePixmapType QEgl::nativePixmap(QPixmap*) +{ + NOEGL + return (EGLNativePixmapType)0; +} + +QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index 5341ea1..cb8dcda 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -210,6 +210,11 @@ VisualID QEgl::getCompatibleVisualId(EGLConfig config) } XFree(chosenVisualInfo); } +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + else + qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); +#endif + if (visualId) { #ifdef QT_DEBUG_X11_VISUAL_SELECTION if (configAlphaSize > 0) @@ -263,6 +268,11 @@ VisualID QEgl::getCompatibleVisualId(EGLConfig config) # endif // QT_DEBUG_X11_VISUAL_SELECTION return visualId; } +# ifdef QT_DEBUG_X11_VISUAL_SELECTION + else + qDebug("Failed to find an XVisual which matches EGL config %d using XRender", configId); +# endif // QT_DEBUG_X11_VISUAL_SELECTION + #endif //!defined(QT_NO_XRENDER) diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h index 7eec7eb..ccde00d 100644 --- a/src/gui/egl/qeglcontext_p.h +++ b/src/gui/egl/qeglcontext_p.h @@ -85,10 +85,6 @@ public: bool lazyDoneCurrent(); bool swapBuffers(EGLSurface surface); - void waitNative(); - void waitClient(); - - bool configAttrib(int name, EGLint *value) const; int configAttrib(int name) const; EGLContext context() const { return ctx; } @@ -99,8 +95,6 @@ public: EGLConfig config() const { return cfg; } void setConfig(EGLConfig config) { cfg = config; } - QEglProperties configProperties() const; - private: QEgl::API apiType; EGLContext ctx; diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp index b5d3103..3638de5 100644 --- a/src/gui/egl/qeglproperties.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -80,19 +80,19 @@ int QEglProperties::value(int name) const case EGL_GREEN_SIZE: return 0; case EGL_BLUE_SIZE: return 0; case EGL_ALPHA_SIZE: return 0; -#if defined(EGL_LUMINANCE_SIZE) +#ifdef EGL_LUMINANCE_SIZE case EGL_LUMINANCE_SIZE: return 0; #endif -#if defined(EGL_ALPHA_MASK_SIZE) +#ifdef EGL_ALPHA_MASK_SIZE case EGL_ALPHA_MASK_SIZE: return 0; #endif -#if defined(EGL_BIND_TO_TEXTURE_RGB) +#ifdef EGL_BIND_TO_TEXTURE_RGB case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE; #endif -#if defined(EGL_BIND_TO_TEXTURE_RGBA) +#ifdef EGL_BIND_TO_TEXTURE_RGBA case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE; #endif -#if defined(EGL_COLOR_BUFFER_TYPE) +#ifdef EGL_COLOR_BUFFER_TYPE case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER; #endif case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE; @@ -103,7 +103,7 @@ int QEglProperties::value(int name) const case EGL_NATIVE_VISUAL_TYPE: return EGL_DONT_CARE; case EGL_MAX_SWAP_INTERVAL: return EGL_DONT_CARE; case EGL_MIN_SWAP_INTERVAL: return EGL_DONT_CARE; -#if defined(EGL_RENDERABLE_TYPE) +#ifdef EGL_RENDERABLE_TYPE case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT; #endif case EGL_SAMPLE_BUFFERS: return 0; @@ -115,7 +115,7 @@ int QEglProperties::value(int name) const case EGL_TRANSPARENT_GREEN_VALUE: return EGL_DONT_CARE; case EGL_TRANSPARENT_BLUE_VALUE: return EGL_DONT_CARE; -#if defined(EGL_VERSION_1_3) +#ifdef EGL_VERSION_1_3 case EGL_CONFORMANT: return 0; case EGL_MATCH_NATIVE_PIXMAP: return EGL_NONE; #endif @@ -215,15 +215,18 @@ void QEglProperties::setPixelFormat(QImage::Format pixelFormat) void QEglProperties::setRenderableType(QEgl::API api) { -#if defined(EGL_RENDERABLE_TYPE) +#ifdef EGL_RENDERABLE_TYPE #if defined(QT_OPENGL_ES_2) if (api == QEgl::OpenGL) setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT); #elif defined(QT_OPENGL_ES) if (api == QEgl::OpenGL) setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT); +#elif defined(EGL_OPENGL_BIT) + if (api == QEgl::OpenGL) + setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT); #endif -#if defined(EGL_OPENVG_BIT) +#ifdef EGL_OPENVG_BIT if (api == QEgl::OpenVG) setValue(EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT); #endif @@ -238,6 +241,9 @@ void QEglProperties::setRenderableType(QEgl::API api) // reductions in complexity are possible. bool QEglProperties::reduceConfiguration() { + if (value(EGL_SWAP_BEHAVIOR) != EGL_DONT_CARE) + removeValue(EGL_SWAP_BEHAVIOR); + #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't // find a config which supports pre-multiplied formats, remove the flag on the surface type: @@ -272,7 +278,7 @@ bool QEglProperties::reduceConfiguration() return true; if (removeValue(EGL_DEPTH_SIZE)) return true; -#if defined(EGL_BIND_TO_TEXTURE_RGB) +#ifdef EGL_BIND_TO_TEXTURE_RGB if (removeValue(EGL_BIND_TO_TEXTURE_RGB)) return true; #endif @@ -289,20 +295,6 @@ static void addTag(QString& str, const QString& tag) str += tag; } -void QEglProperties::dumpAllConfigs() -{ - EGLint count = 0; - eglGetConfigs(QEgl::display(), 0, 0, &count); - if (count < 1) - return; - - EGLConfig *configs = new EGLConfig [count]; - eglGetConfigs(QEgl::display(), configs, count, &count); - for (EGLint index = 0; index < count; ++index) - qWarning() << QEglProperties(configs[index]).toString(); - delete [] configs; -} - // Convert a property list to a string suitable for debug output. QString QEglProperties::toString() const { @@ -327,6 +319,10 @@ QString QEglProperties::toString() const if ((val & EGL_OPENGL_ES2_BIT) != 0) types += QLatin1String("es2"); #endif +#ifdef EGL_OPENGL_BIT + if ((val & EGL_OPENGL_BIT) != 0) + types += QLatin1String("gl"); +#endif if ((val & EGL_OPENVG_BIT) != 0) types += QLatin1String("vg"); if ((val & ~7) != 0) diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h index eebcf72..b1f9642 100644 --- a/src/gui/egl/qeglproperties_p.h +++ b/src/gui/egl/qeglproperties_p.h @@ -90,8 +90,6 @@ public: QString toString() const; - static void dumpAllConfigs(); - private: QVarLengthArray<int> props; }; diff --git a/src/gui/egl/qeglproperties_stub.cpp b/src/gui/egl/qeglproperties_stub.cpp new file mode 100644 index 0000000..2012ebd --- /dev/null +++ b/src/gui/egl/qeglproperties_stub.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the 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 <QtCore/qdebug.h> +#include <QtCore/qstringlist.h> + +#include "qeglproperties_p.h" +#include "qeglcontext_p.h" + +QT_BEGIN_NAMESPACE + +static void noegl(const char *fn) +{ + qWarning() << fn << " called, but Qt configured without EGL" << endl; +} + +#define NOEGL noegl(__FUNCTION__); + +// Initialize a property block. +QEglProperties::QEglProperties() +{ + NOEGL +} + +QEglProperties::QEglProperties(EGLConfig cfg) +{ + Q_UNUSED(cfg) + NOEGL +} + +// Fetch the current value associated with a property. +int QEglProperties::value(int name) const +{ + Q_UNUSED(name) + NOEGL + return 0; +} + +// Set the value associated with a property, replacing an existing +// value if there is one. +void QEglProperties::setValue(int name, int value) +{ + Q_UNUSED(name) + Q_UNUSED(value) + NOEGL +} + +// Remove a property value. Returns false if the property is not present. +bool QEglProperties::removeValue(int name) +{ + Q_UNUSED(name) + NOEGL + return false; +} + +void QEglProperties::setDeviceType(int devType) +{ + Q_UNUSED(devType) + NOEGL +} + + +// Sets the red, green, blue, and alpha sizes based on a pixel format. +// Normally used to match a configuration request to the screen format. +void QEglProperties::setPixelFormat(QImage::Format pixelFormat) +{ + Q_UNUSED(pixelFormat) + NOEGL + +} + +void QEglProperties::setRenderableType(QEgl::API api) +{ + Q_UNUSED(api); + NOEGL +} + +// Reduce the complexity of a configuration request to ask for less +// because the previous request did not result in success. Returns +// true if the complexity was reduced, or false if no further +// reductions in complexity are possible. +bool QEglProperties::reduceConfiguration() +{ + NOEGL + return false; +} + +static void addTag(QString& str, const QString& tag) +{ + Q_UNUSED(str) + Q_UNUSED(tag) + NOEGL +} + +// Convert a property list to a string suitable for debug output. +QString QEglProperties::toString() const +{ + NOEGL + return QString(); +} + +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + Q_UNUSED(dev) + NOEGL +} + +QT_END_NAMESPACE + + diff --git a/src/gui/embedded/qscreenqnx_qws.cpp b/src/gui/embedded/qscreenqnx_qws.cpp index 705db7e..a0a697f 100644 --- a/src/gui/embedded/qscreenqnx_qws.cpp +++ b/src/gui/embedded/qscreenqnx_qws.cpp @@ -205,7 +205,7 @@ static bool createMemSurface(QQnxScreenContext * const d, int w, int h) int ret = gf_surface_create(&d->memSurface, d->device, w, h, GF_FORMAT_ARGB8888, 0, GF_SURFACE_CREATE_CPU_FAST_ACCESS | GF_SURFACE_CREATE_CPU_LINEAR_ACCESSIBLE - | GF_SURFACE_PHYS_CONTIG); + | GF_SURFACE_PHYS_CONTIG | GF_SURFACE_CREATE_SHAREABLE); if (ret != GF_ERR_OK) { qWarning("QQnxScreen: gf_surface_create(%dx%d) failed with error code %d", w, h, ret); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 150343e..326f130 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1237,6 +1237,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q } dirtySceneTransform = 1; + if (!inDestructor && (transformData || (newParent && newParent->d_ptr->transformData))) + transformChanged(); // Restore the sub focus chain. if (subFocusItem) { @@ -1408,8 +1410,16 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, */ QGraphicsItem::~QGraphicsItem() { - if (d_ptr->isObject) - QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true; + if (d_ptr->isObject) { + QGraphicsObject *o = static_cast<QGraphicsObject *>(this); + QObjectPrivate *p = QObjectPrivate::get(o); + p->wasDeleted = true; + if (p->declarativeData) { + QAbstractDeclarativeData::destroyed(p->declarativeData, o); + p->declarativeData = 0; + } + } + d_ptr->inDestructor = 1; d_ptr->removeExtraItemCache(); @@ -3614,6 +3624,7 @@ void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform) q_ptr->prepareGeometryChange(); transformData->transform = transform; dirtySceneTransform = 1; + transformChanged(); } /*! @@ -3804,6 +3815,8 @@ void QGraphicsItem::setRotation(qreal angle) if (d_ptr->isObject) emit static_cast<QGraphicsObject *>(this)->rotationChanged(); + + d_ptr->transformChanged(); } /*! @@ -3868,6 +3881,8 @@ void QGraphicsItem::setScale(qreal factor) if (d_ptr->isObject) emit static_cast<QGraphicsObject *>(this)->scaleChanged(); + + d_ptr->transformChanged(); } @@ -3923,6 +3938,7 @@ void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transf transformations.at(i)->d_func()->setItem(this); d_ptr->transformData->onlyTransform = false; d_ptr->dirtySceneTransform = 1; + d_ptr->transformChanged(); } /*! @@ -3939,6 +3955,7 @@ void QGraphicsItemPrivate::prependGraphicsTransform(QGraphicsTransform *t) t->d_func()->setItem(q); transformData->onlyTransform = false; dirtySceneTransform = 1; + transformChanged(); } /*! @@ -3955,6 +3972,7 @@ void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t) t->d_func()->setItem(q); transformData->onlyTransform = false; dirtySceneTransform = 1; + transformChanged(); } /*! @@ -7307,6 +7325,18 @@ void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints) { Q_D(QGraphicsItem); d->imHints = hints; + if (!hasFocus()) + return; + d->scene->d_func()->updateInputMethodSensitivityInViews(); +#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) + QWidget *fw = QApplication::focusWidget(); + if (!fw) + return; + for (int i = 0 ; i < scene()->views().count() ; ++i) + if (scene()->views().at(i) == fw) + if (QInputContext *inputContext = fw->inputContext()) + inputContext->update(); +#endif } /*! @@ -7319,13 +7349,11 @@ void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints) void QGraphicsItem::updateMicroFocus() { #if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) - if (QWidget *fw = qApp->focusWidget()) { - if (qt_widget_private(fw)->ic || qApp->d_func()->inputContext) { - if (QInputContext *ic = fw->inputContext()) { - if (ic) - ic->update(); - } - } + if (QWidget *fw = QApplication::focusWidget()) { + for (int i = 0 ; i < scene()->views().count() ; ++i) + if (scene()->views().at(i) == fw) + if (QInputContext *inputContext = fw->inputContext()) + inputContext->update(); #ifndef QT_NO_ACCESSIBILITY // ##### is this correct QAccessible::updateAccessibility(fw, 0, QAccessible::StateChanged); @@ -10078,6 +10106,9 @@ bool QGraphicsTextItem::sceneEvent(QEvent *event) #endif //QT_NO_IM } break; + case QEvent::ShortcutOverride: + dd->sendControlEvent(event); + return true; default: break; } diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 9cc75af..9891af3 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -554,6 +554,9 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint) +#ifndef QT_NO_GRAPHICSEFFECT + Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect) +#endif Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged) Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL) Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 922581d..6b22607 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -237,6 +237,7 @@ public: scenePosDescendants(0), pendingPolish(0), mayHaveChildWithGraphicsEffect(0), + isDeclarativeItem(0), globalStackingOrder(-1), q_ptr(0) { @@ -283,6 +284,7 @@ public: void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; + virtual void transformChanged() {} int depth() const; #ifndef QT_NO_GRAPHICSEFFECT enum InvalidateReason { @@ -576,7 +578,8 @@ public: quint32 scenePosDescendants : 1; quint32 pendingPolish : 1; quint32 mayHaveChildWithGraphicsEffect : 1; - quint32 padding : 25; + quint32 isDeclarativeItem : 1; + quint32 padding : 24; // Optional stacking order int globalStackingOrder; @@ -858,7 +861,7 @@ inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect) static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func() ->source->d_func())->invalidateCache(); } - if (parentp->graphicsEffect->isEnabled()) { + if (parentp->scene && parentp->graphicsEffect->isEnabled()) { parentp->dirty = 1; parentp->fullUpdatePending = 1; } diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 2132526..1f89714 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -189,7 +189,7 @@ QT_BEGIN_NAMESPACE */ extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); -extern bool qt_tab_all_widgets; +Q_GUI_EXPORT extern bool qt_tab_all_widgets; /*! \internal @@ -897,6 +897,29 @@ bool QGraphicsProxyWidget::event(QEvent *event) } break; } +#ifndef QT_NO_TOOLTIP + case QEvent::GraphicsSceneHelp: { + // Propagate the help event (for tooltip) to the widget under mouse + if (d->lastWidgetUnderMouse) { + QGraphicsSceneHelpEvent *he = static_cast<QGraphicsSceneHelpEvent *>(event); + QPoint pos = d->mapToReceiver(mapFromScene(he->scenePos()), d->lastWidgetUnderMouse).toPoint(); + QHelpEvent e(QEvent::ToolTip, pos, he->screenPos()); + QApplication::sendEvent(d->lastWidgetUnderMouse, &e); + event->setAccepted(e.isAccepted()); + return e.isAccepted(); + } + break; + } + case QEvent::ToolTipChange: { + // Propagate tooltip change to the widget + if (!d->tooltipChangeMode) { + d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; + d->widget->setToolTip(toolTip()); + d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode; + } + break; + } +#endif default: break; } @@ -952,6 +975,14 @@ bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event) d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode; } break; + case QEvent::ToolTipChange: + // Propagate tooltip change to the proxy. + if (!d->tooltipChangeMode) { + d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; + setToolTip(d->widget->toolTip()); + d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode; + } + break; default: break; } @@ -993,9 +1024,18 @@ void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *even // Map event position from us to the receiver pos = d->mapToReceiver(pos, receiver); + QPoint globalPos = receiver->mapToGlobal(pos.toPoint()); + //If the receiver by-pass the proxy its popups + //will be top level QWidgets therefore they need + //the screen position. mapToGlobal expect the widget to + //have proper coordinates in regards of the windowing system + //but it's not true because the widget is embedded. + if (bypassGraphicsProxyWidget(receiver)) + globalPos = event->screenPos(); + // Send mouse event. ### Doesn't propagate the event. QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()), - pos.toPoint(), receiver->mapToGlobal(pos.toPoint()), event->modifiers()); + pos.toPoint(), globalPos, event->modifiers()); QApplication::sendEvent(receiver, &contextMenuEvent); event->setAccepted(contextMenuEvent.isAccepted()); diff --git a/src/gui/graphicsview/qgraphicsproxywidget_p.h b/src/gui/graphicsview/qgraphicsproxywidget_p.h index 8aed363..0e29a7e 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget_p.h +++ b/src/gui/graphicsview/qgraphicsproxywidget_p.h @@ -72,6 +72,7 @@ public: enabledChangeMode(NoMode), styleChangeMode(NoMode), paletteChangeMode(NoMode), + tooltipChangeMode(NoMode), focusFromWidgetToProxy(0) { } void init(); @@ -117,6 +118,7 @@ public: quint32 enabledChangeMode : 2; quint32 styleChangeMode : 2; quint32 paletteChangeMode : 2; + quint32 tooltipChangeMode : 2; quint32 focusFromWidgetToProxy : 1; quint32 proxyIsGivingFocus : 1; }; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4b612f4..bd0f0d8 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3786,6 +3786,12 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent) QGraphicsItem *toolTipItem = 0; for (int i = 0; i < itemsAtPos.size(); ++i) { QGraphicsItem *tmp = itemsAtPos.at(i); + if (tmp->d_func()->isProxyWidget()) { + // if the item is a proxy widget, the event is forwarded to it + sendEvent(tmp, helpEvent); + if (helpEvent->isAccepted()) + return; + } if (!tmp->toolTip().isEmpty()) { toolTipItem = tmp; break; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a767987..c951dce 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -733,11 +733,13 @@ void QGraphicsViewPrivate::_q_unsetViewportCursor() } // Restore the original viewport cursor. - hasStoredOriginalCursor = false; - if (dragMode == QGraphicsView::ScrollHandDrag) - viewport->setCursor(Qt::OpenHandCursor); - else - viewport->setCursor(originalCursor); + if (hasStoredOriginalCursor) { + hasStoredOriginalCursor = false; + if (dragMode == QGraphicsView::ScrollHandDrag) + viewport->setCursor(Qt::OpenHandCursor); + else + viewport->setCursor(originalCursor); + } } #endif @@ -1035,10 +1037,28 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg void QGraphicsViewPrivate::updateInputMethodSensitivity() { Q_Q(QGraphicsView); - bool enabled = scene && scene->focusItem() - && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod); + QGraphicsItem *focusItem = 0; + bool enabled = scene && (focusItem = scene->focusItem()) + && (focusItem->d_ptr->flags & QGraphicsItem::ItemAcceptsInputMethod); q->setAttribute(Qt::WA_InputMethodEnabled, enabled); q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled); + + if (!enabled) { + q->setInputMethodHints(0); + return; + } + + QGraphicsProxyWidget *proxy = focusItem->d_ptr->isWidget && focusItem->d_ptr->isProxyWidget() + ? static_cast<QGraphicsProxyWidget *>(focusItem) : 0; + if (!proxy) { + q->setInputMethodHints(focusItem->inputMethodHints()); + } else if (QWidget *widget = proxy->widget()) { + if (QWidget *fw = widget->focusWidget()) + widget = fw; + q->setInputMethodHints(widget->inputMethodHints()); + } else { + q->setInputMethodHints(0); + } } /*! diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 300a03f..a6370b2 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -40,9 +40,8 @@ include(statemachine/statemachine.pri) include(math3d/math3d.pri) include(effects/effects.pri) -contains(QT_CONFIG, egl): include(egl/egl.pri) +include(egl/egl.pri) win32:!wince*: DEFINES += QT_NO_EGL - embedded: QT += network QMAKE_LIBS += $$QMAKE_LIBS_GUI diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index fad51f4..bc52e99 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -879,6 +879,25 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const } /*! + \since 4.7 + + Returns the name used to create the icon, if available. + + Depending on the way the icon was created, it may have an associated + name. This is the case for icons created with fromTheme() or icons + using a QIconEngine which supports the QIconEngineV2::IconNameHook. + + \sa fromTheme(), QIconEngine +*/ +QString QIcon::name() const +{ + if (!d || !d->engine || d->engine_version < 2) + return QString(); + QIconEngineV2 *engine = static_cast<QIconEngineV2*>(d->engine); + return engine->iconName(); +} + +/*! \since 4.6 Sets the search paths for icon themes to \a paths. diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 2812703..faef07b 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -81,6 +81,8 @@ public: QSize actualSize(const QSize &size, Mode mode = Normal, State state = Off) const; + QString name() const; + void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const; inline void paint(QPainter *painter, int x, int y, int w, int h, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const { paint(painter, QRect(x, y, w, h), alignment, mode, state); } diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp index 4c7c728..050d48d 100644 --- a/src/gui/image/qiconengine.cpp +++ b/src/gui/image/qiconengine.cpp @@ -183,6 +183,10 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI that should be filled with icon sizes. Engines that work in terms of a scalable, vectorial format normally return an empty list. + \value IconNameHook Allows to query the name used to create the + icon, for example when instantiating an icon using + QIcon::fromTheme(). + \sa virtual_hook() */ @@ -301,4 +305,20 @@ QList<QSize> QIconEngineV2::availableSizes(QIcon::Mode mode, QIcon::State state) return arg.sizes; } +/*! + \since 4.7 + + Returns the name used to create the engine, if available. + + \note This is a helper method and the actual work is done by + virtual_hook() method, hence this method depends on icon engine support + and may not work with all icon engines. + */ +QString QIconEngineV2::iconName() +{ + QString name; + virtual_hook(QIconEngineV2::IconNameHook, reinterpret_cast<void*>(&name)); + return name; +} + QT_END_NAMESPACE diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h index 1f9266b..6d8b6ad 100644 --- a/src/gui/image/qiconengine.h +++ b/src/gui/image/qiconengine.h @@ -80,7 +80,7 @@ public: virtual void virtual_hook(int id, void *data); public: - enum IconEngineHook { AvailableSizesHook = 1 }; + enum IconEngineHook { AvailableSizesHook = 1, IconNameHook }; struct AvailableSizesArgument { @@ -92,6 +92,9 @@ public: // ### Qt 5: make this function const and virtual. QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off); + + // ### Qt 5: make this function const and virtual. + QString iconName(); }; QT_END_NAMESPACE diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 72ec2e8..a515ef8 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -554,6 +554,12 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) } } break; + case QIconEngineV2::IconNameHook: + { + QString &name = *reinterpret_cast<QString*>(data); + name = m_iconName; + } + break; default: QIconEngineV2::virtual_hook(id, data); } diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index d226baf..85be5b1 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -118,8 +118,8 @@ const QVector<QRgb> *qt_image_colortable(const QImage &image) return &image.d->colortable; } -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); QBasicAtomicInt qimage_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); diff --git a/src/gui/image/qpaintengine_pic.cpp b/src/gui/image/qpaintengine_pic.cpp index 029154b..fd1ee6a 100644 --- a/src/gui/image/qpaintengine_pic.cpp +++ b/src/gui/image/qpaintengine_pic.cpp @@ -477,7 +477,7 @@ void QPicturePaintEngine::drawImage(const QRectF &r, const QImage &image, const writeCmdLength(pos, r, false); } -extern int qt_defaultDpi(); +Q_GUI_EXPORT extern int qt_defaultDpi(); void QPicturePaintEngine::drawTextItem(const QPointF &p , const QTextItem &ti) { diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 45b3ed0..20a1dce 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -108,8 +108,8 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, const char *qt_mfhdr_tag = "QPIC"; // header tag static const quint16 mfhdr_maj = 11; // major version # static const quint16 mfhdr_min = 0; // minor version # -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); /*! Constructs an empty picture. diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index b183d0d..9dc15fc 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -361,8 +361,8 @@ QPaintEngine* QRasterPixmapData::paintEngine() const return image.paintEngine(); } -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const { diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index 5a882af..6bebefc 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -383,7 +383,7 @@ struct QX11AlphaDetector return has; // Will implicitly also check format and return quickly for opaque types... checked = true; - has = const_cast<QImage *>(image)->data_ptr()->checkForAlphaPixels(); + has = image->isNull() ? false : const_cast<QImage *>(image)->data_ptr()->checkForAlphaPixels(); return has; } diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 5355ad3..70770c4 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -898,7 +898,7 @@ Q_GUI_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, in expblur<12, 10, false>(blurImage, radius, quality, transposed); } -bool qt_scaleForTransform(const QTransform &transform, qreal *scale); +Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); /*! \internal diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index cc60246..b42e0ab 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -58,6 +58,11 @@ // MAknEdStateObserver::EAknActivatePenInputRequest #define QT_EAknActivatePenInputRequest MAknEdStateObserver::EAknEdwinStateEvent(7) +// EAknEditorFlagSelectionVisible is only valid from 3.2 onwards. +// Sym^3 AVKON FEP manager expects that this flag is used for FEP-aware editors +// that support text selection. +#define QT_EAknEditorFlagSelectionVisible 0x100000 + QT_BEGIN_NAMESPACE QCoeFepInputContext::QCoeFepInputContext(QObject *parent) @@ -75,7 +80,10 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_hasTempPreeditString(false) { m_fepState->SetObjectProvider(this); - m_fepState->SetFlags(EAknEditorFlagDefault); + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) + m_fepState->SetFlags(EAknEditorFlagDefault | QT_EAknEditorFlagSelectionVisible); + else + m_fepState->SetFlags(EAknEditorFlagDefault); m_fepState->SetDefaultInputMode( EAknEditorTextInputMode ); m_fepState->SetPermittedInputModes( EAknEditorAllInputModes ); m_fepState->SetDefaultCase( EAknEditorLowerCase ); @@ -432,7 +440,10 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) m_fepState->SetPermittedCases(flags); ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate); - flags = 0; + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) + flags = QT_EAknEditorFlagSelectionVisible; + else + flags = 0; if (hints & ImhUppercaseOnly && !(hints & ImhLowercaseOnly) || hints & ImhLowercaseOnly && !(hints & ImhUppercaseOnly)) { flags |= EAknEditorFlagFixedCase; @@ -771,7 +782,6 @@ void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction) if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos) longPress = 1; } - return; } QList<QInputMethodEvent::Attribute> attributes; diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 39ca75a..1869093 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -1853,14 +1853,14 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) { horizontalScrollBar()->setSingleStep(step.width() + spacing()); horizontalScrollBar()->setPageStep(viewport()->width()); - horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width() - 2 * spacing()); + horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width()); } void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) { verticalScrollBar()->setSingleStep(step.height() + spacing()); verticalScrollBar()->setPageStep(viewport()->height()); - verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height() - 2 * spacing()); + verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height()); } void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/) @@ -2276,6 +2276,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) const QPoint topLeft = initStaticLayout(info); QStyleOptionViewItemV4 option = viewOptions(); option.rect = info.bounds; + option.rect.adjust(info.spacing, info.spacing, -info.spacing, -info.spacing); // The static layout data structures are as follows: // One vector contains the coordinate in the direction of layout flow. @@ -2905,8 +2906,13 @@ void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info) batchStartRow = info.last + 1; bool done = (info.last >= rowCount() - 1); // resize the content area - if (done || !info.bounds.contains(item->rect())) - contentsSize = QSize(rect.width(), rect.height()); + if (done || !info.bounds.contains(item->rect())) { + contentsSize = rect.size(); + if (info.flow == QListView::LeftToRight) + contentsSize.rheight() += info.spacing; + else + contentsSize.rwidth() += info.spacing; + } // resize tree int insertFrom = info.first; if (done || info.first == 0) { diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index b0a23d4..ec635d4 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -142,7 +142,7 @@ static void initResources() QT_BEGIN_NAMESPACE -extern void qt_call_post_routines(); +Q_DECL_IMPORT extern void qt_call_post_routines(); int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 @@ -5936,6 +5936,7 @@ static const char * const link_xpm[] = { QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape) { +#if defined(Q_WS_X11) || defined(Q_WS_WIN) if (!move_cursor) { move_cursor = new QPixmap((const char **)move_xpm); copy_cursor = new QPixmap((const char **)copy_xpm); @@ -5959,6 +5960,7 @@ QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape) default: break; } +#endif return QPixmap(); } diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 28072fc..321492d 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1221,7 +1221,7 @@ void qt_init(QApplicationPrivate *priv, int) } #endif - if (!app_proc_ae_handlerUPP) { + if (!app_proc_ae_handlerUPP && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) { app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor); for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) { // Install apple event handler, but avoid overwriting an already @@ -2446,25 +2446,30 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event } if(!handled_event) { if(cmd.commandID == kHICommandQuit) { - handled_event = true; - HiliteMenu(0); - bool handle_quit = true; - if(QApplicationPrivate::modalState()) { - int visible = 0; - const QWidgetList tlws = QApplication::topLevelWidgets(); - for(int i = 0; i < tlws.size(); ++i) { - if(tlws.at(i)->isVisible()) - ++visible; + // Quitting the application is not Qt's responsibility if + // used in a plugin or just embedded into a native application. + // In that case, let the event pass down to the native apps event handler. + if (!QApplication::testAttribute(Qt::AA_MacPluginApplication)) { + handled_event = true; + HiliteMenu(0); + bool handle_quit = true; + if(QApplicationPrivate::modalState()) { + int visible = 0; + const QWidgetList tlws = QApplication::topLevelWidgets(); + for(int i = 0; i < tlws.size(); ++i) { + if(tlws.at(i)->isVisible()) + ++visible; + } + handle_quit = (visible <= 1); + } + if(handle_quit) { + QCloseEvent ev; + QApplication::sendSpontaneousEvent(app, &ev); + if(ev.isAccepted()) + app->quit(); + } else { + QApplication::beep(); } - handle_quit = (visible <= 1); - } - if(handle_quit) { - QCloseEvent ev; - QApplication::sendSpontaneousEvent(app, &ev); - if(ev.isAccepted()) - app->quit(); - } else { - QApplication::beep(); } } else if(cmd.commandID == kHICommandSelectWindow) { if((GetCurrentKeyModifiers() & cmdKey)) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 6d71cfe..01abe54 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -520,9 +520,11 @@ public: QGestureManager *gestureManager; QWidget *gestureWidget; +#if defined(Q_WS_X11) || defined(Q_WS_WIN) QPixmap *move_cursor; QPixmap *copy_cursor; QPixmap *link_cursor; +#endif #if defined(Q_WS_WIN) QPixmap *ignore_cursor; #endif diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 1d8eb4c..fb2837e 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -79,6 +79,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #include "qlayout.h" #include "qtooltip.h" #include "qt_windows.h" +#include "qscrollbar.h" #if defined(QT_NON_COMMERCIAL) #include "qnc_win.h" #endif @@ -701,6 +702,21 @@ void QApplicationPrivate::initializeWidgetPaletteHash() QApplication::setPalette(menu, "QMenuBar"); } +static void qt_set_windows_updateScrollBar(QWidget *widget) +{ + QList<QObject*> children = widget->children(); + for (int i = 0; i < children.size(); ++i) { + QObject *o = children.at(i); + if(!o->isWidgetType()) + continue; + if (QWidget *w = static_cast<QWidget *>(o)) + qt_set_windows_updateScrollBar(w); + } + if (qobject_cast<QScrollBar*>(widget)) + widget->updateGeometry(); +} + + /***************************************************************************** qt_init() - initializes Qt for Windows *****************************************************************************/ @@ -1930,6 +1946,15 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa } } } + else if (msg.wParam == SPI_SETNONCLIENTMETRICS) { + widget = (QETWidget*)QWidget::find(hwnd); + if (widget && !widget->parentWidget()) { + qt_set_windows_updateScrollBar(widget); + QEvent e(QEvent::LayoutRequest); + QApplication::sendEvent(widget, &e); + } + } + break; case WM_PAINT: // paint event diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm index b58fd7c..8d65aa1 100644 --- a/src/gui/kernel/qcocoamenuloader_mac.mm +++ b/src/gui/kernel/qcocoamenuloader_mac.mm @@ -53,6 +53,12 @@ QT_FORWARD_DECLARE_CLASS(QCFString) QT_FORWARD_DECLARE_CLASS(QString) +#ifndef QT_NO_TRANSLATION + QT_BEGIN_NAMESPACE + extern QString qt_mac_applicationmenu_string(int type); + QT_END_NAMESPACE +#endif + QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(QCocoaMenuLoader) @@ -226,7 +232,6 @@ QT_USE_NAMESPACE - (void)qtTranslateApplicationMenu { #ifndef QT_NO_TRANSLATION - extern QString qt_mac_applicationmenu_string(int type); [servicesItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(0))]; [hideItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(1).arg(qAppName()))]; [hideAllOthersItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(2))]; diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 129e0a5..e94d247 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp -extern bool qt_blockCocoaSettingModalWindowLevel; // qeventdispatcher_mac_p.h Q_GLOBAL_STATIC(QPointer<QWidget>, currentDragTarget); @@ -102,28 +101,15 @@ QT_END_NAMESPACE return !(isPopup || isToolTip || isTool); } -- (void)orderWindow:(NSWindowOrderingMode)orderingMode relativeTo:(NSInteger)otherWindowNumber +- (void)becomeMainWindow { - if (qt_blockCocoaSettingModalWindowLevel) { - // To avoid windows popping in front while restoring modal sessions - // in the event dispatcher, we block cocoa from ordering this window - // to front. The result of not doing this can be seen if executing - // a native color dialog on top of another executing dialog. - return; - } - [super orderWindow:orderingMode relativeTo:otherWindowNumber]; -} - -- (void)setLevel:(NSInteger)windowLevel -{ - if (qt_blockCocoaSettingModalWindowLevel) { - // To avoid windows popping in front while restoring modal sessions - // in the event dispatcher, we block cocoa from ordering this window - // to front. The result of not doing this can be seen if executing - // a native color dialog on top of another executing dialog. - return; - } - [super setLevel:windowLevel]; + [super becomeMainWindow]; + // Cocoa sometimes tell a hidden window to become the + // main window (and as such, show it). This can e.g + // happend when the application gets activated. If + // this is the case, we tell it to hide again: + if (![self isVisible]) + [self orderOut:self]; } - (void)toggleToolbarShown:(id)sender diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 06eb7ff..dd12f65 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -657,23 +657,34 @@ static int qCocoaViewCount = 0; { if (!qwidget) return; - if (qwidgetprivate->data.in_destructor) return; - QEvent enterEvent(QEvent::Enter); - NSPoint windowPoint = [event locationInWindow]; - NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint]; - NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil]; + if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) { + QEvent enterEvent(QEvent::Enter); + NSPoint windowPoint = [event locationInWindow]; + NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint]; + NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil]; QApplication::sendEvent(qwidget, &enterEvent); qt_mouseover = qwidget; - // Update cursor and dispatch hover events. + // Update cursor icon: qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint()); - if (qwidget->testAttribute(Qt::WA_Hover) && - (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window())) { - QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1)); - QApplicationPrivate::instance()->notify_helper(qwidget, &he); + + // Send mouse move and hover events as well: + if (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window()) { + // This mouse move event should be sendt, even when mouse + // tracking is switched off (to trigger tooltips): + NSEvent *mouseEvent = [NSEvent mouseEventWithType:NSMouseMoved + location:windowPoint modifierFlags:[event modifierFlags] timestamp:[event timestamp] + windowNumber:[event windowNumber] context:[event context] eventNumber:[event eventNumber] + clickCount:0 pressure:0]; + qt_mac_handleMouseEvent(self, mouseEvent, QEvent::MouseMove, Qt::NoButton); + + if (qwidget->testAttribute(Qt::WA_Hover)) { + QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1)); + QApplicationPrivate::instance()->notify_helper(qwidget, &he); + } } } } diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm index 03e38b0..c3d6c54 100644 --- a/src/gui/kernel/qcursor_mac.mm +++ b/src/gui/kernel/qcursor_mac.mm @@ -224,6 +224,15 @@ QPoint QCursor::pos() void QCursor::setPos(int x, int y) { +#ifdef QT_MAC_USE_COCOA + CGPoint pos; + pos.x = x; + pos.y = y; + + CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); +#else CGWarpMouseCursorPosition(CGPointMake(x, y)); /* I'm not too keen on doing this, but this makes it a lot easier, so I just @@ -240,6 +249,7 @@ void QCursor::setPos(int x, int y) QApplication::mouseButtons(), QApplication::keyboardModifiers()); qt_sendSpontaneousEvent(widget, &me); } +#endif } void QCursorData::initCursorFromBitmap() diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index a7f1224..0d93b9f 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -97,11 +97,6 @@ QT_BEGIN_NAMESPACE QT_USE_NAMESPACE /***************************************************************************** - Internal variables and functions - *****************************************************************************/ -bool qt_blockCocoaSettingModalWindowLevel = false; - -/***************************************************************************** Externals *****************************************************************************/ extern void qt_event_request_timer(MacTimerInfo *); //qapplication_mac.cpp @@ -752,7 +747,6 @@ bool QEventDispatcherMacPrivate::interrupt = false; #ifdef QT_MAC_USE_COCOA QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack; bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false; -bool QEventDispatcherMacPrivate::modalSessionsTemporarilyStopped = false; bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false; bool QEventDispatcherMacPrivate::cleanupModalSessionsNeeded = false; NSModalSession QEventDispatcherMacPrivate::currentModalSessionCached = 0; @@ -788,19 +782,14 @@ void QEventDispatcherMacPrivate::temporarilyStopAllModalSessions() // we need to stop all the modal session first. To avoid changing // the stacking order of the windows while doing so, we put // up a block that is used in QCocoaWindow and QCocoaPanel: - QBoolBlocker block1(blockSendPostedEvents, true); - QBoolBlocker block2(qt_blockCocoaSettingModalWindowLevel, true); - int stackSize = cocoaModalSessionStack.size(); for (int i=stackSize-1; i>=0; --i) { QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; if (info.session) { - [NSApp runModalSession:info.session]; [NSApp endModalSession:info.session]; info.session = 0; } } - modalSessionsTemporarilyStopped = true; currentModalSessionCached = 0; } @@ -834,29 +823,12 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession() // When creating a modal session cocoa will rearrange the windows. // In order to avoid windows to be put behind another we need to // keep the window level. - { - int level = [window level]; - info.session = [NSApp beginModalSessionForWindow:window]; - [window setLevel:level]; - } + int level = [window level]; + info.session = [NSApp beginModalSessionForWindow:window]; + [window setLevel:level]; } currentModalSessionCached = info.session; } - - if (modalSessionsTemporarilyStopped && currentModalSessionCached) { - // After a call to temporarilyStopAllModalSessions, cocoa have - // now posted events to restore ended modal session windows to - // the correct window level. Those events will be processed - // _after_ our new calls to beginModalSessionForWindow have - // taken effect, which will end up stacking the windows wrong on - // screen. To work around this, we block cocoa from changing the - // stacking order of the windows, and flush out the pending events - // (the block is used in QCocoaWindow and QCocoaPanel): - QBoolBlocker block1(blockSendPostedEvents, true); - QBoolBlocker block2(qt_blockCocoaSettingModalWindowLevel, true); - [NSApp runModalSession:currentModalSessionCached]; - } - modalSessionsTemporarilyStopped = false; return currentModalSessionCached; } diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h index 8ac7c65..a0afb84 100644 --- a/src/gui/kernel/qeventdispatcher_mac_p.h +++ b/src/gui/kernel/qeventdispatcher_mac_p.h @@ -176,7 +176,6 @@ public: static bool currentExecIsNSAppRun; static bool nsAppRunCalledByQt; static bool cleanupModalSessionsNeeded; - static bool modalSessionsTemporarilyStopped; static NSModalSession currentModalSessionCached; static NSModalSession currentModalSession(); static void updateChildrenWorksWhenModal(); diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp index f259654..a7145d4 100644 --- a/src/gui/kernel/qkeymapper_mac.cpp +++ b/src/gui/kernel/qkeymapper_mac.cpp @@ -756,14 +756,23 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e return true; } - if (qApp->inputContext() && qApp->inputContext()->isComposing()) { + QInputContext *currentContext = qApp->inputContext(); + if (currentContext && currentContext->isComposing()) { if (ekind == kEventRawKeyDown) { - QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext()); + QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext); if (context) context->setLastKeydownEvent(event); } return false; } + // Once we process the key down , we dont need to send the saved event again from + // kEventTextInputUnicodeForKeyEvent, so clear it. + if (currentContext && ekind == kEventRawKeyDown) { + QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext); + if (context) + context->setLastKeydownEvent(0); + } + //get modifiers Qt::KeyboardModifiers modifiers; int qtKey; diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp index fd263ef..d019c0f 100644 --- a/src/gui/kernel/qkeymapper_s60.cpp +++ b/src/gui/kernel/qkeymapper_s60.cpp @@ -144,7 +144,7 @@ static const KeyMapping keyMapping[] = { {EKeyDevice0, EStdKeyDevice0, Key_Context1}, // Found by manual testing. {EKeyDevice1, EStdKeyDevice1, Key_Context2}, // Found by manual testing. {EKeyDevice3, EStdKeyDevice3, Key_Select}, -// {EKeyDevice7, EStdKeyDevice7, Key_Camera}, //not supported by qt yet + {EKeyDevice7, EStdKeyDevice7, Key_Camera}, {EKeyApplication0, EStdKeyApplication0, Key_Menu}, // Found by manual testing. {EKeyApplication1, EStdKeyApplication1, Key_Launch1}, // Found by manual testing. {EKeyApplication2, EStdKeyApplication2, Key_MediaPlay}, // Found by manual testing. @@ -161,7 +161,7 @@ static const KeyMapping keyMapping[] = { {EKeyApplicationD, EStdKeyApplicationD, Key_LaunchD}, {EKeyApplicationE, EStdKeyApplicationE, Key_LaunchE}, {EKeyApplicationF, EStdKeyApplicationF, Key_LaunchF}, -// {EKeyApplication19, EStdKeyApplication19, Key_CameraFocus}, //not supported by qt yet + {EKeyApplication19, EStdKeyApplication19, Key_CameraFocus}, {EKeyYes, EStdKeyYes, Key_Yes}, {EKeyNo, EStdKeyNo, Key_No}, {TKeyCode(0), TStdScanCode(0), Qt::Key(0)} diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 9efcc4e..931bc33 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -390,6 +390,9 @@ static const struct { int key; const char* name; } keyname[] = { + //: This and all following "incomprehensible" strings in QShortcut context + //: are key names. Please use the localized names appearing on actual + //: keyboards or whatever is commonly used. { Qt::Key_Space, QT_TRANSLATE_NOOP("QShortcut", "Space") }, { Qt::Key_Escape, QT_TRANSLATE_NOOP("QShortcut", "Esc") }, { Qt::Key_Tab, QT_TRANSLATE_NOOP("QShortcut", "Tab") }, diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index b1e4c94..a05c7d5 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -882,7 +882,15 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* } } - QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, button, keyMods); + Qt::MouseButtons buttons = 0; + { + UInt32 mac_buttons; + if (GetEventParameter((EventRef)[event eventRef], kEventParamMouseChord, typeUInt32, 0, + sizeof(mac_buttons), 0, &mac_buttons) == noErr) + buttons = qt_mac_get_buttons(mac_buttons); + } + + QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods); qt_sendSpontaneousEvent(widgetToGetEvent, &qme); // We don't need to set the implicit grab widget here because we won't diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp index 1343959..c8fcf45 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -168,9 +168,9 @@ QTipLabel *QTipLabel::instance = 0; QTipLabel::QTipLabel(const QString &text, QWidget *w) #ifndef QT_NO_STYLE_STYLESHEET - : QLabel(w, Qt::ToolTip), styleSheetParent(0), widget(0) + : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), styleSheetParent(0), widget(0) #else - : QLabel(w, Qt::ToolTip), widget(0) + : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), widget(0) #endif { delete instance; diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp index b877784..6181b62 100644 --- a/src/gui/kernel/qwhatsthis.cpp +++ b/src/gui/kernel/qwhatsthis.cpp @@ -143,7 +143,7 @@ QT_BEGIN_NAMESPACE \sa QToolTip */ -extern void qDeleteInEventHandler(QObject *o); +Q_DECL_IMPORT extern void qDeleteInEventHandler(QObject *o); class QWhatsThat : public QWidget { diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index b19f7aa..0da5a38 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1478,7 +1478,7 @@ QWidget::~QWidget() QObjectPrivate::clearGuards(this); if (d->declarativeData) { - QDeclarativeData::destroyed(d->declarativeData, this); + QAbstractDeclarativeData::destroyed(d->declarativeData, this); d->declarativeData = 0; // don't activate again in ~QObject } @@ -7327,7 +7327,7 @@ void QWidgetPrivate::hide_helper() bool isEmbedded = false; #if !defined QT_NO_GRAPHICSVIEW - isEmbedded = q->isWindow() && nearestGraphicsProxyWidget(q->parentWidget()) != 0; + isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != 0; #else Q_UNUSED(isEmbedded); #endif diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 3d86936..d7cd2eb 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -4267,6 +4267,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) QMacCocoaAutoReleasePool pool; bool realWindow = isRealWindow(); + BOOL needDisplay = realWindow ? YES : NO; if (realWindow && !q->testAttribute(Qt::WA_DontShowOnScreen)){ adjustWithinMaxAndMinSize(w, h); @@ -4314,7 +4315,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if (currTopLeft.x() == x && currTopLeft.y() == y && cocoaFrameRect.size.width != 0 && cocoaFrameRect.size.height != 0) { - [window setFrame:cocoaFrameRect display:NO]; + [window setFrame:cocoaFrameRect display:needDisplay]; } else { // The window is moved and resized (or resized to zero). // Since Cocoa usually only sends us a resize callback after @@ -4323,7 +4324,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) // would have the same origin as the setFrame call) we shift the // window back and forth inbetween. cocoaFrameRect.origin.y += 1; - [window setFrame:cocoaFrameRect display:NO]; + [window setFrame:cocoaFrameRect display:needDisplay]; cocoaFrameRect.origin.y -= 1; [window setFrameOrigin:cocoaFrameRect.origin]; } diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 8de9eaa..f9cd59b 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -263,7 +263,7 @@ bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *wi { const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft())); const QRect tlwRect(QRect(pos, rect.size())); - if (dirty.intersects(tlwRect)) + if (fullUpdatePending || dirty.intersects(tlwRect)) return false; // We don't want to scroll junk. return windowSurface->scroll(tlwRect, dx, dy); } @@ -402,7 +402,7 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const const bool widgetDirty = widget && widget != tlw; const QRect tlwRect(topLevelRect()); const QRect surfaceGeometry(windowSurface->geometry()); - if (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size()) { + if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) { if (widgetDirty) { const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size()); const QPoint offset(widget->mapTo(tlw, QPoint())); @@ -555,6 +555,18 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up return; } + if (fullUpdatePending) { + if (updateImmediately) + sendUpdateRequest(tlw, updateImmediately); + return; + } + + if (!windowSurface->hasPartialUpdateSupport()) { + fullUpdatePending = true; + sendUpdateRequest(tlw, updateImmediately); + return; + } + const QPoint offset = widget->mapTo(tlw, QPoint()); const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect()); if (qt_region_strictContains(dirty, widgetRect.translated(offset))) { @@ -638,6 +650,18 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd return; } + if (fullUpdatePending) { + if (updateImmediately) + sendUpdateRequest(tlw, updateImmediately); + return; + } + + if (!windowSurface->hasPartialUpdateSupport()) { + fullUpdatePending = true; + sendUpdateRequest(tlw, updateImmediately); + return; + } + const QRect widgetRect = widget->d_func()->effectiveRectFor(rect); const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint()))); if (qt_region_strictContains(dirty, translatedRect)) { @@ -833,6 +857,7 @@ void QWidgetBackingStore::updateLists(QWidget *cur) QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) : tlw(topLevel), dirtyOnScreenWidgets(0), hasDirtyFromPreviousSync(false) + , fullUpdatePending(0) { windowSurface = tlw->windowSurface(); if (!windowSurface) @@ -1122,6 +1147,7 @@ void QWidgetBackingStore::sync() for (int i = 0; i < dirtyWidgets.size(); ++i) resetWidget(dirtyWidgets.at(i)); dirtyWidgets.clear(); + fullUpdatePending = false; } return; } @@ -1132,28 +1158,28 @@ void QWidgetBackingStore::sync() const QRect surfaceGeometry(windowSurface->geometry()); bool repaintAllWidgets = false; - if (inTopLevelResize || surfaceGeometry != tlwRect) { - if ((inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) { - if (hasStaticContents()) { - // Repaint existing dirty area and newly visible area. - const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); - const QRegion staticRegion(staticContents(0, clipRect)); - QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height()); - newVisible -= staticRegion; - dirty += newVisible; - windowSurface->setStaticContents(staticRegion); - } else { - // Repaint everything. - dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height()); - for (int i = 0; i < dirtyWidgets.size(); ++i) - resetWidget(dirtyWidgets.at(i)); - dirtyWidgets.clear(); - repaintAllWidgets = true; - } + if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) { + if (hasStaticContents()) { + // Repaint existing dirty area and newly visible area. + const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); + const QRegion staticRegion(staticContents(0, clipRect)); + QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height()); + newVisible -= staticRegion; + dirty += newVisible; + windowSurface->setStaticContents(staticRegion); + } else { + // Repaint everything. + dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height()); + for (int i = 0; i < dirtyWidgets.size(); ++i) + resetWidget(dirtyWidgets.at(i)); + dirtyWidgets.clear(); + repaintAllWidgets = true; } - windowSurface->setGeometry(tlwRect); } + if (inTopLevelResize || surfaceGeometry != tlwRect) + windowSurface->setGeometry(tlwRect); + if (updatesDisabled) return; @@ -1212,6 +1238,8 @@ void QWidgetBackingStore::sync() } dirtyWidgets.clear(); + fullUpdatePending = false; + if (toClean.isEmpty()) { // Nothing to repaint. However, we might have newly exposed areas on the // screen if this function was called from sync(QWidget *, QRegion)), so diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h index 02c0f7c..6510b57 100644 --- a/src/gui/painting/qbackingstore_p.h +++ b/src/gui/painting/qbackingstore_p.h @@ -91,6 +91,7 @@ public: inline bool isDirty() const { return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && !hasDirtyFromPreviousSync + && !fullUpdatePending #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) && !hasDirtyWindowDecoration() #endif @@ -115,7 +116,8 @@ private: #ifdef Q_BACKINGSTORE_SUBSURFACES QList<QWindowSurface*> subSurfaces; #endif - bool hasDirtyFromPreviousSync; + uint hasDirtyFromPreviousSync : 1; + uint fullUpdatePending : 1; QPoint tlwOffset; diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp index 147fbf9..7ff2a37 100644 --- a/src/gui/painting/qbezier.cpp +++ b/src/gui/painting/qbezier.cpp @@ -118,7 +118,7 @@ QBezier QBezier::mapBy(const QTransform &transform) const } //0.05 is really low, but required for scaled-up beziers... -static const qreal flatness = qreal(0.05); +static const qreal flatness = 0.05; //based on "Fast, precise flattening of cubic Bezier path and offset curves" // by T. F. Hain, A. L. Ahmad, S. V. R. Racherla and D. D. Langan @@ -612,88 +612,6 @@ give_up: return o - curveSegments; } -#if 0 -static inline bool IntersectBB(const QBezier &a, const QBezier &b) -{ - return a.bounds().intersects(b.bounds()); -} -#else -static int IntersectBB(const QBezier &a, const QBezier &b) -{ - // Compute bounding box for a - qreal minax, maxax, minay, maxay; - if (a.x1 > a.x4) // These are the most likely to be extremal - minax = a.x4, maxax = a.x1; - else - minax = a.x1, maxax = a.x4; - - if (a.x3 < minax) - minax = a.x3; - else if (a.x3 > maxax) - maxax = a.x3; - - if (a.x2 < minax) - minax = a.x2; - else if (a.x2 > maxax) - maxax = a.x2; - - if (a.y1 > a.y4) - minay = a.y4, maxay = a.y1; - else - minay = a.y1, maxay = a.y4; - - if (a.y3 < minay) - minay = a.y3; - else if (a.y3 > maxay) - maxay = a.y3; - - if (a.y2 < minay) - minay = a.y2; - else if (a.y2 > maxay) - maxay = a.y2; - - // Compute bounding box for b - qreal minbx, maxbx, minby, maxby; - if (b.x1 > b.x4) - minbx = b.x4, maxbx = b.x1; - else - minbx = b.x1, maxbx = b.x4; - - if (b.x3 < minbx) - minbx = b.x3; - else if (b.x3 > maxbx) - maxbx = b.x3; - - if (b.x2 < minbx) - minbx = b.x2; - else if (b.x2 > maxbx) - maxbx = b.x2; - - if (b.y1 > b.y4) - minby = b.y4, maxby = b.y1; - else - minby = b.y1, maxby = b.y4; - - if (b.y3 < minby) - minby = b.y3; - else if (b.y3 > maxby) - maxby = b.y3; - - if (b.y2 < minby) - minby = b.y2; - else if (b.y2 > maxby) - maxby = b.y2; - - // Test bounding box of b against bounding box of a - if ((minax > maxbx) || (minay > maxby) // Not >= : need boundary case - || (minbx > maxax) || (minby > maxay)) - return 0; // they don't intersect - else - return 1; // they intersect -} -#endif - - #ifdef QDEBUG_BEZIER static QDebug operator<<(QDebug dbg, const QBezier &bz) { @@ -705,193 +623,6 @@ static QDebug operator<<(QDebug dbg, const QBezier &bz) } #endif -static bool RecursivelyIntersect(const QBezier &a, qreal t0, qreal t1, int deptha, - const QBezier &b, qreal u0, qreal u1, int depthb, - QVector<QPair<qreal, qreal> > *t) -{ -#ifdef QDEBUG_BEZIER - static int I = 0; - int currentD = I; - fprintf(stderr, "%d) t0 = %lf, t1 = %lf, deptha = %d\n" - "u0 = %lf, u1 = %lf, depthb = %d\n", I++, t0, t1, deptha, - u0, u1, depthb); -#endif - if (deptha > 0) { - QBezier A[2]; - a.split(&A[0], &A[1]); - qreal tmid = (t0+t1)*0.5; - //qDebug()<<"\t1)"<<A[0]; - //qDebug()<<"\t2)"<<A[1]; - deptha--; - if (depthb > 0) { - QBezier B[2]; - b.split(&B[0], &B[1]); - //qDebug()<<"\t3)"<<B[0]; - //qDebug()<<"\t4)"<<B[1]; - qreal umid = (u0+u1)*0.5; - depthb--; - if (IntersectBB(A[0], B[0])) { - //fprintf(stderr, "\t 1 from %d\n", currentD); - if (RecursivelyIntersect(A[0], t0, tmid, deptha, - B[0], u0, umid, depthb, - t) && !t) - return true; - } - if (IntersectBB(A[1], B[0])) { - //fprintf(stderr, "\t 2 from %d\n", currentD); - if (RecursivelyIntersect(A[1], tmid, t1, deptha, - B[0], u0, umid, depthb, - t) && !t) - return true; - } - if (IntersectBB(A[0], B[1])) { - //fprintf(stderr, "\t 3 from %d\n", currentD); - if (RecursivelyIntersect(A[0], t0, tmid, deptha, - B[1], umid, u1, depthb, - t) && !t) - return true; - } - if (IntersectBB(A[1], B[1])) { - //fprintf(stderr, "\t 4 from %d\n", currentD); - if (RecursivelyIntersect(A[1], tmid, t1, deptha, - B[1], umid, u1, depthb, - t) && !t) - return true; - } - return t ? !t->isEmpty() : false; - } else { - if (IntersectBB(A[0], b)) { - //fprintf(stderr, "\t 5 from %d\n", currentD); - if (RecursivelyIntersect(A[0], t0, tmid, deptha, - b, u0, u1, depthb, - t) && !t) - return true; - } - if (IntersectBB(A[1], b)) { - //fprintf(stderr, "\t 6 from %d\n", currentD); - if (RecursivelyIntersect(A[1], tmid, t1, deptha, - b, u0, u1, depthb, - t) && !t) - return true; - } - return t ? !t->isEmpty() : false; - } - } else { - if (depthb > 0) { - QBezier B[2]; - b.split(&B[0], &B[1]); - qreal umid = (u0 + u1)*0.5; - depthb--; - if (IntersectBB(a, B[0])) { - //fprintf(stderr, "\t 7 from %d\n", currentD); - if (RecursivelyIntersect(a, t0, t1, deptha, - B[0], u0, umid, depthb, - t) && !t) - return true; - } - if (IntersectBB(a, B[1])) { - //fprintf(stderr, "\t 8 from %d\n", currentD); - if (RecursivelyIntersect(a, t0, t1, deptha, - B[1], umid, u1, depthb, - t) && !t) - return true; - } - return t ? !t->isEmpty() : false; - } - else { - // Both segments are fully subdivided; now do line segments - qreal xlk = a.x4 - a.x1; - qreal ylk = a.y4 - a.y1; - qreal xnm = b.x4 - b.x1; - qreal ynm = b.y4 - b.y1; - qreal xmk = b.x1 - a.x1; - qreal ymk = b.y1 - a.y1; - qreal det = xnm * ylk - ynm * xlk; - if (1.0 + det == 1.0) { - return false; - } else { - qreal detinv = 1.0 / det; - qreal rs = (xnm * ymk - ynm *xmk) * detinv; - qreal rt = (xlk * ymk - ylk * xmk) * detinv; - if ((rs < 0.0) || (rs > 1.0) || (rt < 0.0) || (rt > 1.0)) - return false; - - if (t) { - const qreal alpha_a = t0 + rs * (t1 - t0); - const qreal alpha_b = u0 + rt * (u1 - u0); - - *t << qMakePair(alpha_a, alpha_b); - } - - return true; - } - } - } -} - -QVector< QPair<qreal, qreal> > QBezier::findIntersections(const QBezier &a, const QBezier &b) -{ - QVector< QPair<qreal, qreal> > v(2); - findIntersections(a, b, &v); - return v; -} - -bool QBezier::findIntersections(const QBezier &a, const QBezier &b, - QVector<QPair<qreal, qreal> > *t) -{ - if (IntersectBB(a, b)) { - QPointF la1(qFabs((a.x3 - a.x2) - (a.x2 - a.x1)), - qFabs((a.y3 - a.y2) - (a.y2 - a.y1))); - QPointF la2(qFabs((a.x4 - a.x3) - (a.x3 - a.x2)), - qFabs((a.y4 - a.y3) - (a.y3 - a.y2))); - QPointF la; - if (la1.x() > la2.x()) la.setX(la1.x()); else la.setX(la2.x()); - if (la1.y() > la2.y()) la.setY(la1.y()); else la.setY(la2.y()); - QPointF lb1(qFabs((b.x3 - b.x2) - (b.x2 - b.x1)), - qFabs((b.y3 - b.y2) - (b.y2 - b.y1))); - QPointF lb2(qFabs((b.x4 - b.x3) - (b.x3 - b.x2)), - qFabs((b.y4 - b.y3) - (b.y3 - b.y2))); - QPointF lb; - if (lb1.x() > lb2.x()) lb.setX(lb1.x()); else lb.setX(lb2.x()); - if (lb1.y() > lb2.y()) lb.setY(lb1.y()); else lb.setY(lb2.y()); - qreal l0; - if (la.x() > la.y()) - l0 = la.x(); - else - l0 = la.y(); - int ra; - if (l0 * 0.75 * M_SQRT2 + 1.0 == 1.0) - ra = 0; - else - ra = qCeil(log4(M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0)); - if (lb.x() > lb.y()) - l0 = lb.x(); - else - l0 = lb.y(); - int rb; - if (l0 * 0.75 * M_SQRT2 + 1.0 == 1.0) - rb = 0; - else - rb = qCeil(log4(M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0)); - - // if qreal is float then halve the number of subdivisions - if (sizeof(qreal) == 4) { - ra /= 2; - rb /= 2; - } - - return RecursivelyIntersect(a, 0., 1., ra, b, 0., 1., rb, t); - } - - //Don't sort here because it breaks the orders of corresponding - // intersections points. this way t's at the same locations correspond - // to the same intersection point. - //qSort(parameters[0].begin(), parameters[0].end(), qLess<qreal>()); - //qSort(parameters[1].begin(), parameters[1].end(), qLess<qreal>()); - - return false; -} - static inline void splitBezierAt(const QBezier &bez, qreal t, QBezier *left, QBezier *right) { @@ -920,42 +651,6 @@ static inline void splitBezierAt(const QBezier &bez, qreal t, right->y4 = bez.y4; } -QVector< QList<QBezier> > QBezier::splitAtIntersections(QBezier &b) -{ - QVector< QList<QBezier> > curves(2); - - QVector< QPair<qreal, qreal> > allInters = findIntersections(*this, b); - - QList<qreal> inters1; - QList<qreal> inters2; - - for (int i = 0; i < allInters.size(); ++i) { - inters1 << allInters[i].first; - inters2 << allInters[i].second; - } - - qSort(inters1.begin(), inters1.end(), qLess<qreal>()); - qSort(inters2.begin(), inters2.end(), qLess<qreal>()); - - Q_ASSERT(inters1.count() == inters2.count()); - - int i; - for (i = 0; i < inters1.count(); ++i) { - qreal t1 = inters1.at(i); - qreal t2 = inters2.at(i); - - QBezier curve1, curve2; - parameterSplitLeft(t1, &curve1); - b.parameterSplitLeft(t2, &curve2); - curves[0].append(curve1); - curves[0].append(curve2); - } - curves[0].append(*this); - curves[1].append(b); - - return curves; -} - qreal QBezier::length(qreal error) const { qreal length = 0.0; diff --git a/src/gui/painting/qbezier_p.h b/src/gui/painting/qbezier_p.h index f015ea8..846635f 100644 --- a/src/gui/painting/qbezier_p.h +++ b/src/gui/painting/qbezier_p.h @@ -111,16 +111,7 @@ public: int shifted(QBezier *curveSegments, int maxSegmets, qreal offset, float threshold) const; - QVector< QList<QBezier> > splitAtIntersections(QBezier &a); - QBezier bezierOnInterval(qreal t0, qreal t1) const; - - static QVector< QPair<qreal, qreal> > findIntersections(const QBezier &a, - const QBezier &b); - - static bool findIntersections(const QBezier &a, const QBezier &b, - QVector<QPair<qreal, qreal> > *t); - QBezier getSubRange(qreal t0, qreal t1) const; qreal x1, y1, x2, y2, x3, y3, x4, y4; diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 182cce9..96d547b 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -160,8 +160,7 @@ static void qt_cleanup_brush_pattern_image_cache() qt_brushPatternImageCache()->cleanup(); } -Q_GUI_EXPORT -QImage qt_imageForBrush(int brushStyle, bool invert) +Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert) { return qt_brushPatternImageCache()->getImage(brushStyle, invert); } diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index b440fce..bfa1136 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -674,6 +674,11 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int image_width = data->texture.width; int image_height = data->texture.height; + int image_x1 = data->texture.x1; + int image_y1 = data->texture.y1; + int image_x2 = data->texture.x2; + int image_y2 = data->texture.y2; + const qreal cx = x + 0.5; const qreal cy = y + 0.5; @@ -708,17 +713,17 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * y2 = y1 + 1; y2 %= image_height; } else { - if (x1 < 0) { - x2 = x1 = 0; - } else if (x1 >= image_width - 1) { - x2 = x1 = image_width - 1; + if (x1 < image_x1) { + x2 = x1 = image_x1; + } else if (x1 >= image_x2 - 1) { + x2 = x1 = image_x2 - 1; } else { x2 = x1 + 1; } - if (y1 < 0) { - y2 = y1 = 0; - } else if (y1 >= image_height - 1) { - y2 = y1 = image_height - 1; + if (y1 < image_y1) { + y2 = y1 = image_y1; + } else if (y1 >= image_y2 - 1) { + y2 = y1 = image_y2 - 1; } else { y2 = y1 + 1; } diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index f5b17ea..acf765c 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -69,6 +69,13 @@ QT_BEGIN_NAMESPACE +#if defined(Q_OS_MAC) && (defined(__ppc__) || defined(__ppc64__)) +#undef QT_HAVE_MMX +#undef QT_HAVE_SSE +#undef QT_HAVE_SSE2 +#undef QT_HAVE_3DNOW +#endif + #if defined(Q_CC_MSVC) && _MSCVER <= 1300 && !defined(Q_CC_INTEL) #define Q_STATIC_TEMPLATE_SPECIALIZATION static #else diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index e1156dc..3a4c94c 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -54,8 +54,8 @@ QT_BEGIN_NAMESPACE -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); extern void qt_format_text(const QFont &font, const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect, int tabstops, int* tabarray, int tabarraylen, @@ -312,6 +312,7 @@ int QPaintBuffer::processCommands(QPainter *painter, int begin, int end) const return depth; } +#ifndef QT_NO_DEBUG_STREAM QString QPaintBuffer::commandDescription(int command) const { QString desc; @@ -563,6 +564,7 @@ QString QPaintBuffer::commandDescription(int command) const return desc; } +#endif QRectF QPaintBuffer::boundingRect() const { diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h index 4576947..e4fe4bf 100644 --- a/src/gui/painting/qpaintbuffer_p.h +++ b/src/gui/painting/qpaintbuffer_p.h @@ -82,7 +82,9 @@ public: int frameStartIndex(int frame) const; int frameEndIndex(int frame) const; int processCommands(QPainter *painter, int begin, int end) const; +#ifndef QT_NO_DEBUG_STREAM QString commandDescription(int command) const; +#endif void setBoundingRect(const QRectF &rect); QRectF boundingRect() const; diff --git a/src/gui/painting/qpaintengine_alpha.cpp b/src/gui/painting/qpaintengine_alpha.cpp index 5a3c0cf..4b1c58d 100644 --- a/src/gui/painting/qpaintengine_alpha.cpp +++ b/src/gui/painting/qpaintengine_alpha.cpp @@ -93,8 +93,8 @@ bool QAlphaPaintEngine::begin(QPaintDevice *pdev) return true; } -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); bool QAlphaPaintEngine::end() { diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 03d0825..9148ac2 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -103,7 +103,7 @@ QT_BEGIN_NAMESPACE -extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp +Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp #define qreal_to_fixed_26_6(f) (int(f * 64)) #define qt_swap_int(x, y) { int tmp = (x); (x) = (y); (y) = tmp; } @@ -2552,7 +2552,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe int sr_t = qFloor(sr.top()); int sr_b = qCeil(sr.bottom()) - 1; - if (!s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { + if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { // as fillRect will apply the aliased coordinate delta we need to // subtract it here as we don't use it for image drawing QTransform old = s->matrix; @@ -4996,7 +4996,7 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe) clip = pe ? pe->d_func()->clip() : 0; } -extern QImage qt_imageForBrush(int brushStyle, bool invert); +Q_GUI_EXPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode) { diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 990e3c4..a78cafb 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -380,7 +380,7 @@ QPainterState *QPaintEngineEx::createState(QPainterState *orig) const return new QPainterState(orig); } -extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp +Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) { @@ -974,6 +974,9 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/) { + if (pixmap.isNull()) + return; + qreal oldOpacity = state()->opacity; QTransform oldTransform = state()->matrix; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index f78de34..f5a698e 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1914,7 +1914,7 @@ static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF case QPainterPath::MoveToElement: if (i > 0 - && qFuzzyCompare(last_pt.x(), last_start.y()) + && qFuzzyCompare(last_pt.x(), last_start.x()) && qFuzzyCompare(last_pt.y(), last_start.y()) && qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(), last_start.x(), last_start.y(), rect)) @@ -3167,6 +3167,8 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) Set operations on paths will treat the paths as areas. Non-closed paths will be treated as implicitly closed. + Bezier curves may be flattened to line segments due to numerical instability of + doing bezier curve intersections. \sa intersected(), subtracted() */ @@ -3182,6 +3184,8 @@ QPainterPath QPainterPath::united(const QPainterPath &p) const \since 4.3 Returns a path which is the intersection of this path's fill area and \a p's fill area. + Bezier curves may be flattened to line segments due to numerical instability of + doing bezier curve intersections. */ QPainterPath QPainterPath::intersected(const QPainterPath &p) const { @@ -3198,7 +3202,8 @@ QPainterPath QPainterPath::intersected(const QPainterPath &p) const Set operations on paths will treat the paths as areas. Non-closed paths will be treated as implicitly closed. - + Bezier curves may be flattened to line segments due to numerical instability of + doing bezier curve intersections. */ QPainterPath QPainterPath::subtracted(const QPainterPath &p) const { @@ -3227,6 +3232,8 @@ QPainterPath QPainterPath::subtractedInverted(const QPainterPath &p) const Returns a simplified version of this path. This implies merging all subpaths that intersect, and returning a path containing no intersecting edges. Consecutive parallel lines will also be merged. The simplified path will always use the default fill rule, Qt::OddEvenFill. + Bezier curves may be flattened to line segments due to numerical instability of + doing bezier curve intersections. */ QPainterPath QPainterPath::simplified() const { diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 00e74ba..c910024 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -43,6 +43,7 @@ #include <private/qbezier_p.h> #include <private/qdatabuffer_p.h> +#include <private/qnumeric_p.h> #include <qmath.h> /** @@ -105,22 +106,9 @@ public: bool hasIntersections(const QPathSegments &a, const QPathSegments &b) const; private: - void intersectBeziers(const QBezier &one, const QBezier &two, QVector<QPair<qreal, qreal> > &t, QDataBuffer<QIntersection> &intersections); - void intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections); - - bool beziersIntersect(const QBezier &one, const QBezier &two) const; bool linesIntersect(const QLineF &a, const QLineF &b) const; }; -bool QIntersectionFinder::beziersIntersect(const QBezier &one, const QBezier &two) const -{ - return (comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2()) - && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4())) - || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3()) - && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1())) - || QBezier::findIntersections(one, two, 0); -} - bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const { const QPointF p1 = a.p1(); @@ -174,11 +162,6 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const return false; } - // if the lines are not parallel and share a common end point, then they - // don't intersect - if (p1_equals_q1 || p1_equals_q2 || p2_equals_q1 || p2_equals_q2) - return false; - const qreal invPar = 1 / par; const qreal tp = (qDelta.y() * (q1.x() - p1.x()) - @@ -193,49 +176,223 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const return tq >= 0 && tq <= 1; } -void QIntersectionFinder::intersectBeziers(const QBezier &one, const QBezier &two, QVector<QPair<qreal, qreal> > &t, QDataBuffer<QIntersection> &intersections) +bool QIntersectionFinder::hasIntersections(const QPathSegments &a, const QPathSegments &b) const { - if ((comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2()) - && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4())) - || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3()) - && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1()))) { + if (a.segments() == 0 || b.segments() == 0) + return false; - return; + const QRectF &rb0 = b.elementBounds(0); + + qreal minX = rb0.left(); + qreal minY = rb0.top(); + qreal maxX = rb0.right(); + qreal maxY = rb0.bottom(); + + for (int i = 1; i < b.segments(); ++i) { + const QRectF &r = b.elementBounds(i); + minX = qMin(minX, r.left()); + minY = qMin(minY, r.top()); + maxX = qMax(maxX, r.right()); + maxY = qMax(maxY, r.bottom()); } - t.clear(); + QRectF rb(minX, minY, maxX - minX, maxY - minY); - if (!QBezier::findIntersections(one, two, &t)) - return; + for (int i = 0; i < a.segments(); ++i) { + const QRectF &r1 = a.elementBounds(i); - int count = t.size(); - - for (int i = 0; i < count; ++i) { - qreal alpha_p = t.at(i).first; - qreal alpha_q = t.at(i).second; - - QPointF pt; - if (qFuzzyIsNull(alpha_p)) { - pt = one.pt1(); - } else if (qFuzzyIsNull(alpha_p - 1)) { - pt = one.pt4(); - } else if (qFuzzyIsNull(alpha_q)) { - pt = two.pt1(); - } else if (qFuzzyIsNull(alpha_q - 1)) { - pt = two.pt4(); - } else { - pt = one.pointAt(alpha_p); + if (r1.left() > rb.right() || rb.left() > r1.right()) + continue; + if (r1.top() > rb.bottom() || rb.top() > r1.bottom()) + continue; + + for (int j = 0; j < b.segments(); ++j) { + const QRectF &r2 = b.elementBounds(j); + + if (r1.left() > r2.right() || r2.left() > r1.right()) + continue; + if (r1.top() > r2.bottom() || r2.top() > r1.bottom()) + continue; + + if (linesIntersect(a.lineAt(i), b.lineAt(j))) + return true; } + } - QIntersection intersection; - intersection.alphaA = alpha_p; - intersection.alphaB = alpha_q; - intersection.pos = pt; - intersections.add(intersection); + return false; +} + +namespace { +struct TreeNode +{ + qreal splitLeft; + qreal splitRight; + bool leaf; + + int lowestLeftIndex; + int lowestRightIndex; + + union { + struct { + int first; + int last; + } interval; + struct { + int left; + int right; + } children; + } index; +}; + +struct RectF +{ + qreal x1; + qreal y1; + qreal x2; + qreal y2; +}; + +class SegmentTree +{ +public: + SegmentTree(QPathSegments &segments); + + QRectF boundingRect() const; + + void produceIntersections(int segment); + +private: + TreeNode buildTree(int first, int last, int depth, const RectF &bounds); + + void produceIntersectionsLeaf(const TreeNode &node, int segment); + void produceIntersections(const TreeNode &node, int segment, const RectF &segmentBounds, const RectF &nodeBounds, int axis); + void intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections); + + QPathSegments &m_segments; + QVector<int> m_index; + + RectF m_bounds; + + QVector<TreeNode> m_tree; + QDataBuffer<QIntersection> m_intersections; +}; + +SegmentTree::SegmentTree(QPathSegments &segments) + : m_segments(segments) +{ + m_bounds.x1 = qt_inf(); + m_bounds.y1 = qt_inf(); + m_bounds.x2 = -qt_inf(); + m_bounds.y2 = -qt_inf(); + + m_index.resize(m_segments.segments()); + + for (int i = 0; i < m_index.size(); ++i) { + m_index[i] = i; + + const QRectF &segmentBounds = m_segments.elementBounds(i); + + if (segmentBounds.left() < m_bounds.x1) + m_bounds.x1 = segmentBounds.left(); + if (segmentBounds.top() < m_bounds.y1) + m_bounds.y1 = segmentBounds.top(); + if (segmentBounds.right() > m_bounds.x2) + m_bounds.x2 = segmentBounds.right(); + if (segmentBounds.bottom() > m_bounds.y2) + m_bounds.y2 = segmentBounds.bottom(); } + + m_tree.resize(1); + + TreeNode root = buildTree(0, m_index.size(), 0, m_bounds); + m_tree[0] = root; +} + +QRectF SegmentTree::boundingRect() const +{ + return QRectF(QPointF(m_bounds.x1, m_bounds.y1), + QPointF(m_bounds.x2, m_bounds.y2)); +} + +static inline qreal coordinate(const QPointF &pos, int axis) +{ + return axis == 0 ? pos.x() : pos.y(); } -void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections) +TreeNode SegmentTree::buildTree(int first, int last, int depth, const RectF &bounds) +{ + if (depth >= 24 || (last - first) <= 10) { + TreeNode node; + node.leaf = true; + node.index.interval.first = first; + node.index.interval.last = last; + + return node; + } + + int splitAxis = (depth & 1); + + TreeNode node; + node.leaf = false; + + qreal split = 0.5f * ((&bounds.x1)[splitAxis] + (&bounds.x2)[splitAxis]); + + node.splitLeft = (&bounds.x1)[splitAxis]; + node.splitRight = (&bounds.x2)[splitAxis]; + + node.lowestLeftIndex = INT_MAX; + node.lowestRightIndex = INT_MAX; + + const int treeSize = m_tree.size(); + + node.index.children.left = treeSize; + node.index.children.right = treeSize + 1; + + m_tree.resize(treeSize + 2); + + int l = first; + int r = last - 1; + + // partition into left and right sets + while (l <= r) { + const int index = m_index.at(l); + const QRectF &segmentBounds = m_segments.elementBounds(index); + + qreal lowCoordinate = coordinate(segmentBounds.topLeft(), splitAxis); + + if (coordinate(segmentBounds.center(), splitAxis) < split) { + qreal highCoordinate = coordinate(segmentBounds.bottomRight(), splitAxis); + if (highCoordinate > node.splitLeft) + node.splitLeft = highCoordinate; + if (index < node.lowestLeftIndex) + node.lowestLeftIndex = index; + ++l; + } else { + if (lowCoordinate < node.splitRight) + node.splitRight = lowCoordinate; + if (index < node.lowestRightIndex) + node.lowestRightIndex = index; + qSwap(m_index[l], m_index[r]); + --r; + } + } + + RectF lbounds = bounds; + (&lbounds.x2)[splitAxis] = node.splitLeft; + + RectF rbounds = bounds; + (&rbounds.x1)[splitAxis] = node.splitRight; + + TreeNode left = buildTree(first, l, depth + 1, lbounds); + m_tree[node.index.children.left] = left; + + TreeNode right = buildTree(l, last, depth + 1, rbounds); + m_tree[node.index.children.right] = right; + + return node; +} + +void SegmentTree::intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections) { const QPointF p1 = a.p1(); const QPointF p2 = a.p2(); @@ -357,149 +514,86 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData intersections.add(intersection); } -static const QBezier bezierFromLine(const QLineF &line) +void SegmentTree::produceIntersections(int segment) { - const QPointF p1 = line.p1(); - const QPointF p2 = line.p2(); - const QPointF delta = (p2 - p1) / 3; - return QBezier::fromPoints(p1, p1 + delta, p1 + 2 * delta, p2); -} - -bool QIntersectionFinder::hasIntersections(const QPathSegments &a, const QPathSegments &b) const -{ - QBezier tempA; - QBezier tempB; - - if (a.segments() == 0 || b.segments() == 0) - return false; + const QRectF &segmentBounds = m_segments.elementBounds(segment); - const QRectF &rb0 = b.elementBounds(0); - - qreal minX = rb0.left(); - qreal minY = rb0.top(); - qreal maxX = rb0.right(); - qreal maxY = rb0.bottom(); + RectF sbounds; + sbounds.x1 = segmentBounds.left(); + sbounds.y1 = segmentBounds.top(); + sbounds.x2 = segmentBounds.right(); + sbounds.y2 = segmentBounds.bottom(); - for (int i = 1; i < b.segments(); ++i) { - const QRectF &r = b.elementBounds(i); - minX = qMin(minX, r.left()); - minY = qMin(minY, r.top()); - maxX = qMax(maxX, r.right()); - maxY = qMax(maxY, r.bottom()); - } + produceIntersections(m_tree.at(0), segment, sbounds, m_bounds, 0); +} - QRectF rb(minX, minY, maxX - minX, maxY - minY); +void SegmentTree::produceIntersectionsLeaf(const TreeNode &node, int segment) +{ + const QRectF &r1 = m_segments.elementBounds(segment); + const QLineF lineA = m_segments.lineAt(segment); - for (int i = 0; i < a.segments(); ++i) { - const QBezier *bezierA = a.bezierAt(i); - bool isBezierA = bezierA != 0; + for (int i = node.index.interval.first; i < node.index.interval.last; ++i) { + const int other = m_index.at(i); + if (other >= segment) + continue; - const QRectF &r1 = a.elementBounds(i); + const QRectF &r2 = m_segments.elementBounds(other); - if (r1.left() > rb.right() || rb.left() > r1.right()) + if (r1.left() > r2.right() || r2.left() > r1.right()) continue; - if (r1.top() > rb.bottom() || rb.top() > r1.bottom()) + if (r1.top() > r2.bottom() || r2.top() > r1.bottom()) continue; - for (int j = 0; j < b.segments(); ++j) { - const QRectF &r2 = b.elementBounds(j); + m_intersections.reset(); - if (r1.left() > r2.right() || r2.left() > r1.right()) - continue; - if (r1.top() > r2.bottom() || r2.top() > r1.bottom()) - continue; + const QLineF lineB = m_segments.lineAt(other); - bool isBezierB = b.bezierAt(j) != 0; + intersectLines(lineA, lineB, m_intersections); - if (isBezierA || isBezierB) { - const QBezier *bezierB; - if (isBezierB) { - bezierB = b.bezierAt(j); - } else { - tempB = bezierFromLine(b.lineAt(j)); - bezierB = &tempB; - } + for (int k = 0; k < m_intersections.size(); ++k) { + QPathSegments::Intersection i_isect, j_isect; + i_isect.vertex = j_isect.vertex = m_segments.addPoint(m_intersections.at(k).pos); - if (!bezierA) { - tempA = bezierFromLine(a.lineAt(i)); - bezierA = &tempA; - } + i_isect.t = m_intersections.at(k).alphaA; + j_isect.t = m_intersections.at(k).alphaB; - if (beziersIntersect(*bezierA, *bezierB)) - return true; - } else { - if (linesIntersect(a.lineAt(i), b.lineAt(j))) - return true; - } + i_isect.next = 0; + j_isect.next = 0; + + m_segments.addIntersection(segment, i_isect); + m_segments.addIntersection(other, j_isect); } } - - return false; } -void QIntersectionFinder::produceIntersections(QPathSegments &segments) +void SegmentTree::produceIntersections(const TreeNode &node, int segment, const RectF &segmentBounds, const RectF &nodeBounds, int axis) { - QBezier tempA; - QBezier tempB; - - QVector<QPair<qreal, qreal> > t; - QDataBuffer<QIntersection> intersections; - - for (int i = 0; i < segments.segments(); ++i) { - const QBezier *bezierA = segments.bezierAt(i); - bool isBezierA = bezierA != 0; - - const QRectF &r1 = segments.elementBounds(i); - - for (int j = 0; j < i; ++j) { - const QRectF &r2 = segments.elementBounds(j); - - if (r1.left() > r2.right() || r2.left() > r1.right()) - continue; - if (r1.top() > r2.bottom() || r2.top() > r1.bottom()) - continue; + if (node.leaf) { + produceIntersectionsLeaf(node, segment); + return; + } - intersections.reset(); + RectF lbounds = nodeBounds; + (&lbounds.x2)[axis] = node.splitLeft; - bool isBezierB = segments.bezierAt(j) != 0; + RectF rbounds = nodeBounds; + (&rbounds.x1)[axis] = node.splitRight; - if (isBezierA || isBezierB) { - const QBezier *bezierB; - if (isBezierB) { - bezierB = segments.bezierAt(j); - } else { - tempB = bezierFromLine(segments.lineAt(j)); - bezierB = &tempB; - } + if (segment > node.lowestLeftIndex && (&segmentBounds.x1)[axis] <= node.splitLeft) + produceIntersections(m_tree.at(node.index.children.left), segment, segmentBounds, lbounds, !axis); - if (!bezierA) { - tempA = bezierFromLine(segments.lineAt(i)); - bezierA = &tempA; - } - - intersectBeziers(*bezierA, *bezierB, t, intersections); - } else { - const QLineF lineA = segments.lineAt(i); - const QLineF lineB = segments.lineAt(j); - - intersectLines(lineA, lineB, intersections); - } - - for (int k = 0; k < intersections.size(); ++k) { - QPathSegments::Intersection i_isect, j_isect; - i_isect.vertex = j_isect.vertex = segments.addPoint(intersections.at(k).pos); + if (segment > node.lowestRightIndex && (&segmentBounds.x2)[axis] >= node.splitRight) + produceIntersections(m_tree.at(node.index.children.right), segment, segmentBounds, rbounds, !axis); +} - i_isect.t = intersections.at(k).alphaA; - j_isect.t = intersections.at(k).alphaB; +} - i_isect.next = 0; - j_isect.next = 0; +void QIntersectionFinder::produceIntersections(QPathSegments &segments) +{ + SegmentTree tree(segments); - segments.addIntersection(i, i_isect); - segments.addIntersection(j, j_isect); - } - } - } + for (int i = 0; i < segments.segments(); ++i) + tree.produceIntersections(i); } class QKdPointTree @@ -731,53 +825,34 @@ void QWingedEdge::intersectAndAdd() qSort(intersections.data(), intersections.data() + intersections.size()); - const QBezier *bezier = m_segments.bezierAt(i); - if (bezier) { - int first = m_segments.segmentAt(i).va; - int second = m_segments.segmentAt(i).vb; - - qreal alpha = 0.0; - int last = first; - for (int j = 0; j < intersections.size(); ++j) { - const QPathSegments::Intersection &isect = intersections.at(j); - - addBezierEdge(bezier, last, isect.vertex, alpha, isect.t, pathId); - - alpha = isect.t; - last = isect.vertex; - } - - addBezierEdge(bezier, last, second, alpha, 1.0, pathId); - } else { - int first = m_segments.segmentAt(i).va; - int second = m_segments.segmentAt(i).vb; - - int last = first; - for (int j = 0; j < intersections.size(); ++j) { - const QPathSegments::Intersection &isect = intersections.at(j); - - QPathEdge *ep = edge(addEdge(last, isect.vertex)); - - if (ep) { - const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1; - if (pathId == 0) - ep->windingA += dir; - else - ep->windingB += dir; - } + int first = m_segments.segmentAt(i).va; + int second = m_segments.segmentAt(i).vb; - last = isect.vertex; - } + int last = first; + for (int j = 0; j < intersections.size(); ++j) { + const QPathSegments::Intersection &isect = intersections.at(j); - QPathEdge *ep = edge(addEdge(last, second)); + QPathEdge *ep = edge(addEdge(last, isect.vertex)); if (ep) { - const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1; + const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1; if (pathId == 0) ep->windingA += dir; else ep->windingB += dir; } + + last = isect.vertex; + } + + QPathEdge *ep = edge(addEdge(last, second)); + + if (ep) { + const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1; + if (pathId == 0) + ep->windingA += dir; + else + ep->windingB += dir; } } } @@ -832,7 +907,6 @@ static bool isLine(const QBezier &bezier) void QPathSegments::setPath(const QPainterPath &path) { m_points.reset(); - m_beziers.reset(); m_intersections.reset(); m_segments.reset(); @@ -879,8 +953,25 @@ void QPathSegments::addPath(const QPainterPath &path) if (isLine(bezier)) { m_segments << Segment(m_pathId, last, current); } else { - m_segments << Segment(m_pathId, last, current, m_beziers.size()); - m_beziers << bezier; + QRectF bounds = bezier.bounds(); + + // threshold based on similar algorithm as in qtriangulatingstroker.cpp + int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * (2 * qreal(3.14) / 6)); + + if (threshold < 3) threshold = 3; + qreal one_over_threshold_minus_1 = qreal(1) / (threshold - 1); + + for (int t = 1; t < threshold - 1; ++t) { + currentPoint = bezier.pointAt(t * one_over_threshold_minus_1); + + int index = m_points.size(); + m_segments << Segment(m_pathId, last, index); + last = index; + + m_points << currentPoint; + } + + m_segments << Segment(m_pathId, last, current); } } last = current; @@ -896,24 +987,19 @@ void QPathSegments::addPath(const QPainterPath &path) m_segments << Segment(m_pathId, last, lastMoveTo); for (int i = firstSegment; i < m_segments.size(); ++i) { - const QBezier *bezier = bezierAt(i); - if (bezier) { - m_segments.at(i).bounds = bezier->bounds(); - } else { - const QLineF line = lineAt(i); + const QLineF line = lineAt(i); - qreal x1 = line.p1().x(); - qreal y1 = line.p1().y(); - qreal x2 = line.p2().x(); - qreal y2 = line.p2().y(); + qreal x1 = line.p1().x(); + qreal y1 = line.p1().y(); + qreal x2 = line.p2().x(); + qreal y2 = line.p2().y(); - if (x2 < x1) - qSwap(x1, x2); - if (y2 < y1) - qSwap(y1, y2); + if (x2 < x1) + qSwap(x1, x2); + if (y2 < y1) + qSwap(y1, y2); - m_segments.at(i).bounds = QRectF(x1, y1, x2 - x1, y2 - y1); - } + m_segments.at(i).bounds = QRectF(x1, y1, x2 - x1, y2 - y1); } ++m_pathId; @@ -948,28 +1034,17 @@ static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei) const QPathEdge *ep = list.edge(ei); Q_ASSERT(ep); - qreal t; qreal sign; if (ep->first == vi) { - t = ep->t0; sign = 1; } else { - t = ep->t1; sign = -1; } - QPointF normal; - if (ep->bezier) { - normal = ep->bezier->derivedAt(t); - - if (qFuzzyIsNull(normal.x()) && qFuzzyIsNull(normal.y())) - normal = ep->bezier->secondDerivedAt(t); - } else { - const QPointF a = *list.vertex(ep->first); - const QPointF b = *list.vertex(ep->second); - normal = b - a; - } + const QPointF a = *list.vertex(ep->first); + const QPointF b = *list.vertex(ep->second); + QPointF normal = b - a; return normalize(sign * normal); } @@ -979,83 +1054,9 @@ static inline QPointF midPoint(const QWingedEdge &list, int ei) const QPathEdge *ep = list.edge(ei); Q_ASSERT(ep); - if (ep->bezier) { - return ep->bezier->pointAt(0.5 * (ep->t0 + ep->t1)); - } else { - const QPointF a = *list.vertex(ep->first); - const QPointF b = *list.vertex(ep->second); - return a + 0.5 * (b - a); - } -} - -static QBezier transform(const QBezier &bezier, const QPointF &xAxis, const QPointF &yAxis, const QPointF &origin) -{ - QPointF points[4] = { - bezier.pt1(), - bezier.pt2(), - bezier.pt3(), - bezier.pt4() - }; - - for (int i = 0; i < 4; ++i) { - const QPointF p = points[i] - origin; - - points[i].rx() = dot(xAxis, p); - points[i].ry() = dot(yAxis, p); - } - - return QBezier::fromPoints(points[0], points[1], points[2], points[3]); -} - -static bool isLeftOf(const QWingedEdge &list, int vi, int ai, int bi) -{ - const QPathEdge *ap = list.edge(ai); - const QPathEdge *bp = list.edge(bi); - - Q_ASSERT(ap); - Q_ASSERT(bp); - - if (!(ap->bezier || bp->bezier)) - return false; - - const QPointF tangent = tangentAt(list, vi, ai); - const QPointF normal(tangent.y(), -tangent.x()); - - const QPointF origin = *list.vertex(vi); - - const QPointF dpA = midPoint(list, ai) - origin; - const QPointF dpB = midPoint(list, bi) - origin; - - qreal xA = dot(normal, dpA); - qreal xB = dot(normal, dpB); - - if (xA <= 0 && xB >= 0) - return true; - - if (xA >= 0 && xB <= 0) - return false; - - if (!ap->bezier) - return xB > 0; - - if (!bp->bezier) - return xA < 0; - - // both are beziers on the same side of the tangent - - // transform the beziers into the local coordinate system - // such that positive y is along the tangent, and positive x is along the normal - - QBezier bezierA = transform(*ap->bezier, normal, tangent, origin); - QBezier bezierB = transform(*bp->bezier, normal, tangent, origin); - - qreal y = qMin(bezierA.pointAt(0.5 * (ap->t0 + ap->t1)).y(), - bezierB.pointAt(0.5 * (bp->t0 + bp->t1)).y()); - - xA = bezierA.pointAt(bezierA.tForY(ap->t0, ap->t1, y)).x(); - xB = bezierB.pointAt(bezierB.tForY(bp->t0, bp->t1, y)).x(); - - return xA < xB; + const QPointF a = *list.vertex(ep->first); + const QPointF b = *list.vertex(ep->second); + return a + 0.5 * (b - a); } QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const @@ -1084,7 +1085,6 @@ QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const status.flip(); Q_ASSERT(edge(status.edge)->vertex(status.direction) == vi); - qreal d2 = delta(vi, ei, status.edge); #ifdef QDEBUG_CLIPPER @@ -1092,8 +1092,7 @@ QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const qDebug() << "Delta to edge" << status.edge << d2 << ", angles: " << op->angle << op->invAngle; #endif - if (!(qFuzzyIsNull(d2) && isLeftOf(*this, vi, status.edge, ei)) - && (d2 < d || (qFuzzyCompare(d2, d) && isLeftOf(*this, vi, status.edge, position)))) { + if (d2 < d) { position = status.edge; d = d2; } @@ -1210,15 +1209,15 @@ static qreal computeAngle(const QPointF &v) #endif } -int QWingedEdge::addEdge(const QPointF &a, const QPointF &b, const QBezier *bezier, qreal t0, qreal t1) +int QWingedEdge::addEdge(const QPointF &a, const QPointF &b) { int fi = insert(a); int si = insert(b); - return addEdge(fi, si, bezier, t0, t1); + return addEdge(fi, si); } -int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal t1) +int QWingedEdge::addEdge(int fi, int si) { if (fi == si) return -1; @@ -1236,29 +1235,11 @@ int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal QPathEdge *ep = edge(ei); - ep->bezier = bezier; - ep->t0 = t0; - ep->t1 = t1; - - if (bezier) { - QPointF aTangent = bezier->derivedAt(t0); - QPointF bTangent = -bezier->derivedAt(t1); - - if (qFuzzyIsNull(aTangent.x()) && qFuzzyIsNull(aTangent.y())) - aTangent = bezier->secondDerivedAt(t0); - - if (qFuzzyIsNull(bTangent.x()) && qFuzzyIsNull(bTangent.y())) - bTangent = bezier->secondDerivedAt(t1); - - ep->angle = computeAngle(aTangent); - ep->invAngle = computeAngle(bTangent); - } else { - const QPointF tangent = QPointF(*sp) - QPointF(*fp); - ep->angle = computeAngle(tangent); - ep->invAngle = ep->angle + 64; - if (ep->invAngle >= 128) - ep->invAngle -= 128; - } + const QPointF tangent = QPointF(*sp) - QPointF(*fp); + ep->angle = computeAngle(tangent); + ep->invAngle = ep->angle + 64; + if (ep->invAngle >= 128) + ep->invAngle -= 128; QPathVertex *vertices[2] = { fp, sp }; QPathEdge::Direction dirs[2] = { QPathEdge::Backward, QPathEdge::Forward }; @@ -1313,74 +1294,6 @@ int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal return ei; } -void QWingedEdge::addBezierEdge(const QBezier *bezier, int vertexA, int vertexB, qreal alphaA, qreal alphaB, int path) -{ - if (qFuzzyCompare(alphaA, alphaB)) - return; - - qreal alphaMid = (alphaA + alphaB) * 0.5; - - qreal s0 = 0; - qreal s1 = 1; - int count = bezier->stationaryYPoints(s0, s1); - - m_splitPoints.clear(); - m_splitPoints << alphaA; - m_splitPoints << alphaMid; - m_splitPoints << alphaB; - - if (count > 0 && !qFuzzyCompare(s0, alphaA) && !qFuzzyCompare(s0, alphaMid) && !qFuzzyCompare(s0, alphaB) && s0 > alphaA && s0 < alphaB) - m_splitPoints << s0; - - if (count > 1 && !qFuzzyCompare(s1, alphaA) && !qFuzzyCompare(s1, alphaMid) && !qFuzzyCompare(s1, alphaB) && s1 > alphaA && s1 < alphaB) - m_splitPoints << s1; - - if (count > 0) - qSort(m_splitPoints.begin(), m_splitPoints.end()); - - int last = vertexA; - for (int i = 0; i < m_splitPoints.size() - 1; ++i) { - const qreal t0 = m_splitPoints[i]; - const qreal t1 = m_splitPoints[i+1]; - - int current; - if ((i + 1) == (m_splitPoints.size() - 1)) { - current = vertexB; - } else { - current = insert(bezier->pointAt(t1)); - } - - QPathEdge *ep = edge(addEdge(last, current, bezier, t0, t1)); - - if (ep) { - const int dir = m_vertices.at(last).y < m_vertices.at(current).y ? 1 : -1; - if (path == 0) - ep->windingA += dir; - else - ep->windingB += dir; - } - - last = current; - } -} - -void QWingedEdge::addBezierEdge(const QBezier *bezier, const QPointF &a, const QPointF &b, qreal alphaA, qreal alphaB, int path) -{ - if (qFuzzyCompare(alphaA, alphaB)) - return; - - if (comparePoints(a, b)) { - int v = insert(a); - - addBezierEdge(bezier, v, v, alphaA, alphaB, path); - } else { - int va = insert(a); - int vb = insert(b); - - addBezierEdge(bezier, va, vb, alphaA, alphaB, path); - } -} - int QWingedEdge::insert(const QPathVertex &vertex) { if (!m_vertices.isEmpty()) { @@ -1429,37 +1342,12 @@ static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge status.traversal = traversal; status.direction = QPathEdge::Forward; - const QBezier *bezier = 0; - qreal t0 = 1; - qreal t1 = 0; - bool forward = true; - path.moveTo(*list.vertex(list.edge(edge)->first)); do { const QPathEdge *ep = list.edge(status.edge); - if (ep->bezier != bezier || (bezier && t0 != ep->t1 && t1 != ep->t0)) { - if (bezier) { - QBezier sub = bezier->bezierOnInterval(t0, t1); - - if (forward) - path.cubicTo(sub.pt2(), sub.pt3(), sub.pt4()); - else - path.cubicTo(sub.pt3(), sub.pt2(), sub.pt1()); - } - - bezier = ep->bezier; - t0 = 1; - t1 = 0; - forward = status.direction == QPathEdge::Forward; - } - - if (ep->bezier) { - t0 = qMin(t0, ep->t0); - t1 = qMax(t1, ep->t1); - } else - addLineTo(path, *list.vertex(ep->vertex(status.direction))); + addLineTo(path, *list.vertex(ep->vertex(status.direction))); if (status.traversal == QPathEdge::LeftTraversal) ep->flag &= ~16; @@ -1468,14 +1356,6 @@ static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge status = list.next(status); } while (status.edge != edge); - - if (bezier) { - QBezier sub = bezier->bezierOnInterval(t0, t1); - if (forward) - path.cubicTo(sub.pt2(), sub.pt3(), sub.pt4()); - else - path.cubicTo(sub.pt3(), sub.pt2(), sub.pt1()); - } } void QWingedEdge::simplify() @@ -1937,25 +1817,10 @@ bool QWingedEdge::isInside(qreal x, qreal y) const QPointF b = *vertex(ep->second); if ((a.y() < y && b.y() > y) || (a.y() > y && b.y() < y)) { - if (ep->bezier) { - qreal maxX = qMax(a.x(), qMax(b.x(), qMax(ep->bezier->x2, ep->bezier->x3))); - qreal minX = qMin(a.x(), qMin(b.x(), qMin(ep->bezier->x2, ep->bezier->x3))); - - if (minX > x) { - winding += w; - } else if (maxX > x) { - const qreal t = ep->bezier->tForY(ep->t0, ep->t1, y); - const qreal intersection = ep->bezier->pointAt(t).x(); - - if (intersection > x) - winding += w; - } - } else { - qreal intersectionX = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y()); + qreal intersectionX = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y()); - if (intersectionX > x) - winding += w; - } + if (intersectionX > x) + winding += w; } } @@ -1971,17 +1836,9 @@ static QVector<QCrossingEdge> findCrossings(const QWingedEdge &list, qreal y) QPointF b = *list.vertex(edge->second); if ((a.y() < y && b.y() > y) || (a.y() > y && b.y() < y)) { - if (edge->bezier) { - const qreal t = edge->bezier->tForY(edge->t0, edge->t1, y); - const qreal intersection = edge->bezier->pointAt(t).x(); - - const QCrossingEdge edge = { i, intersection }; - crossings << edge; - } else { - const qreal intersection = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y()); - const QCrossingEdge edge = { i, intersection }; - crossings << edge; - } + const qreal intersection = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y()); + const QCrossingEdge edge = { i, intersection }; + crossings << edge; } } return crossings; diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h index b42dc1d..7962400 100644 --- a/src/gui/painting/qpathclipper_p.h +++ b/src/gui/painting/qpathclipper_p.h @@ -151,10 +151,6 @@ public: qreal angle; qreal invAngle; - const QBezier *bezier; - qreal t0; - qreal t1; - int next(Traversal traversal, Direction direction) const; void setNext(Traversal traversal, Direction direction, int next); @@ -182,9 +178,8 @@ public: }; struct Segment { - Segment(int pathId, int vertexA, int vertexB, int bezierIndex = -1) + Segment(int pathId, int vertexA, int vertexB) : path(pathId) - , bezier(bezierIndex) , va(vertexA) , vb(vertexB) , intersection(-1) @@ -192,7 +187,6 @@ public: } int path; - int bezier; // vertices int va; @@ -216,7 +210,6 @@ public: const Segment &segmentAt(int index) const; const QLineF lineAt(int index) const; - const QBezier *bezierAt(int index) const; const QRectF &elementBounds(int index) const; int pathId(int index) const; @@ -231,7 +224,6 @@ public: private: QDataBuffer<QPointF> m_points; QDataBuffer<Segment> m_segments; - QDataBuffer<QBezier> m_beziers; QDataBuffer<Intersection> m_intersections; int m_pathId; @@ -272,8 +264,8 @@ public: TraversalStatus next(const TraversalStatus &status) const; - int addEdge(const QPointF &a, const QPointF &b, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1); - int addEdge(int vertexA, int vertexB, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1); + int addEdge(const QPointF &a, const QPointF &b); + int addEdge(int vertexA, int vertexB); bool isInside(qreal x, qreal y) const; @@ -285,11 +277,7 @@ private: void printNode(int i, FILE *handle); - QBezier bezierFromIndex(int index) const; - void removeEdge(int ei); - void addBezierEdge(const QBezier *bezier, const QPointF &a, const QPointF &b, qreal alphaA, qreal alphaB, int path); - void addBezierEdge(const QBezier *bezier, int vertexA, int vertexB, qreal alphaA, qreal alphaB, int path); int insert(const QPathVertex &vertex); TraversalStatus findInsertStatus(int vertex, int edge) const; @@ -312,9 +300,6 @@ inline QPathEdge::QPathEdge(int a, int b) , second(b) , angle(0) , invAngle(0) - , bezier(0) - , t0(0) - , t1(0) { m_next[0][0] = -1; m_next[1][0] = -1; @@ -396,15 +381,6 @@ inline const QLineF QPathSegments::lineAt(int index) const return QLineF(m_points.at(segment.va), m_points.at(segment.vb)); } -inline const QBezier *QPathSegments::bezierAt(int index) const -{ - const Segment &segment = m_segments.at(index); - if (segment.bezier >= 0) - return &m_beziers.at(segment.bezier); - else - return 0; -} - inline const QRectF &QPathSegments::elementBounds(int index) const { return m_segments.at(index).bounds; diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index dcf745f..44049c0 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE -extern int qt_defaultDpi(); +Q_GUI_EXPORT extern int qt_defaultDpi(); #ifndef QT_NO_PRINTER diff --git a/src/gui/painting/qprintengine_mac.mm b/src/gui/painting/qprintengine_mac.mm index 3d5d1d5..a548225 100644 --- a/src/gui/painting/qprintengine_mac.mm +++ b/src/gui/painting/qprintengine_mac.mm @@ -114,8 +114,11 @@ bool QMacPrintEngine::end() Q_D(QMacPrintEngine); if (d->state == QPrinter::Aborted) return true; // I was just here a function call ago :) - if(d->paintEngine->type() == QPaintEngine::CoreGraphics) + if(d->paintEngine->type() == QPaintEngine::CoreGraphics) { + // We dont need the paint engine to call restoreGraphicsState() + static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0; static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0; + } d->paintEngine->end(); if (d->state != QPrinter::Idle) d->releaseSession(); diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index 9740fce..e43544c 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -825,7 +825,7 @@ qreal qt_t_for_arc_angle(qreal angle) return t; } -void qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length, +Q_GUI_EXPORT void qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length, QPointF* startPoint, QPointF *endPoint); /*! diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 988d678..80b7520 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -47,6 +47,7 @@ #include "qpainterpath.h" #include "qvariant.h" #include <qmath.h> +#include <qnumeric.h> #include <private/qbezier_p.h> @@ -410,6 +411,12 @@ QTransform &QTransform::translate(qreal dx, qreal dy) { if (dx == 0 && dy == 0) return *this; +#ifndef QT_NO_DEBUG + if (qIsNaN(dx) | qIsNaN(dy)) { + qWarning() << "QTransform::translate with NaN called"; + return *this; + } +#endif switch(inline_type()) { case TxNone: @@ -447,6 +454,12 @@ QTransform &QTransform::translate(qreal dx, qreal dy) */ QTransform QTransform::fromTranslate(qreal dx, qreal dy) { +#ifndef QT_NO_DEBUG + if (qIsNaN(dx) | qIsNaN(dy)) { + qWarning() << "QTransform::fromTranslate with NaN called"; + return QTransform(); +} +#endif QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true); if (dx == 0 && dy == 0) transform.m_type = TxNone; @@ -466,6 +479,12 @@ QTransform & QTransform::scale(qreal sx, qreal sy) { if (sx == 1 && sy == 1) return *this; +#ifndef QT_NO_DEBUG + if (qIsNaN(sx) | qIsNaN(sy)) { + qWarning() << "QTransform::scale with NaN called"; + return *this; + } +#endif switch(inline_type()) { case TxNone: @@ -501,6 +520,12 @@ QTransform & QTransform::scale(qreal sx, qreal sy) */ QTransform QTransform::fromScale(qreal sx, qreal sy) { +#ifndef QT_NO_DEBUG + if (qIsNaN(sx) | qIsNaN(sy)) { + qWarning() << "QTransform::fromScale with NaN called"; + return QTransform(); +} +#endif QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true); if (sx == 1. && sy == 1.) transform.m_type = TxNone; @@ -520,6 +545,12 @@ QTransform & QTransform::shear(qreal sh, qreal sv) { if (sh == 0 && sv == 0) return *this; +#ifndef QT_NO_DEBUG + if (qIsNaN(sh) | qIsNaN(sv)) { + qWarning() << "QTransform::shear with NaN called"; + return *this; + } +#endif switch(inline_type()) { case TxNone: @@ -575,6 +606,12 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis) { if (a == 0) return *this; +#ifndef QT_NO_DEBUG + if (qIsNaN(a)) { + qWarning() << "QTransform::rotate with NaN called"; + return *this; + } +#endif qreal sina = 0; qreal cosa = 0; @@ -660,6 +697,12 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis) */ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) { +#ifndef QT_NO_DEBUG + if (qIsNaN(a)) { + qWarning() << "QTransform::rotateRadians with NaN called"; + return *this; + } +#endif qreal sina = qSin(a); qreal cosa = qCos(a); diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp index 8bd6344..e18ea3f 100644 --- a/src/gui/painting/qwindowsurface.cpp +++ b/src/gui/painting/qwindowsurface.cpp @@ -49,13 +49,19 @@ QT_BEGIN_NAMESPACE class QWindowSurfacePrivate { public: - QWindowSurfacePrivate(QWidget *w) : window(w), staticContentsSupport(false) {} + QWindowSurfacePrivate(QWidget *w) + : window(w) + , staticContentsSupport(0) + , partialUpdateSupport(1) + { + } QWidget *window; QRect geometry; QRegion staticContents; QList<QImage*> bufferImages; - bool staticContentsSupport; + uint staticContentsSupport : 1; + uint partialUpdateSupport : 1; }; /*! @@ -284,6 +290,10 @@ bool QWindowSurface::hasStaticContentsSupport() const void QWindowSurface::setStaticContentsSupport(bool enable) { + if (enable && !d_ptr->partialUpdateSupport) { + qWarning("QWindowSurface::setStaticContentsSupport: static contents support requires partial update support"); + return; + } d_ptr->staticContentsSupport = enable; } @@ -302,6 +312,20 @@ bool QWindowSurface::hasStaticContents() const return d_ptr->staticContentsSupport && !d_ptr->staticContents.isEmpty(); } +bool QWindowSurface::hasPartialUpdateSupport() const +{ + return d_ptr->partialUpdateSupport; +} + +void QWindowSurface::setPartialUpdateSupport(bool enable) +{ + if (!enable && d_ptr->staticContentsSupport) { + qWarning("QWindowSurface::setPartialUpdateSupport: static contents support requires partial update support"); + return; + } + d_ptr->partialUpdateSupport = enable; +} + void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) { // make sure we don't detach diff --git a/src/gui/painting/qwindowsurface_p.h b/src/gui/painting/qwindowsurface_p.h index 0a453af..6171ae8 100644 --- a/src/gui/painting/qwindowsurface_p.h +++ b/src/gui/painting/qwindowsurface_p.h @@ -73,8 +73,12 @@ public: QWidget *window() const; virtual QPaintDevice *paintDevice() = 0; - virtual void flush(QWidget *widget, const QRegion ®ion, - const QPoint &offset) = 0; + + // 'widget' can be a child widget, in which case 'region' is in child widget coordinates and + // offset is the (child) widget's offset in relation to the window surface. On QWS, 'offset' + // can be larger than just the offset from the top-level widget as there may also be window + // decorations which are painted into the window surface. + virtual void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) = 0; virtual void setGeometry(const QRect &rect); QRect geometry() const; @@ -90,6 +94,7 @@ public: inline QRect rect(const QWidget *widget) const; bool hasStaticContentsSupport() const; + bool hasPartialUpdateSupport() const; void setStaticContents(const QRegion ®ion); QRegion staticContents() const; @@ -97,6 +102,7 @@ public: protected: bool hasStaticContents() const; void setStaticContentsSupport(bool enable); + void setPartialUpdateSupport(bool enable); private: QWindowSurfacePrivate *d_ptr; diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index b0e2d37..8036728 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -981,7 +981,7 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt qreal y = position.y() + line.y() + line.ascent(); p->save(); p->setFont(option->font); - p->drawText(int(x), int(y), elidedText); + p->drawText(QPointF(x, y), elidedText); p->restore(); break; } diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 074dd89..f5b0b0c 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -2143,7 +2143,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW if (qstyleoption_cast<const QStyleOptionComboBox *>(opt) != 0) ret = 0; else - ret = QWindowsStyle::pixelMetric(metric, opt, widget); + ret = 1; break; case PM_MaximumDragDistance: ret = -1; @@ -3099,14 +3099,16 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai HIRect hirect = qt_hirectForQRect(opt->rect); HIThemeDrawButton(&hirect, &bi, cg, kHIThemeOrientationNormal, 0); break; } + case PE_Frame: { QPen oldPen = p->pen(); - QPen newPen; - newPen.setBrush(opt->palette.dark()); - p->setPen(newPen); + p->setPen(opt->palette.base().color().darker(140)); p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); + p->setPen(opt->palette.base().color().darker(180)); + p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); p->setPen(oldPen); break; } + case PE_FrameLineEdit: if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { if (frame->state & State_Sunken) { @@ -3279,10 +3281,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (header->orientation == Qt::Horizontal){ switch (header->position) { case QStyleOptionHeader::Beginning: + ir.adjust(-1, -1, 0, 0); break; case QStyleOptionHeader::Middle: + ir.adjust(-1, -1, 0, 0); + break; + case QStyleOptionHeader::OnlyOneSection: case QStyleOptionHeader::End: - ir.adjust(-1, 0, 0, 0); + ir.adjust(-1, -1, 1, 0); break; default: break; diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index f49acc4..7587343 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -122,6 +122,8 @@ QPalette *QS60StylePrivate::m_themePalette = 0; qint64 QS60StylePrivate::m_webPaletteKey = 0; +QPointer<QWidget> QS60StylePrivate::m_pressedWidget = 0; + const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameElementsData[] = { {SE_ButtonNormal, QS60StyleEnums::SP_QsnFrButtonTbCenter}, {SE_ButtonPressed, QS60StyleEnums::SP_QsnFrButtonTbCenterPressed}, @@ -138,6 +140,8 @@ const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameEleme {SE_PanelBackground, QS60StyleEnums::SP_QsnFrSetOptCenter}, {SE_ButtonInactive, QS60StyleEnums::SP_QsnFrButtonCenterInactive}, {SE_Editor, QS60StyleEnums::SP_QsnFrInputCenter}, + {SE_TableItemPressed, QS60StyleEnums::SP_QsnFrGridCenterPressed}, + {SE_ListItemPressed, QS60StyleEnums::SP_QsnFrListPressed}, }; static const int frameElementsCount = @@ -294,6 +298,12 @@ void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter, case SE_DropArea: drawPart(QS60StyleEnums::SP_QgnGrafOrgBgGrid, painter, rect, flags | SF_PointNorth); break; + case SE_TableItemPressed: + drawFrame(SF_TableItemPressed, painter, rect, flags | SF_PointNorth); + break; + case SE_ListItemPressed: + drawFrame(SF_ListItemPressed, painter, rect, flags | SF_PointNorth); + break; default: break; } @@ -542,6 +552,7 @@ void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start, QRect endRect; if (orientation == Qt::Horizontal) { + startRect.setHeight(rect.height()); startRect.setWidth(qMin((rect.width() >> 1) - 1, startRect.width())); endRect = startRect.translated(rect.width() - startRect.width(), 0); middleRect.adjust(startRect.width(), 0, -startRect.width(), 0); @@ -551,6 +562,7 @@ void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start, endRect.adjust(overlap, 0, 0, 0); } } else { + startRect.setWidth(rect.width()); startRect.setHeight(qMin((rect.height() >> 1) - 1, startRect.height())); endRect = startRect.translated(0, rect.height() - startRect.height()); middleRect.adjust(0, startRect.height(), 0, -startRect.height()); @@ -939,6 +951,11 @@ bool QS60StylePrivate::canDrawThemeBackground(const QBrush &backgroundBrush, con backgroundBrush.style() == Qt::NoBrush) ? true : false; } +bool QS60StylePrivate::isWidgetPressed(const QWidget *widget) +{ + return (widget && widget == m_pressedWidget); +} + /*! \class QS60Style \brief The QS60Style class provides a look and feel suitable for applications on S60. @@ -1357,14 +1374,13 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, optionComboBox.palette.setColor(QPalette::Inactive, QPalette::WindowText, optionComboBox.palette.text().color() ); QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget); - painter->save(); - painter->setClipRect(editRect); + const int frameW = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); if (!comboBox->currentIcon.isNull()) { - QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; - QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode); + const QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + const QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode); QRect iconRect(editRect); - iconRect.setWidth(comboBox->iconSize.width() + 4); + iconRect.setWidth(comboBox->iconSize.width() + frameW); iconRect = alignedRect(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter, iconRect.size(), editRect); @@ -1373,17 +1389,19 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); if (comboBox->direction == Qt::RightToLeft) - editRect.translate(-4 - comboBox->iconSize.width(), 0); + editRect.setRight(editRect.right() - frameW - comboBox->iconSize.width()); else - editRect.translate(comboBox->iconSize.width() + 4, 0); + editRect.setLeft(comboBox->iconSize.width() + frameW); } if (!comboBox->currentText.isEmpty() && !comboBox->editable) { + const Qt::TextElideMode elideMode = (comboBox->direction == Qt::LeftToRight) ? Qt::ElideRight : Qt::ElideLeft; + const QString text = comboBox->fontMetrics.elidedText(comboBox->currentText, elideMode, editRect.width()); + QCommonStyle::drawItemText(painter, editRect.adjusted(QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 0, -1, 0), visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter), - comboBox->palette, comboBox->state & State_Enabled, comboBox->currentText); + comboBox->palette, comboBox->state & State_Enabled, text); } - painter->restore(); } break; #endif //QT_NO_COMBOBOX @@ -1424,73 +1442,37 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, // draw themed background for table unless background brush has been defined. if (vopt->backgroundBrush == Qt::NoBrush) { if (itemView) { - const QModelIndex index = vopt->index; - //todo: Draw cell background only once - for the first cell. - QStyleOptionViewItemV4 voptAdj2 = voptAdj; - const QModelIndex indexFirst = itemView->model()->index(0, 0); - const QModelIndex indexLast = itemView->model()->index( - itemView->model()->rowCount() - 1, itemView->model()->columnCount() -1); - if (itemView->viewport()) - voptAdj2.rect = QRect( itemView->visualRect(indexFirst).topLeft(), - itemView->visualRect(indexLast).bottomRight()).intersect(itemView->viewport()->rect()); drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget); } } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);} - // draw the focus rect - if (isSelected || hasFocus ) { - QRect highlightRect = option->rect.adjusted(1,1,-1,-1); - QAbstractItemView::SelectionBehavior selectionBehavior = - itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems; - if (selectionBehavior != QAbstractItemView::SelectItems) { - // set highlight rect so that it is continuous from cell to cell, yet sligthly - // smaller than cell rect - int xBeginning = 0, yBeginning = 0, xEnd = 0, yEnd = 0; - if (selectionBehavior == QAbstractItemView::SelectRows) { - yBeginning = 1; yEnd = -1; - if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) - xBeginning = 1; - else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) - xEnd = -1; - } else if (selectionBehavior == QAbstractItemView::SelectColumns) { - xBeginning = 1; xEnd = -1; - if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) - yBeginning = 1; - else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) - yEnd = -1; - } - highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, yEnd); - } - if (vopt->showDecorationSelected && - (vopt->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color())) - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags); - else - painter->fillRect(highlightRect, vopt->palette.highlight()); - } - // draw the icon const QIcon::Mode mode = (voptAdj.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled; - const QIcon::State state = voptAdj.state & State_Open ? QIcon::On : QIcon::Off; + const QIcon::State state = (voptAdj.state & State_Open) ? QIcon::On : QIcon::Off; voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state); // Draw selection check mark. Show check mark only in multi selection modes. if (itemView) { const bool singleSelection = (itemView->selectionMode() == QAbstractItemView::SingleSelection || - itemView->selectionMode() == QAbstractItemView::NoSelection); + itemView->selectionMode() == QAbstractItemView::NoSelection)|| + (itemView->selectionModel()->selectedIndexes().count() < 2 ); + + const bool selectItemsOnly = (itemView->selectionBehavior() == QAbstractItemView::SelectItems); + const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget); QStyleOptionViewItemV4 checkMarkOption(voptAdj); - // Draw selection mark. - if (voptAdj.state & State_Selected && !singleSelection) { + if (selectionRect.isValid()) checkMarkOption.rect = selectionRect; - drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); - if ( textRect.right() > selectionRect.left() ) + // Draw selection mark. + if (isSelected && !singleSelection && selectItemsOnly) { + proxy()->drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); + // @todo: this should happen in the rect retrievel i.e. subElementRect() + if (textRect.right() > selectionRect.left()) textRect.setRight(selectionRect.left()); } else if (singleSelection && - voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator && - selectionRect.isValid()) { - checkMarkOption.rect = selectionRect; + voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) { checkMarkOption.state = checkMarkOption.state & ~State_HasFocus; switch (vopt->checkState) { @@ -1562,7 +1544,6 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); const int tabOverlap = QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness; - //todo: draw navi wipe behind tabbar - must be drawn with first draw if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive|| skinElement==QS60StylePrivate::SE_TabBarTabEastActive|| @@ -1666,7 +1647,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, painter->drawPixmap(tr.left() + tabOverlap, tr.center().y() - (tabIcon.height() >> 1), tabIcon); - tr.setLeft(tr.left() + iconSize.width() + 4); + tr.setLeft(tr.left() + iconSize.width() + 4); //todo: magic four } QCommonStyle::drawItemText(painter, tr, alignment, optionTab.palette, tab->state & State_Enabled, tab->text, QPalette::WindowText); @@ -1985,14 +1966,14 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, // We need to reduce the focus frame size if LayoutSpacing is smaller than FocusFrameMargin // Otherwise, we would overlay adjacent widgets. const int frameHeightReduction = - qMin(0, pixelMetric(QStyle::PM_LayoutVerticalSpacing) - - pixelMetric(QStyle::PM_FocusFrameVMargin)); + qMin(0, pixelMetric(PM_LayoutVerticalSpacing) + - pixelMetric(PM_FocusFrameVMargin)); const int frameWidthReduction = - qMin(0, pixelMetric(QStyle::PM_LayoutHorizontalSpacing) - - pixelMetric(QStyle::PM_FocusFrameHMargin)); + qMin(0, pixelMetric(PM_LayoutHorizontalSpacing) + - pixelMetric(PM_FocusFrameHMargin)); const int rounding = - qMin(pixelMetric(QStyle::PM_FocusFrameVMargin), - pixelMetric(QStyle::PM_LayoutVerticalSpacing)); + qMin(pixelMetric(PM_FocusFrameVMargin), + pixelMetric(PM_LayoutVerticalSpacing)); const QRect frameRect = option->rect.adjusted(-frameWidthReduction, -frameHeightReduction, frameWidthReduction, frameHeightReduction); @@ -2037,7 +2018,10 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) if ((qstyleoption_cast<const QStyleOptionFocusRect *>(option) && (qobject_cast<const QRadioButton *>(widget) || qobject_cast<const QCheckBox *>(widget)))) - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); + QS60StylePrivate::drawSkinElement( + QS60StylePrivate::isWidgetPressed(widget) ? + QS60StylePrivate::SE_ListItemPressed : + QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); else commonStyleDraws = true; } @@ -2257,6 +2241,57 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti break; #ifndef QT_NO_ITEMVIEWS case PE_PanelItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) { + const bool isSelected = (vopt->state & State_Selected); + const bool hasFocus = (vopt->state & State_HasFocus); + const bool isPressed = QS60StylePrivate::isWidgetPressed(widget); + + if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) { + QRect highlightRect = vopt->rect.adjusted(1,1,-1,-1); + const QAbstractItemView *itemView = qobject_cast<const QAbstractItemView *>(widget); + QAbstractItemView::SelectionBehavior selectionBehavior = + itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems; + // Set the draw area for highlights (focus, select rect or pressed rect) + if (hasFocus || isSelected || isPressed) { + if (selectionBehavior != QAbstractItemView::SelectItems) { + // set highlight rect so that it is continuous from cell to cell, yet sligthly + // smaller than cell rect + int xBeginning = 0, yBeginning = 0, xEnd = 0, yEnd = 0; + if (selectionBehavior == QAbstractItemView::SelectRows) { + yBeginning = 1; yEnd = -1; + if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) + xBeginning = 1; + else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) + xEnd = -1; + } else if (selectionBehavior == QAbstractItemView::SelectColumns) { + xBeginning = 1; xEnd = -1; + if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) + yBeginning = 1; + else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) + yEnd = -1; + } + highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, yEnd); + } + } + bool tableView = false; + if (itemView && qobject_cast<const QTableView *>(widget)) + tableView = true; + + QS60StylePrivate::SkinElements element; + QRect elementRect = option->rect; + + //draw item is drawn as pressed, if it already has focus. + if (isPressed && (hasFocus || isSelected)) { + element = tableView ? QS60StylePrivate::SE_TableItemPressed : QS60StylePrivate::SE_ListItemPressed; + } else if (hasFocus || (isSelected && selectionBehavior != QAbstractItemView::SelectItems)) { + element = QS60StylePrivate::SE_ListHighlight; + elementRect = highlightRect; + } + QS60StylePrivate::drawSkinElement(element, painter, elementRect, flags); + } else { + QCommonStyle::drawPrimitive(element, option, painter, widget); + } + } break; #endif //QT_NO_ITEMVIEWS @@ -2814,7 +2849,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con const int tabOverlapNoBorder = QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap); const int tabOverlap = - tabOverlapNoBorder-QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + tabOverlapNoBorder - QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget); int gain = (tab) ? tabOverlap * tab->count() : 0; switch (twf->shape) { @@ -2880,7 +2915,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con ret = QRect(); } else { if (menuItem->direction == Qt::RightToLeft) - ret.translate(ret.width()-indicatorWidth, 0); + ret.translate(ret.width() - indicatorWidth, 0); ret.setWidth(indicatorWidth); } } else { @@ -3067,8 +3102,11 @@ void QS60Style::unpolish(QWidget *widget) void QS60Style::polish(QApplication *application) { Q_D(QS60Style); + QCommonStyle::polish(qApp); d->m_originalPalette = application->palette(); d->setThemePalette(application); + if (QS60StylePrivate::isTouchSupported()) + qApp->installEventFilter(this); } /*! @@ -3077,10 +3115,14 @@ void QS60Style::polish(QApplication *application) void QS60Style::unpolish(QApplication *application) { Q_UNUSED(application) + Q_D(QS60Style); + QCommonStyle::unpolish(qApp); const QPalette newPalette = QApplication::style()->standardPalette(); QApplication::setPalette(newPalette); QApplicationPrivate::setSystemPalette(d->m_originalPalette); + if (QS60StylePrivate::isTouchSupported()) + qApp->removeEventFilter(this); } /*! @@ -3227,9 +3269,40 @@ QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, */ bool QS60Style::eventFilter(QObject *object, QEvent *event) { + Q_D(QS60Style); + switch(event->type()) { + case QEvent::MouseButtonPress: { + QWidget *w = QApplication::widgetAt(QCursor::pos()); + if (w) { + QWidget *focusW = w->focusProxy(); + if (qobject_cast<QAbstractItemView *>(focusW) || + qobject_cast<QRadioButton *>(focusW) || + qobject_cast<QCheckBox *>(focusW)) + d->m_pressedWidget = focusW; + else if (qobject_cast<QAbstractItemView *>(w)|| + qobject_cast<QRadioButton *>(w) || + qobject_cast<QCheckBox *>(w)) + d->m_pressedWidget = w; + + if ( d->m_pressedWidget) + d->m_pressedWidget->update(); + } + break; + } + case QEvent::MouseButtonRelease: { + const QWidget *w = QApplication::widgetAt(QCursor::pos()); + if (w && d->m_pressedWidget) { + d->m_pressedWidget->update(); + d->m_pressedWidget = 0; + } + break; + } + default: + break; + } + #ifdef Q_WS_S60 #ifndef QT_NO_PROGRESSBAR - Q_D(QS60Style); switch(event->type()) { case QEvent::StyleChange: case QEvent::Show: @@ -3242,15 +3315,17 @@ bool QS60Style::eventFilter(QObject *object, QEvent *event) break; case QEvent::Destroy: case QEvent::Hide: - d->stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); - d->m_bars.removeAll(reinterpret_cast<QProgressBar *>(object)); + if (QProgressBar *bar = reinterpret_cast<QProgressBar *>(object)) { + d->stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); + d->m_bars.removeAll(bar); + } break; default: break; } #endif // QT_NO_PROGRESSBAR #endif // Q_WS_S60 - return QStyle::eventFilter(object, event); + return QCommonStyle::eventFilter(object, event); } /*! diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h index 6ce4960..9dd3810 100644 --- a/src/gui/styles/qs60style_p.h +++ b/src/gui/styles/qs60style_p.h @@ -293,6 +293,24 @@ public: SP_QsnFrButtonSideLInactive, SP_QsnFrButtonSideRInactive, SP_QsnFrButtonCenterInactive, + SP_QsnFrGridCornerTlPressed, // Pressed table item + SP_QsnFrGridCornerTrPressed, + SP_QsnFrGridCornerBlPressed, + SP_QsnFrGridCornerBrPressed, + SP_QsnFrGridSideTPressed, + SP_QsnFrGridSideBPressed, + SP_QsnFrGridSideLPressed, + SP_QsnFrGridSideRPressed, + SP_QsnFrGridCenterPressed, + SP_QsnFrListCornerTlPressed, // Pressed list item + SP_QsnFrListCornerTrPressed, + SP_QsnFrListCornerBlPressed, + SP_QsnFrListCornerBrPressed, + SP_QsnFrListSideTPressed, + SP_QsnFrListSideBPressed, + SP_QsnFrListSideLPressed, + SP_QsnFrListSideRPressed, + SP_QsnFrListPressed, }; enum ColorLists { @@ -424,7 +442,9 @@ public: SE_ScrollBarHandlePressedVertical, SE_ButtonInactive, SE_Editor, - SE_DropArea + SE_DropArea, + SE_TableItemPressed, + SE_ListItemPressed, }; enum SkinFrameElements { @@ -442,6 +462,8 @@ public: SF_ToolBarButtonPressed, SF_PanelBackground, SF_ButtonInactive, + SF_TableItemPressed, + SF_ListItemPressed, }; enum SkinElementFlag { @@ -496,6 +518,7 @@ public: static bool isToolBarBackground(); static bool hasSliderGrooveGraphic(); static bool isSingleClickUi(); + static bool isWidgetPressed(const QWidget *widget); // calculates average color based on button skin graphics (minus borders). QColor colorFromFrameGraphics(SkinFrameElements frame) const; @@ -593,6 +616,8 @@ private: QPointer<QFocusFrame> m_focusFrame; static qint64 m_webPaletteKey; + static QPointer<QWidget> m_pressedWidget; + #ifdef Q_WS_S60 //list of progress bars having animation running QList<QProgressBar *> m_bars; diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 6a552e0..58a7159 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -377,6 +377,27 @@ const partMapEntry QS60StyleModeSpecifics::m_partMap[] = { /* SP_QsnFrButtonSideRInactive */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b8}, /* SP_QsnFrButtonCenterInactive */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_3_X, EAknsMajorSkin, 0x21b9}, + // No pressed down grid in 3.1/3.2 + /* SP_QsnFrGridCornerTlPressed */ {KAknsIIDQsnFrGridCornerTl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2681}, /*KAknsIIDQsnFrGridCornerTlPressed*/ + /* SP_QsnFrGridCornerTrPressed */ {KAknsIIDQsnFrGridCornerTr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2682}, + /* SP_QsnFrGridCornerBlPressed */ {KAknsIIDQsnFrGridCornerBl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2683}, + /* SP_QsnFrGridCornerBrPressed */ {KAknsIIDQsnFrGridCornerBr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2684}, + /* SP_QsnFrGridSideTPressed */ {KAknsIIDQsnFrGridSideT, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2685}, + /* SP_QsnFrGridSideBPressed */ {KAknsIIDQsnFrGridSideB, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2686}, + /* SP_QsnFrGridSideLPressed */ {KAknsIIDQsnFrGridSideL, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2687}, + /* SP_QsnFrGridSideRPressed */ {KAknsIIDQsnFrGridSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2688}, + /* SP_QsnFrGridCenterPressed */ {KAknsIIDQsnFrGridCenter, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2689}, + + // No pressed down list in 3.1/3.2 + /* SP_QsnFrListCornerTlPressed */ {KAknsIIDQsnFrListCornerTl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268b}, /*KAknsIIDQsnFrListCornerTlPressed*/ + /* SP_QsnFrListCornerTrPressed */ {KAknsIIDQsnFrListCornerTr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268c}, + /* SP_QsnFrListCornerBlPressed */ {KAknsIIDQsnFrListCornerBl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268d}, + /* SP_QsnFrListCornerBrPressed */ {KAknsIIDQsnFrListCornerBr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268e}, + /* SP_QsnFrListSideTPressed */ {KAknsIIDQsnFrListSideT, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268f}, + /* SP_QsnFrListSideBPressed */ {KAknsIIDQsnFrListSideB, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2690}, + /* SP_QsnFrListSideLPressed */ {KAknsIIDQsnFrListSideL, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2691}, + /* SP_QsnFrListSideRPressed */ {KAknsIIDQsnFrListSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2692}, + /* SP_QsnFrListPressed */ {KAknsIIDQsnFrList, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2693}, }; QPixmap QS60StyleModeSpecifics::skinnedGraphics( diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index a1a98ba..81b923b 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -4255,8 +4255,15 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) { const QAbstractScrollAreaPrivate *sap = sa->d_func(); rule.drawBackground(p, opt->rect, sap->contentsOffset()); - if (rule.hasBorder()) - rule.drawBorder(p, rule.borderRect(opt->rect)); + if (rule.hasBorder()) { + QRect brect = rule.borderRect(opt->rect); + if (styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, opt, w)) { + QRect r = brect.adjusted(0, 0, sa->verticalScrollBar()->isVisible() ? -sa->verticalScrollBar()->width() : 0, + sa->horizontalScrollBar()->isVisible() ? -sa->horizontalScrollBar()->height() : 0); + brect = QStyle::visualRect(opt->direction, brect, r); + } + rule.drawBorder(p, brect); + } break; } #endif @@ -4641,6 +4648,11 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const return msz.width() == -1 ? msz.height() : msz.width(); } break; + + case PM_ScrollView_ScrollBarSpacing: + if(!rule.hasNativeBorder() || rule.hasBox()) + return 0; + break; #endif // QT_NO_SCROLLBAR case PM_ProgressBarChunkWidth: diff --git a/src/gui/styles/qwindowsxpstyle_p.h b/src/gui/styles/qwindowsxpstyle_p.h index 4e8aa00..0a13a52 100644 --- a/src/gui/styles/qwindowsxpstyle_p.h +++ b/src/gui/styles/qwindowsxpstyle_p.h @@ -59,10 +59,15 @@ #include <qt_windows.h> // Note, these tests are duplicated in qwizard_win.cpp. -// minimum version for Windows XP is 0x501 -#if _WIN32_WINNT < 0x0501 -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 +#ifdef Q_CC_GNU +# include <w32api.h> +# if (__W32API_MAJOR_VERSION >= 3 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION >= 5)) +# ifdef _WIN32_WINNT +# undef _WIN32_WINNT +# endif +# define _WIN32_WINNT 0x0501 +# include <commctrl.h> +# endif #endif #include <uxtheme.h> diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 938decd..b3d2526 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -895,7 +895,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord BorderData data = qvariant_cast<BorderData>(decl.d->parsed); *width = lengthValueFromData(data.width, f); *style = data.style; - *color = brushFromData(data.color, pal); + *color = data.color.type != BrushData::Invalid ? brushFromData(data.color, pal) : QBrush(QColor()); return; } diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 6803120..ae5e9ca 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -83,7 +83,7 @@ QT_BEGIN_NAMESPACE #define SMOOTH_SCALABLE 0xffff -extern int qt_defaultDpiY(); // in qfont.cpp +Q_GUI_EXPORT extern int qt_defaultDpiY(); // in qfont.cpp bool qt_enable_test_font = false; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index a9def8e..449dffd 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1368,7 +1368,7 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransfor if (!gs) { // don't try to load huge fonts - bool draw_as_outline = fontDef.pixelSize * qSqrt(matrix.det()) >= 64; + bool draw_as_outline = fontDef.pixelSize * qSqrt(qAbs(matrix.det())) >= 64; if (draw_as_outline) return 0; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 0bfdbc0..a6510cb 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -226,8 +226,19 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay QFixed *outAdvances_y = glyphs->advances_y; glyph_t *initialGlyph = outGlyphs; - if (arraySize == 0) - return false; + if (arraySize == 0) { + // CoreText failed to shape the text we gave it, so we assume one glyph + // per character and build a list of invalid glyphs with zero advance + *nglyphs = len; + for (int i = 0; i < len; ++i) { + outGlyphs[i] = 0; + logClusters[i] = i; + outAdvances_x[i] = QFixed(); + outAdvances_y[i] = QFixed(); + outAttributes[i].clusterStart = true; + } + return true; + } const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft); diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 3a52e8e..5163c94 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -63,7 +63,7 @@ extern void qt_format_text(const QFont& font, const QRectF &_r, int tf, const QString &text, QRectF *brect, int tabStops, int *tabArray, int tabArrayLen, QPainter *painter); -extern int qt_defaultDpi(); +Q_GUI_EXPORT extern int qt_defaultDpi(); /***************************************************************************** QFontMetrics member functions diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index 6c504a7..c7817c6 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -363,7 +363,7 @@ QSizeF QStaticText::size() const } QStaticTextPrivate::QStaticTextPrivate() - : items(0), itemCount(0), glyphPool(0), positionPool(0), textWidth(-1.0), + : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText) { } @@ -387,8 +387,8 @@ QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q) return q->data.data(); } -extern int qt_defaultDpiX(); -extern int qt_defaultDpiY(); +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); namespace { @@ -584,11 +584,13 @@ void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p) textLayout.draw(p, topLeftPosition); } else { QTextDocument document; +#ifndef QT_NO_CSSPARSER QColor color = p->pen().color(); document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }") .arg(QString::number(color.red(), 16), 2, QLatin1Char('0')) .arg(QString::number(color.green(), 16), 2, QLatin1Char('0')) .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0'))); +#endif document.setDefaultFont(font); document.setDocumentMargin(0.0); if (textWidth >= 0.0) diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 3c596e5..a2ee659 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -885,8 +885,10 @@ void QTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset, QWid void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget) { Q_D(QTextControl); - if (d->interactionFlags & Qt::NoTextInteraction) + if (d->interactionFlags == Qt::NoTextInteraction) { + e->ignore(); return; + } d->contextWidget = contextWidget; diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 9a1b70c..3e556a7 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1656,7 +1656,7 @@ static void printPage(int index, QPainter *painter, const QTextDocument *doc, co painter->restore(); } -extern int qt_defaultDpi(); +Q_GUI_EXPORT extern int qt_defaultDpi(); /*! Prints the document to the given \a printer. The QPrinter must be diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 302a349..e2bca04 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -870,6 +870,7 @@ int QTextDocumentPrivate::undoRedo(bool undo) undoEnabled = false; beginEditBlock(); int editPos = -1; + int editLength = -1; while (1) { if (undo) --undoState; @@ -882,12 +883,16 @@ int QTextDocumentPrivate::undoRedo(bool undo) PMDEBUG(" erase: from %d, length %d", c.pos, c.length); c.command = QTextUndoCommand::Removed; editPos = c.pos; + editLength = 0; break; case QTextUndoCommand::Removed: PMDEBUG(" insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos); insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation); c.command = QTextUndoCommand::Inserted; - editPos = c.pos + c.length; + if (editPos != (int)c.pos) + editLength = 0; + editPos = c.pos; + editLength += c.length; break; case QTextUndoCommand::BlockInserted: case QTextUndoCommand::BlockAdded: @@ -898,6 +903,7 @@ int QTextDocumentPrivate::undoRedo(bool undo) else c.command = QTextUndoCommand::BlockDeleted; editPos = c.pos; + editLength = 0; break; case QTextUndoCommand::BlockRemoved: case QTextUndoCommand::BlockDeleted: @@ -908,7 +914,10 @@ int QTextDocumentPrivate::undoRedo(bool undo) c.command = QTextUndoCommand::BlockInserted; else c.command = QTextUndoCommand::BlockAdded; - editPos = c.pos + 1; + if (editPos != (int)c.pos) + editLength = 0; + editPos = c.pos; + editLength += 1; break; case QTextUndoCommand::CharFormatChanged: { resetBlockRevision = -1; // ## TODO @@ -919,7 +928,10 @@ int QTextDocumentPrivate::undoRedo(bool undo) int oldFormat = it.value()->format; setCharFormat(c.pos, c.length, formats.charFormat(c.format)); c.format = oldFormat; - editPos = c.pos + c.length; + if (editPos != (int)c.pos) + editLength = 0; + editPos = c.pos; + editLength += c.length; break; } case QTextUndoCommand::BlockFormatChanged: { @@ -987,13 +999,19 @@ int QTextDocumentPrivate::undoRedo(bool undo) break; } undoEnabled = true; - if (editPos < 0 && docChangeFrom >= 0) { - editPos = qMin(docChangeFrom + docChangeLength, length() - 1); - } + + int newCursorPos = -1; + + if (editPos >=0) + newCursorPos = editPos + editLength; + else if (docChangeFrom >= 0) + newCursorPos= qMin(docChangeFrom + docChangeLength, length() - 1); + endEditBlock(); emitUndoAvailable(isUndoAvailable()); emitRedoAvailable(isRedoAvailable()); - return editPos; + + return newCursorPos; } /*! diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index b45fcbb..f12bf0b 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE -extern int qt_defaultDpi(); +Q_GUI_EXPORT extern int qt_defaultDpi(); // ################ should probably add frameFormatChange notification! diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 6485966..d34553f 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -856,7 +856,7 @@ void QTextEngine::shapeLine(const QScriptLine &line) } } -extern int qt_defaultDpiY(); // in qfont.cpp +Q_GUI_EXPORT extern int qt_defaultDpiY(); // in qfont.cpp void QTextEngine::shapeText(int item) const { @@ -2494,7 +2494,7 @@ void QTextEngine::splitItem(int item, int pos) const // qDebug("split at position %d itempos=%d", pos, item); } -extern int qt_defaultDpiY(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const { diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp index fa49a32..6733793 100644 --- a/src/gui/text/qtextimagehandler.cpp +++ b/src/gui/text/qtextimagehandler.cpp @@ -123,7 +123,7 @@ static QSize getPixmapSize(QTextDocument *doc, const QTextImageFormat &format) qreal scale = 1.0; QPaintDevice *pdev = doc->documentLayout()->paintDevice(); if (pdev) { - extern int qt_defaultDpi(); + Q_GUI_EXPORT extern int qt_defaultDpi(); if (pm.isNull()) pm = getPixmap(doc, format); if (!pm.isNull()) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 312d135..ce7915d 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -305,7 +305,7 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const Once the layout is done, these lines can be drawn on a paint device. - Here's some pseudo code that presents the layout phase: + Here's some code snippet that presents the layout phase: \snippet doc/src/snippets/code/src_gui_text_qtextlayout.cpp 0 The text can be drawn by calling the layout's draw() function: diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index d369bff0..7992de5 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -493,10 +493,10 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format.nonBreakableLines() ? QString::fromLatin1("true") : QString::fromLatin1("false")); if (format.hasProperty(QTextFormat::TabPositions)) { QList<QTextOption::Tab> tabs = format.tabPositions(); - writer.writeStartElement(styleNS, QString::fromLatin1("style-tab-stops")); + writer.writeStartElement(styleNS, QString::fromLatin1("tab-stops")); QList<QTextOption::Tab>::Iterator iterator = tabs.begin(); while(iterator != tabs.end()) { - writer.writeEmptyElement(styleNS, QString::fromLatin1("style-tab-stop")); + writer.writeEmptyElement(styleNS, QString::fromLatin1("tab-stop")); writer.writeAttribute(styleNS, QString::fromLatin1("position"), pixelToPoint(iterator->position) ); QString type; switch(iterator->type) { @@ -511,7 +511,7 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat ++iterator; } - writer.writeEndElement(); // style-tab-stops + writer.writeEndElement(); // tab-stops } writer.writeEndElement(); // paragraph-properties @@ -698,11 +698,11 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe if (padding > 0) writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding)); if (format.bottomPadding() > 0) - writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.bottomPadding())); + writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"), pixelToPoint(format.bottomPadding())); if (format.leftPadding() > 0) - writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.leftPadding())); + writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding())); if (format.rightPadding() > 0) - writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.rightPadding())); + writer.writeAttribute(foNS, QString::fromLatin1("padding-right"), pixelToPoint(format.rightPadding())); } if (format.hasProperty(QTextFormat::TextVerticalAlignment)) { diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp index 5ceb237..995d659 100644 --- a/src/gui/widgets/qabstractbutton.cpp +++ b/src/gui/widgets/qabstractbutton.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE #define AUTO_REPEAT_DELAY 300 #define AUTO_REPEAT_INTERVAL 100 -extern bool qt_tab_all_widgets; +Q_GUI_EXPORT extern bool qt_tab_all_widgets; /*! \class QAbstractButton diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp index 1d496d5..8cffebd 100644 --- a/src/gui/widgets/qabstractscrollarea.cpp +++ b/src/gui/widgets/qabstractscrollarea.cpp @@ -394,7 +394,7 @@ void QAbstractScrollAreaPrivate::layoutChildren() if ((frameStyle != QFrame::NoFrame) && q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, q)) { controlsRect = widgetRect; - const int extra = q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing); + const int extra = q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, q); const QPoint cornerExtra(needv ? extra : 0, needh ? extra : 0); QRect frameRect = widgetRect; frameRect.adjust(0, 0, -cornerOffset.x() - cornerExtra.x(), -cornerOffset.y() - cornerExtra.y()); @@ -983,6 +983,7 @@ bool QAbstractScrollArea::event(QEvent *e) case QEvent::StyleChange: case QEvent::LayoutDirectionChange: case QEvent::ApplicationLayoutDirectionChange: + case QEvent::LayoutRequest: d->layoutChildren(); // fall through default: diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index b1a27f2..ca58e6d 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -76,6 +76,10 @@ #ifndef QT_NO_EFFECTS # include <private/qeffects_p.h> #endif +#if defined(Q_WS_S60) +#include "private/qt_s60_p.h" +#endif + QT_BEGIN_NAMESPACE QComboBoxPrivate::QComboBoxPrivate() @@ -2458,11 +2462,16 @@ void QComboBox::showPopup() // in portait, menu should be positioned above softkeys listRect.moveBottom(screen.bottom()); } else { - // landscape, menu should be at the right and horizontally centered + TRect staConTopRect = TRect(); + AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EStaconTop, staConTopRect); listRect.setWidth(listRect.height()); + //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : - listRect.setLeft(screen.left()); + if (staConTopRect.IsEmpty()) { + // landscape without stacon, menu should be at the right + (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : + listRect.setLeft(screen.left()); + } } #endif } else if (!boundToScreen || listRect.height() <= belowHeight) { @@ -2690,13 +2699,18 @@ void QComboBox::changeEvent(QEvent *e) // in portait, menu should be positioned above softkeys listRect.moveBottom(screen.bottom()); } else { - // landscape, menu should be at the right and horizontally centered + TRect staConTopRect = TRect(); + AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EStaconTop, staConTopRect); listRect.setWidth(listRect.height()); + //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : - listRect.setLeft(screen.left()); + if (staConTopRect.IsEmpty()) { + // landscape without stacon, menu should be at the right + (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : + listRect.setLeft(screen.left()); + } + d->container->setGeometry(listRect); } - d->container->setGeometry(listRect); } } #endif diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 42df800..d027b91 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1350,6 +1350,7 @@ bool QLineControl::processEvent(QEvent* ev) #endif switch(ev->type()){ #ifndef QT_NO_GRAPHICSVIEW + case QEvent::GraphicsSceneMouseDoubleClick: case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMouseRelease: case QEvent::GraphicsSceneMousePress:{ @@ -1439,6 +1440,7 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) moveCursor(cursor, mark); break; } + case QEvent::GraphicsSceneMouseDoubleClick: case QEvent::MouseButtonDblClick: if (ev->button() == Qt::LeftButton) { selectWordAtPos(xToPos(ev->pos().x())); diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 0b8dca9..655fc61 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1869,13 +1869,18 @@ void QLineEdit::paintEvent(QPaintEvent *) } QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height()); + int minLB = qMax(0, -fm.minLeftBearing()); + int minRB = qMax(0, -fm.minRightBearing()); + if (d->control->text().isEmpty()) { if (!hasFocus() && !d->placeholderText.isEmpty()) { QColor col = pal.text().color(); col.setAlpha(128); QPen oldpen = p.pen(); p.setPen(col); - p.drawText(lineRect, va, d->placeholderText); + lineRect.adjust(minLB, 0, 0, 0); + QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, lineRect.width()); + p.drawText(lineRect, va, elidedText); p.setPen(oldpen); return; } @@ -1889,8 +1894,6 @@ void QLineEdit::paintEvent(QPaintEvent *) // the below code handles all scrolling based on the textline (widthUsed, // minLB, minRB), the line edit rect (lineRect) and the cursor position // (cix). - int minLB = qMax(0, -fm.minLeftBearing()); - int minRB = qMax(0, -fm.minRightBearing()); int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; if ((minLB + widthUsed) <= lineRect.width()) { // text fits in lineRect; use hscroll for alignment diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 9e190b7..907dd14 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -1805,7 +1805,7 @@ QSize QMenu::sizeHint() const void QMenu::popup(const QPoint &p, QAction *atAction) { Q_D(QMenu); - if (d->scroll) { //reset scroll state from last popup + if (d->scroll) { // reset scroll state from last popup d->scroll->scrollOffset = 0; d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone; } @@ -1834,7 +1834,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction) QSize size = sizeHint(); QRect screen; #ifndef QT_NO_GRAPHICSVIEW - bool isEmbedded = d->nearestGraphicsProxyWidget(this); + bool isEmbedded = !bypassGraphicsProxyWidget(this) && d->nearestGraphicsProxyWidget(this); if (isEmbedded) screen = d->popupGeometry(this); else @@ -1860,9 +1860,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction) } #endif if (d->ncols > 1) { - pos.setY(screen.top()+desktopFrame); + pos.setY(screen.top() + desktopFrame); } else if (atAction) { - for(int i = 0, above_height = 0; i < d->actions.count(); i++) { + for (int i = 0, above_height = 0; i < d->actions.count(); i++) { QAction *action = d->actions.at(i); if (action == atAction) { int newY = pos.y() - above_height; @@ -1877,7 +1877,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction) if (d->scroll && d->scroll->scrollFlags != QMenuPrivate::QMenuScroller::ScrollNone && !style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, 0, this)) { int below_height = above_height + d->scroll->scrollOffset; - for(int i2 = i; i2 < d->actionRects.count(); i2++) + for (int i2 = i; i2 < d->actionRects.count(); i2++) below_height += d->actionRects.at(i2).height(); size.setHeight(below_height); } @@ -1890,28 +1890,28 @@ void QMenu::popup(const QPoint &p, QAction *atAction) QPoint mouse = QCursor::pos(); d->mousePopupPos = mouse; - const bool snapToMouse = (QRect(p.x()-3, p.y()-3, 6, 6).contains(mouse)); + const bool snapToMouse = (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse)); if (adjustToDesktop) { - //handle popup falling "off screen" + // handle popup falling "off screen" if (isRightToLeft()) { - if(snapToMouse) //position flowing left from the mouse - pos.setX(mouse.x()-size.width()); + if (snapToMouse) // position flowing left from the mouse + pos.setX(mouse.x() - size.width()); #ifndef QT_NO_MENUBAR - //if in a menubar, it should be right-aligned + // if in a menubar, it should be right-aligned if (qobject_cast<QMenuBar*>(d->causedPopup.widget)) pos.rx() -= size.width(); #endif //QT_NO_MENUBAR - if (pos.x() < screen.left()+desktopFrame) - pos.setX(qMax(p.x(), screen.left()+desktopFrame)); - if (pos.x()+size.width()-1 > screen.right()-desktopFrame) - pos.setX(qMax(p.x()-size.width(), screen.right()-desktopFrame-size.width()+1)); + if (pos.x() < screen.left() + desktopFrame) + pos.setX(qMax(p.x(), screen.left() + desktopFrame)); + if (pos.x() + size.width() - 1 > screen.right() - desktopFrame) + pos.setX(qMax(p.x() - size.width(), screen.right() - desktopFrame - size.width() + 1)); } else { - if (pos.x()+size.width()-1 > screen.right()-desktopFrame) - pos.setX(screen.right()-desktopFrame-size.width()+1); - if (pos.x() < screen.left()+desktopFrame) + if (pos.x() + size.width() - 1 > screen.right() - desktopFrame) + pos.setX(screen.right() - desktopFrame - size.width() + 1); + if (pos.x() < screen.left() + desktopFrame) pos.setX(screen.left() + desktopFrame); } if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) { @@ -1925,14 +1925,14 @@ void QMenu::popup(const QPoint &p, QAction *atAction) if (pos.y() < screen.top() + desktopFrame) pos.setY(screen.top() + desktopFrame); - if (pos.y()+size.height()-1 > screen.bottom() - desktopFrame) { + if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) { if (d->scroll) { d->scroll->scrollFlags |= uint(QMenuPrivate::QMenuScroller::ScrollDown); int y = qMax(screen.y(),pos.y()); - size.setHeight(screen.bottom()-(desktopFrame*2)-y); + size.setHeight(screen.bottom() - (desktopFrame * 2) - y); } else { // Too big for screen, bias to see bottom of menu (for some reason) - pos.setY(screen.bottom()-size.height()+1); + pos.setY(screen.bottom() - size.height() + 1); } } } @@ -1941,19 +1941,19 @@ void QMenu::popup(const QPoint &p, QAction *atAction) int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll; int vGuess = QEffects::DownScroll; if (isRightToLeft()) { - if ((snapToMouse && (pos.x() + size.width()/2 > mouse.x())) || - (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width()/2 > d->causedPopup.widget->x())) + if ((snapToMouse && (pos.x() + size.width() / 2 > mouse.x())) || + (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width() / 2 > d->causedPopup.widget->x())) hGuess = QEffects::RightScroll; } else { - if ((snapToMouse && (pos.x() + size.width()/2 < mouse.x())) || - (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width()/2 < d->causedPopup.widget->x())) + if ((snapToMouse && (pos.x() + size.width() / 2 < mouse.x())) || + (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width() / 2 < d->causedPopup.widget->x())) hGuess = QEffects::LeftScroll; } #ifndef QT_NO_MENUBAR - if ((snapToMouse && (pos.y() + size.height()/2 < mouse.y())) || + if ((snapToMouse && (pos.y() + size.height() / 2 < mouse.y())) || (qobject_cast<QMenuBar*>(d->causedPopup.widget) && - pos.y() + size.width()/2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y())) + pos.y() + size.width() / 2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y())) vGuess = QEffects::UpScroll; #endif if (QApplication::isEffectEnabled(Qt::UI_AnimateMenu)) { diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index 6a0eb53..e8400d6 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -665,6 +665,7 @@ void qt_mac_set_modal_state_helper_recursive(OSMenuRef menu, OSMenuRef merge, bo } } #else + bool modalWindowOnScreen = qApp->activeModalWidget() != 0; for (NSMenuItem *item in [menu itemArray]) { OSMenuRef submenu = [item submenu]; if (submenu != merge) { @@ -674,10 +675,20 @@ void qt_mac_set_modal_state_helper_recursive(OSMenuRef menu, OSMenuRef merge, bo // The item should follow what the QAction has. if ([item tag]) { QAction *action = reinterpret_cast<QAction *>([item tag]); - syncNSMenuItemEnabled(item, action->isEnabled()); - } else { - syncNSMenuItemEnabled(item, YES); - } + syncNSMenuItemEnabled(item, action->isEnabled()); + } else { + syncNSMenuItemEnabled(item, YES); + } + // We sneak in some extra code here to handle a menu problem: + // If there is no window on screen, we cannot set 'nil' as + // menu item target, because then cocoa will disable the item + // (guess it assumes that there will be no first responder to + // catch the trigger anyway?) OTOH, If we have a modal window, + // then setting the menu loader as target will make cocoa not + // deliver the trigger because the loader is then seen as modally + // shaddowed). So either way there are shortcomings. Instead, we + // decide the target as late as possible: + [item setTarget:modalWindowOnScreen ? nil : getMenuLoader()]; } else { syncNSMenuItemEnabled(item, NO); } @@ -1820,7 +1831,7 @@ void QMenuBarPrivate::macDestroyMenuBar() menubars()->remove(tlw); mac_menubar = 0; - if (qt_mac_current_menubar.qmenubar == q) { + if (!qt_mac_current_menubar.qmenubar || qt_mac_current_menubar.qmenubar == q) { #ifdef QT_MAC_USE_COCOA QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); [loader removeActionsFromAppMenu]; diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index a13a2fa..ef37fd1 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1931,9 +1931,9 @@ void QMenuBar::setNativeMenuBar(bool nativeMenuBar) d->macCreateMenuBar(parentWidget()); } macUpdateMenuBar(); - updateGeometry(); - setVisible(false); - setVisible(true); + updateGeometry(); + if (!d->nativeMenuBar && parentWidget()) + setVisible(true); #endif } } diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index ef9fac3..2734fba 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -944,8 +944,8 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() int vSliderLength = 0; if (!centerOnScroll && q->isVisible()) { QTextBlock block = doc->lastBlock(); - const int visible = static_cast<int>(viewport->rect().height() - margin - 1); - int y = 0; + const qreal visible = viewport->rect().height() - margin - 1; + qreal y = 0; int visibleFromBottom = 0; while (block.isValid()) { @@ -953,7 +953,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() block = block.previous(); continue; } - y += int(documentLayout->blockBoundingRect(block).height()); + y += documentLayout->blockBoundingRect(block).height(); QTextLayout *layout = block.layout(); int layoutLineCount = layout->lineCount(); @@ -962,7 +962,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() while (lineNumber < layoutLineCount) { QTextLine line = layout->lineAt(lineNumber); const QRectF lr = line.naturalTextRect(); - if (int(lr.top()) >= y - visible) + if (lr.top() >= y - visible) break; ++lineNumber; } diff --git a/src/gui/widgets/qscrollarea.cpp b/src/gui/widgets/qscrollarea.cpp index 6b81d9f..38e799e 100644 --- a/src/gui/widgets/qscrollarea.cpp +++ b/src/gui/widgets/qscrollarea.cpp @@ -482,14 +482,14 @@ void QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin, int yma d->hbar->setValue(focusRect.center().x() - d->viewport->width() / 2); else if (focusRect.right() > visibleRect.right()) d->hbar->setValue(focusRect.right() - d->viewport->width()); - else + else if (focusRect.left() < visibleRect.left()) d->hbar->setValue(focusRect.left()); if (focusRect.height() > visibleRect.height()) d->vbar->setValue(focusRect.center().y() - d->viewport->height() / 2); else if (focusRect.bottom() > visibleRect.bottom()) d->vbar->setValue(focusRect.bottom() - d->viewport->height()); - else + else if (focusRect.top() < visibleRect.top()) d->vbar->setValue(focusRect.top()); } diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index 7559311..d03a2f4 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -580,16 +580,10 @@ void QTabBarPrivate::layoutTab(int index) } } -void QTabBarPrivate::layoutWidgets(int index) +void QTabBarPrivate::layoutWidgets(int start) { Q_Q(QTabBar); - int start = 0; - int end = q->count(); - if (index != -1) { - start = qMax(index, 0); - end = qMin(end, start + 1); - } - for (int i = start; i < end; ++i) { + for (int i = start; i < q->count(); ++i) { layoutTab(i); } } @@ -1171,8 +1165,9 @@ void QTabBar::setCurrentIndex(int index) update(); d->makeVisible(index); d->tabList[index].lastTab = oldIndex; - d->layoutWidgets(oldIndex); - d->layoutWidgets(index); + if (oldIndex >= 0 && oldIndex < count()) + d->layoutTab(oldIndex); + d->layoutTab(index); #ifdef QT3_SUPPORT emit selected(index); #endif diff --git a/src/gui/widgets/qtabbar_p.h b/src/gui/widgets/qtabbar_p.h index 83636e6..37741f7 100644 --- a/src/gui/widgets/qtabbar_p.h +++ b/src/gui/widgets/qtabbar_p.h @@ -178,7 +178,7 @@ public: void refresh(); void layoutTabs(); - void layoutWidgets(int index = -1); + void layoutWidgets(int start = 0); void layoutTab(int index); void updateMacBorderMetrics(); void setupMovableTab(); |